diff --git a/.gitignore b/.gitignore index d06636f68..1da7b8b78 100644 --- a/.gitignore +++ b/.gitignore @@ -59,4 +59,6 @@ xcschememanagement.plist .DS_Store ._.* xcuserdata/ -DerivedData/ \ No newline at end of file +DerivedData/ +*.dll +src/libraylib.a \ No newline at end of file diff --git a/README.md b/README.md index d6f6d996a..f9a5a0e23 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ I've coded quite a lot in C# and XNA and I really love it (in fact, my students so, I decided to use C# language notation and XNA naming conventions. That way, students can jump from raylib to XNA, MonoGame or similar libs extremely easily. -raylib started as a weekend project and after three months of hard work, first version was published. +raylib started as a weekend project and after three months of hard work, raylib 1.0 was published on November 2013. Enjoy it. @@ -99,14 +99,37 @@ Most of the examples have been completely rewritten and +10 new examples have be Lots of code changes and lot of testing have concluded in this amazing new raylib 1.3. +notes on raylib 1.4 +------------------- + +On February 2016, after 4 months of raylib 1.3 release, it comes raylib 1.4. + +Lots of parts of the library have been reviewed to better accomodate to shaders systems and multiple new features have been added. + +SpriteFonts system has been improved, adding support for AngelCode fonts (.fnt) and TTF fonts (using stb_truetype). + +Finally, raycast system for 3D picking is working, including some ray collision-detection functions. + +A set of Image manipulation functions have been added to crop, resize, colorize, dither and even draw image-to-image or text-to-image. + +Two new functions added for persistent data storage. + +New [physac](https://github.com/raysan5/raylib/blob/develop/src/physac.h) physics module! + +Complete LUA scripting support to allow raylib usage from LUA and LUA scripts support within raylib. + +Up to 8 new examples have been added to show the new raylib features. + +Lots of code changes and lot of testing have concluded in this amazing new raylib 1.4. + features -------- * Written in plain C code (C99) * Uses C# PascalCase/camelCase notation * Hardware accelerated with OpenGL (1.1, 3.3 or ES2) - * Unique OpenGL abstraction layer: [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.c) - * Powerful fonts module with SpriteFonts support + * Unique OpenGL abstraction layer (usable as standalone module): [rlgl](https://github.com/raysan5/raylib/blob/master/src/rlgl.c) + * Powerful fonts module with multiple SpriteFonts formats support (XNA bitmap fonts, AngelCode fonts, TTF) * Outstanding texture formats support, including compressed formats * Basic 3d support for Shapes, Models, Billboards, Heightmaps and Cubicmaps * Powerful math module for Vector and Matrix operations: [raymath](https://github.com/raysan5/raylib/blob/master/src/raymath.c) @@ -145,126 +168,12 @@ Since raylib v1.1, you can download a Windows Installer package for easy install building source (generate libraylib.a) -------------------------------------- -**Building raylib sources on desktop platforms:** - -_Step 1:_ Using MinGW make tool, just navigate from command line to `raylib/src/` folder and type: - - mingw32-make PLATFORM=PLATFORM_DESKTOP - -NOTE: By default raylib compiles using OpenGL 1.1 to maximize compatibility; to use OpenGL 3.3 just type: - - mingw32-make PLATFORM=PLATFORM_DESKTOP GRAPHICS=GRAPHICS_API_OPENGL_33 - -**Building raylib sources on Raspberry Pi:** - -_Step 1._ Make sure you have installed in your Raspberry Pi OpenAL Soft library for audio: - - sudo apt-get install openal1 - -_Step 2._ Navigate from command line to `raylib/src/` folder and type: - - make - -**Building raylib sources for Android:** - -_Step 1._ Make sure you have installed Android SDK, Android NDK and Apache Ant tools: - -> Download and decompress on C: [Android SDK r23](http://dl.google.com/android/android-sdk_r23.0.2-windows.zip) - -> Download and decompress on C: [Android NDK r10b](http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86.zip) - -> Download and decompress on C: [Apache Ant 1.9.4](http://ftp.cixug.es/apache//ant/binaries/apache-ant-1.9.4-bin.zip) - -_Step 2._ Create the following environment variables with the correct paths: - - ANDROID_SDK_TOOLS = C:\android-sdk\platform-tools - ANDROID_NDK_ROOT = C:\android-ndk-r10b - ANT_HOME = C:\apache-ant-1.9.4 - -_Step 3._ Navigate from command line to folder `raylib/template_android/` and type: - - %ANDROID_NDK_ROOT%\ndk-build - -NOTE: libraylib.a will be generated in folder `raylib/src_android/obj/local/armeabi/`, it must be copied -to Android project; if using `raylib/template_android` project, copy it to `raylib/template_android/jni/libs/`. - -**Building raylib sources for Web (HTML5)** - -_Step 1._ Make sure you have installed emscripten SDK: - -> Download latest version from [here](http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html). I recommend downloading the [Portable Emscripten SDK for Windows](https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-1.25.0-portable-64bit.zip) and decompress it in `C:\emsdk-1.25.0` folder. After that, follow the portable version installation instructions. - -_Step 2._ Open `raylib/src/makefile` on Notepad++ and run the script named `raylib_makefile_emscripten` +Check raylib wiki page: [Building source](https://github.com/raysan5/raylib/wiki/Building-source) building examples ----------------- -**Building raylib examples on desktop platforms:** - -_Step 1:_ Using MinGW make tool, just navigate from command line to `raylib/examples/` folder and type: - - mingw32-make PLATFORM=PLATFORM_DESKTOP - -NOTE: Make sure the following libs (and their headers) are placed on their respectibe MinGW folders: - - libglfw3.a - GLFW3 (static version) - libglew32.a - GLEW, OpenGL extension loading, only required if using OpenGL 3.3+ or ES2 - libopenal32.a - OpenAL Soft, audio device management - -**Building raylib examples on Raspberry Pi:** - -_Step 1._ Make sure you have installed in your Raspberry Pi OpenAL Soft library for audio: - - sudo apt-get install openal1 - -_Step 2._ Navigate from command line to `raylib/examples/` folder and type: - - make - -**Building raylib examples for HTML5 (emscripten):** - -_Step 1._ Make sure you have installed emscripten SDK: - -> Download latest version from [here](http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html). I recommend downloading the [Portable Emscripten SDK for Windows](https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-1.25.0-portable-64bit.zip) and decompress it in `C:\emsdk-1.25.0` folder. After that, follow the portable version installation instructions. - -_Step 2._ Open `raylib/examples/makefile` on Notepad++ and run the script named `raylib_makefile_emscripten` - -NOTE: At this moment, raylib examples are not ready to directly compile for HTML5, code needs to be reorganized due to the way web browsers work. To see how code should be refactored to fit compilation for web, check [core_basic_window_web.c](https://github.com/raysan5/raylib/blob/master/examples/core_basic_window_web.c) example. - -**Building raylib project for Android (using template):** - -_Step 1._ Make sure you have installed Android SDK, Android NDK and Apache Ant tools: - -> Download and decompress on C: [Android SDK r23] (http://dl.google.com/android/android-sdk_r23.0.2-windows.zip) - -> Download and decompress on C: [Android NDK r10b] (http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86.zip) - -> Download and decompress on C: [Apache Ant 1.9.4] (http://ftp.cixug.es/apache//ant/binaries/apache-ant-1.9.4-bin.zip) - -_Step 2._ Create the following environment variables with the correct paths: - - ANDROID_SDK_TOOLS = C:\android-sdk\platform-tools - ANDROID_NDK_ROOT = C:\android-ndk-r10b - ANT_HOME = C:\apache-ant-1.9.4 - -_Step 3._ To compile project, navigate from command line to folder `raylib/template_android/` and type: - - %ANDROID_NDK_ROOT%\ndk-build - -_Step 4._ To generate APK, navigate to folder `raylib/template_android/` and type: - - %ANT_HOME%\bin\ant debug - -_Step 5:_ To install APK into connected device (previously intalled drivers and activated USB debug mode on device): - - %ANT_HOME%\bin\ant installd - -_Step 6:_ To view log output from device: - - %ANDROID_SDK_TOOLS%\adb logcat -c - %ANDROID_SDK_TOOLS%\adb -d logcat raylib:V *:S - -**If you have any doubt, [just let me know][raysan5].** +Check raylib wiki page: [Building examples](https://github.com/raysan5/raylib/wiki/Building-examples) contact ------- @@ -292,6 +201,9 @@ The following people have contributed in some way to make raylib project a reali - Daniel Moreno for testing and using raylib on a real product ([Koala Seasons](http://www.koalaseasons.com)) - Daniel Gomez for testing and using raylib on a real product ([Koala Seasons](http://www.koalaseasons.com)) - Sergio Martinez for helping on raygui development and tools development. + - Victor Fisac for developing physics raylib module (physac) and implementing light shaders and raycast system... and multiple tools and games. + - Albert Martos for helping on raygui and porting examples and game-templates to Android and HTML5. + - Ian Eito for helping on raygui and porting examples and game-templates to Android and HTML5. -[raysan5]: mailto:raysan@raysanweb.com "Ramon Santamaria - Ray San" +[raysan5]: mailto:raysan5@gmail.com "Ramon Santamaria - Ray San" diff --git a/ROADMAP.md b/ROADMAP.md index 324f4614e..e0d0c825b 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -8,14 +8,17 @@ Around the source code there are multiple TODO points with pending revisions/bug raylib v1.4 - - TTF fonts support (using stb_truetype) - - Raycast system for 3D picking (including collisions detection) + [DONE] TTF fonts support (using stb_truetype) + [DONE] Raycast system for 3D picking (including collisions detection) + [DONE] Floyd-Steinberg dithering on 16bit image format conversion + [DONE] Basic image manipulation functions (crop, resize, draw...) + [DONE] Storage load/save data functionality + [DONE] Physics module + [IN PROGRESS] LUA scripting support (wrapper to lua lib) - Remove GLEW dependency (use another solution... glad?) - - Floyd-Steinberg dithering on 16bit image format conversion - - Basic image manipulation functions (crop, resize, draw...) - Basic image procedural generation (spot, gradient, noise...) - Basic GPU stats sytem (memory, draws, time...) - - LUA scripting support (wrapper to lua lib) + Check [GITHUB ISSUES][issues] for further details on implementation status for this features! diff --git a/examples/audio_music_stream.c b/examples/audio_music_stream.c index e61d48397..8c668cce7 100644 --- a/examples/audio_music_stream.c +++ b/examples/audio_music_stream.c @@ -27,7 +27,7 @@ int main() PlayMusicStream("resources/audio/guitar_noodling.ogg"); // Play music stream int framesCounter = 0; - float timePlayed = 0; + float timePlayed = 0.0f; //float volume = 1.0; SetTargetFPS(60); // Set our game to run at 60 frames-per-second diff --git a/examples/audio_sound_loading.c b/examples/audio_sound_loading.c index 1376a27d2..8819aad11 100644 --- a/examples/audio_sound_loading.c +++ b/examples/audio_sound_loading.c @@ -26,6 +26,8 @@ int main() Sound fxWav = LoadSound("resources/audio/weird.wav"); // Load WAV audio file Sound fxOgg = LoadSound("resources/audio/tanatana.ogg"); // Load OGG audio file + + SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/core_3d_camera_first_person.c b/examples/core_3d_camera_first_person.c index aa947c3ce..8a092275d 100644 --- a/examples/core_3d_camera_first_person.c +++ b/examples/core_3d_camera_first_person.c @@ -23,7 +23,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera first person"); // Define the camera to look into our 3d world - Camera camera = {{ 0.0, 10.0, 10.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }}; + Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; // Generates some random columns float heights[MAX_COLUMNS]; @@ -37,7 +37,7 @@ int main() colors[i] = (Color){ GetRandomValue(20, 255), GetRandomValue(10, 55), 30, 255 }; } - Vector3 playerPosition = { 4, 2, 4 }; // Define player position + Vector3 playerPosition = { 4.0f, 2.0f, 4.0f }; // Define player position SetCameraMode(CAMERA_FIRST_PERSON); // Set a first person camera mode @@ -60,16 +60,16 @@ int main() Begin3dMode(camera); - DrawPlane((Vector3){ 0, 0, 0 }, (Vector2){ 32, 32 }, LIGHTGRAY); // Draw ground - DrawCube((Vector3){ -16, 2.5, 0 }, 1, 5, 32, BLUE); // Draw a blue wall - DrawCube((Vector3){ 16, 2.5, 0 }, 1, 5, 32, LIME); // Draw a green wall - DrawCube((Vector3){ 0, 2.5, 16 }, 32, 5, 1, GOLD); // Draw a yellow wall + DrawPlane((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector2){ 32.0f, 32.0f }, LIGHTGRAY); // Draw ground + DrawCube((Vector3){ -16.0f, 2.5f, 0.0f }, 1.0f, 5.0f, 32.0f, BLUE); // Draw a blue wall + DrawCube((Vector3){ 16.0f, 2.5f, 0.0f }, 1.0f, 5.0f, 32.0f, LIME); // Draw a green wall + DrawCube((Vector3){ 0.0f, 2.5f, 16.0f }, 32.0f, 5.0f, 1.0f, GOLD); // Draw a yellow wall // Draw some cubes around for (int i = 0; i < MAX_COLUMNS; i++) { - DrawCube(positions[i], 2, heights[i], 2, colors[i]); - DrawCubeWires(positions[i], 2, heights[i], 2, MAROON); + DrawCube(positions[i], 2.0f, heights[i], 2.0f, colors[i]); + DrawCubeWires(positions[i], 2.0f, heights[i], 2.0f, MAROON); } End3dMode(); diff --git a/examples/core_3d_camera_free.c b/examples/core_3d_camera_free.c index be44ed2a8..df1b480c9 100644 --- a/examples/core_3d_camera_free.c +++ b/examples/core_3d_camera_free.c @@ -21,9 +21,12 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free"); // Define the camera to look into our 3d world - Camera camera = {{ 0.0, 10.0, 10.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }}; + Camera camera; + camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; + camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; - Vector3 cubePosition = { 0.0, 0.0, 0.0 }; + Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; SetCameraMode(CAMERA_FREE); // Set a free camera mode SetCameraPosition(camera.position); // Set internal camera position to match our camera position @@ -48,10 +51,10 @@ int main() Begin3dMode(camera); - DrawCube(cubePosition, 2, 2, 2, RED); - DrawCubeWires(cubePosition, 2, 2, 2, MAROON); + DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); + DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); - DrawGrid(10.0, 1.0); + DrawGrid(10, 1.0f); End3dMode(); diff --git a/examples/core_3d_mode.c b/examples/core_3d_mode.c index c38da256b..40415feac 100644 --- a/examples/core_3d_mode.c +++ b/examples/core_3d_mode.c @@ -21,11 +21,14 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d mode"); // Define the camera to look into our 3d world - Camera camera = {{ 0.0, 10.0, 10.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }}; + Camera camera; + camera.position = (Vector3){ 0.0f, 10.0f, 10.0f }; + camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; - Vector3 cubePosition = { 0.0, 0.0, 0.0 }; + Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; - //SetTargetFPS(60); // Set our game to run at 60 frames-per-second, but not now... + SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- // Main game loop @@ -40,14 +43,14 @@ int main() //---------------------------------------------------------------------------------- BeginDrawing(); - ClearBackground(WHITE); + ClearBackground(RAYWHITE); Begin3dMode(camera); - DrawCube(cubePosition, 2, 2, 2, RED); - DrawCubeWires(cubePosition, 2, 2, 2, MAROON); + DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); + DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); - DrawGrid(10.0, 1.0); + DrawGrid(10, 1.0f); End3dMode(); diff --git a/examples/core_3d_picking.c b/examples/core_3d_picking.c index 2fc05e818..9a6cc1383 100644 --- a/examples/core_3d_picking.c +++ b/examples/core_3d_picking.c @@ -21,12 +21,15 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d picking"); // Define the camera to look into our 3d world - Camera camera = {{ 0.0, 10.0, 10.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }}; + Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; - Vector3 cubePosition = { 0.0, 1.0, 0.0 }; + Vector3 cubePosition = { 0.0f, 1.0f, 0.0f }; + Vector3 cubeSize = { 2.0f, 2.0f, 2.0f }; Ray ray; // Picking line ray + bool collision = false; + SetCameraMode(CAMERA_FREE); // Set a free camera mode SetCameraPosition(camera.position); // Set internal camera position to match our camera position @@ -45,7 +48,10 @@ int main() // NOTE: This function is NOT WORKING properly! ray = GetMouseRay(GetMousePosition(), camera); - // TODO: Check collision between ray and box + // Check collision between ray and box + collision = CheckCollisionRayBox(ray, + (Vector3){ cubePosition.x - cubeSize.x/2, cubePosition.y - cubeSize.y/2, cubePosition.z - cubeSize.z/2 }, + (Vector3){ cubePosition.x + cubeSize.x/2, cubePosition.y + cubeSize.y/2, cubePosition.z + cubeSize.z/2 }); } //---------------------------------------------------------------------------------- @@ -57,16 +63,18 @@ int main() Begin3dMode(camera); - DrawCube(cubePosition, 2, 2, 2, GRAY); - DrawCubeWires(cubePosition, 2, 2, 2, DARKGRAY); - - DrawGrid(10.0, 1.0); + DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, GRAY); + DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, DARKGRAY); DrawRay(ray, MAROON); + + DrawGrid(10, 1.0f); End3dMode(); DrawText("Try selecting the box with mouse!", 240, 10, 20, GRAY); + + if(collision) DrawText("BOX SELECTED", (screenWidth - MeasureText("BOX SELECTED", 30)) / 2, screenHeight * 0.1f, 30, GREEN); DrawFPS(10, 10); diff --git a/examples/core_basic_window.c b/examples/core_basic_window.c index b039e53f5..fb83400aa 100644 --- a/examples/core_basic_window.c +++ b/examples/core_basic_window.c @@ -29,6 +29,8 @@ int main() int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); + + SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/core_input_gamepad.c b/examples/core_input_gamepad.c index 64be4cd84..1de2d424e 100644 --- a/examples/core_input_gamepad.c +++ b/examples/core_input_gamepad.c @@ -23,8 +23,8 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - gamepad input"); - Vector2 ballPosition = { screenWidth/2, screenHeight/2 }; - Vector2 gamepadMovement = { 0, 0 }; + Vector2 ballPosition = { (float)screenWidth/2, (float)screenHeight/2 }; + Vector2 gamepadMovement = { 0.0f, 0.0f }; SetTargetFPS(60); // Set target frames-per-second //-------------------------------------------------------------------------------------- @@ -43,8 +43,8 @@ int main() if (IsGamepadButtonPressed(GAMEPAD_PLAYER1, GAMEPAD_BUTTON_A)) { - ballPosition.x = screenWidth/2; - ballPosition.y = screenHeight/2; + ballPosition.x = (float)screenWidth/2; + ballPosition.y = (float)screenHeight/2; } } //---------------------------------------------------------------------------------- diff --git a/examples/core_input_keys.c b/examples/core_input_keys.c index 99d5e5160..b2305246e 100644 --- a/examples/core_input_keys.c +++ b/examples/core_input_keys.c @@ -20,7 +20,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - keyboard input"); - Vector2 ballPosition = { screenWidth/2, screenHeight/2 }; + Vector2 ballPosition = { (float)screenWidth/2, (float)screenHeight/2 }; SetTargetFPS(60); // Set target frames-per-second //-------------------------------------------------------------------------------------- @@ -30,10 +30,10 @@ int main() { // Update //---------------------------------------------------------------------------------- - if (IsKeyDown(KEY_RIGHT)) ballPosition.x += 0.8; - if (IsKeyDown(KEY_LEFT)) ballPosition.x -= 0.8; - if (IsKeyDown(KEY_UP)) ballPosition.y -= 0.8; - if (IsKeyDown(KEY_DOWN)) ballPosition.y += 0.8; + if (IsKeyDown(KEY_RIGHT)) ballPosition.x += 0.8f; + if (IsKeyDown(KEY_LEFT)) ballPosition.x -= 0.8f; + if (IsKeyDown(KEY_UP)) ballPosition.y -= 0.8f; + if (IsKeyDown(KEY_DOWN)) ballPosition.y += 0.8f; //---------------------------------------------------------------------------------- // Draw diff --git a/examples/core_input_mouse.c b/examples/core_input_mouse.c index c64b421e3..358b5fd68 100644 --- a/examples/core_input_mouse.c +++ b/examples/core_input_mouse.c @@ -20,8 +20,9 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - mouse input"); - int mouseX, mouseY; - Vector2 ballPosition = { -100.0, -100.0 }; + Vector2 ballPosition = { -100.0f, -100.0f }; + + SetTargetFPS(60); //--------------------------------------------------------------------------------------- // Main game loop @@ -31,11 +32,7 @@ int main() //---------------------------------------------------------------------------------- if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { - mouseX = GetMouseX(); - mouseY = GetMouseY(); - - ballPosition.x = (float)mouseX; - ballPosition.y = (float)mouseY; + ballPosition = GetMousePosition(); } //---------------------------------------------------------------------------------- diff --git a/examples/core_random_values.c b/examples/core_random_values.c index 98e0e91ef..06e550dd3 100644 --- a/examples/core_random_values.c +++ b/examples/core_random_values.c @@ -22,7 +22,7 @@ int main() int framesCounter = 0; // Variable used to count frames - int randValue = GetRandomValue(-8,5); // Get a random integer number between -8 and 5 (both included) + int randValue = GetRandomValue(-8, 5); // Get a random integer number between -8 and 5 (both included) SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -37,7 +37,7 @@ int main() // Every two seconds (120 frames) a new random value is generated if (((framesCounter/120)%2) == 1) { - randValue = GetRandomValue(-8,5); + randValue = GetRandomValue(-8, 5); framesCounter = 0; } //---------------------------------------------------------------------------------- diff --git a/examples/core_storage_values.c b/examples/core_storage_values.c new file mode 100644 index 000000000..3190d0a08 --- /dev/null +++ b/examples/core_storage_values.c @@ -0,0 +1,85 @@ +/******************************************************************************************* +* +* raylib [core] example - Storage save/load values +* +* This example has been created using raylib 1.4 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +// NOTE: Storage positions must start with 0, directly related to file memory layout +typedef enum { STORAGE_SCORE = 0, STORAGE_HISCORE } StorageData; + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - storage save/load values"); + + int score = 0; + int hiscore = 0; + + int framesCounter = 0; + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + if (IsKeyPressed(KEY_R)) + { + score = GetRandomValue(1000, 2000); + hiscore = GetRandomValue(2000, 4000); + } + + if (IsKeyPressed(KEY_ENTER)) + { + StorageSaveValue(STORAGE_SCORE, score); + StorageSaveValue(STORAGE_HISCORE, hiscore); + } + else if (IsKeyPressed(KEY_SPACE)) + { + // NOTE: If requested position could not be found, value 0 is returned + score = StorageLoadValue(STORAGE_SCORE); + hiscore = StorageLoadValue(STORAGE_HISCORE); + } + + framesCounter++; + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + DrawText(FormatText("SCORE: %i", score), 280, 130, 40, MAROON); + DrawText(FormatText("HI-SCORE: %i", hiscore), 210, 200, 50, BLACK); + + DrawText(FormatText("frames: %i", framesCounter), 10, 10, 20, LIME); + + DrawText("Press R to generate random numbers", 220, 40, 20, LIGHTGRAY); + DrawText("Press ENTER to SAVE values", 250, 310, 20, LIGHTGRAY); + DrawText("Press SPACE to LOAD values", 252, 350, 20, LIGHTGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/core_storage_values.png b/examples/core_storage_values.png new file mode 100644 index 000000000..6cfd552dd Binary files /dev/null and b/examples/core_storage_values.png differ diff --git a/examples/core_world_screen.c b/examples/core_world_screen.c new file mode 100644 index 000000000..b70b40dd3 --- /dev/null +++ b/examples/core_world_screen.c @@ -0,0 +1,77 @@ +/******************************************************************************************* +* +* raylib [core] example - World to screen +* +* This example has been created using raylib 1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [core] example - 3d camera free"); + + // Define the camera to look into our 3d world + Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + + Vector3 cubePosition = { 0.0f, 0.0f, 0.0f }; + + Vector2 cubeScreenPosition; + + SetCameraMode(CAMERA_FREE); // Set a free camera mode + SetCameraPosition(camera.position); // Set internal camera position to match our camera position + SetCameraTarget(camera.target); // Set internal camera target to match our camera target + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera); // Update internal camera and our camera + + // Calculate cube screen space position (with a little offset to be in top) + cubeScreenPosition = WorldToScreen((Vector3){cubePosition.x, cubePosition.y + 2.5f, cubePosition.z}, camera); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + Begin3dMode(camera); + + DrawCube(cubePosition, 2.0f, 2.0f, 2.0f, RED); + DrawCubeWires(cubePosition, 2.0f, 2.0f, 2.0f, MAROON); + + DrawGrid(10, 1.0f); + + End3dMode(); + + DrawText("Enemy: 100 / 100", cubeScreenPosition.x - MeasureText("Enemy: 100 / 100", 20) / 2, cubeScreenPosition.y, 20, BLACK); + DrawText("Text is always on top of the cube", (screenWidth - MeasureText("Text is always on top of the cube", 20)) / 2, 25, 20, GRAY); + + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/lighting_blinn_phong.png b/examples/lighting_blinn_phong.png new file mode 100644 index 000000000..4a3c5d18e Binary files /dev/null and b/examples/lighting_blinn_phong.png differ diff --git a/examples/makefile b/examples/makefile index dac378cef..04dc77561 100644 --- a/examples/makefile +++ b/examples/makefile @@ -113,8 +113,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),LINUX) # libraries for Debian GNU/Linux desktop compiling # requires the following packages: - # libopenal-dev libglew-dev libegl1-mesa-dev - LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -pthread + # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev + LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread + # on XWindow could require also below libraries, just uncomment + #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor else ifeq ($(PLATFORM_OS),OSX) # libraries for OS X 10.9 desktop compiling @@ -134,6 +136,7 @@ ifeq ($(PLATFORM),PLATFORM_RPI) LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal endif ifeq ($(PLATFORM),PLATFORM_WEB) + # just adjust the correct path to libraylib.bc LIBS = ../src/libraylib.bc endif diff --git a/examples/models_billboard.c b/examples/models_billboard.c index 05d836ca3..bac42d356 100644 --- a/examples/models_billboard.c +++ b/examples/models_billboard.c @@ -21,10 +21,10 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - drawing billboards"); // Define the camera to look into our 3d world - Camera camera = {{ 5.0, 4.0, 5.0 }, { 0.0, 2.0, 0.0 }, { 0.0, 1.0, 0.0 }}; + Camera camera = {{ 5.0f, 4.0f, 5.0f }, { 0.0f, 2.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; Texture2D bill = LoadTexture("resources/billboard.png"); // Our texture billboard - Vector3 billPosition = { 0.0, 2.0, 0.0 }; // Position where draw billboard + Vector3 billPosition = { 0.0f, 2.0f, 0.0f }; // Position where draw billboard SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode SetCameraPosition(camera.position); // Set internal camera position to match our camera position @@ -48,10 +48,10 @@ int main() ClearBackground(RAYWHITE); Begin3dMode(camera); - + DrawBillboard(camera, bill, billPosition, 2.0f, WHITE); - - DrawGrid(10.0, 1.0); // Draw a grid + + DrawGrid(10, 1.0f); // Draw a grid End3dMode(); diff --git a/examples/models_box_collisions.c b/examples/models_box_collisions.c index 18fca0912..3751041f0 100644 --- a/examples/models_box_collisions.c +++ b/examples/models_box_collisions.c @@ -21,16 +21,16 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - box collisions"); // Define the camera to look into our 3d world - Camera camera = {{ 0.0, 10.0, 10.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }}; + Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; - Vector3 playerPosition = { 0, 1, 2 }; - Vector3 playerSize = { 1, 2, 1 }; + Vector3 playerPosition = { 0.0f, 1.0f, 2.0f }; + Vector3 playerSize = { 1.0f, 2.0f, 1.0f }; Color playerColor = GREEN; - Vector3 enemyBoxPos = { -4, 1, 0 }; - Vector3 enemyBoxSize = { 2, 2, 2 }; + Vector3 enemyBoxPos = { -4.0f, 1.0f, 0.0f }; + Vector3 enemyBoxSize = { 2.0f, 2.0f, 2.0f }; - Vector3 enemySpherePos = { 4, 0, 0 }; + Vector3 enemySpherePos = { 4.0f, 0.0f, 0.0f }; float enemySphereSize = 1.5f; bool collision = false; @@ -98,7 +98,7 @@ int main() // Draw player DrawCubeV(playerPosition, playerSize, playerColor); - DrawGrid(10.0, 1.0); // Draw a grid + DrawGrid(10, 1.0f); // Draw a grid End3dMode(); diff --git a/examples/models_cubicmap.c b/examples/models_cubicmap.c index 98fc54afe..e2a902ef7 100644 --- a/examples/models_cubicmap.c +++ b/examples/models_cubicmap.c @@ -21,7 +21,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - cubesmap loading and drawing"); // Define the camera to look into our 3d world - Camera camera = {{ 16.0, 14.0, 16.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }}; + Camera camera = {{ 16.0f, 14.0f, 16.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; Image image = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM) Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM) @@ -31,7 +31,7 @@ int main() Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture SetModelTexture(&map, texture); // Bind texture to map model - Vector3 mapPosition = { -16, 0.0, -8 }; // Set model position + Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position UnloadImage(image); // Unload cubesmap image from RAM, already uploaded to VRAM diff --git a/examples/models_geometric_shapes.c b/examples/models_geometric_shapes.c index e2d41dcd5..9ea5b4232 100644 --- a/examples/models_geometric_shapes.c +++ b/examples/models_geometric_shapes.c @@ -21,7 +21,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes"); // Define the camera to look into our 3d world - Camera camera = {{ 0.0, 10.0, 10.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }}; + Camera camera = {{ 0.0f, 10.0f, 10.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -42,21 +42,21 @@ int main() Begin3dMode(camera); - DrawCube((Vector3){-4, 0, 2}, 2, 5, 2, RED); - DrawCubeWires((Vector3){-4, 0, 2}, 2, 5, 2, GOLD); - DrawCubeWires((Vector3){-4, 0, -2}, 3, 6, 2, MAROON); + DrawCube((Vector3){-4.0f, 0.0f, 2.0f}, 2.0f, 5.0f, 2.0f, RED); + DrawCubeWires((Vector3){-4.0f, 0.0f, 2.0f}, 2.0f, 5.0f, 2.0f, GOLD); + DrawCubeWires((Vector3){-4.0f, 0.0f, -2.0f}, 3.0f, 6.0f, 2.0f, MAROON); - DrawSphere((Vector3){-1, 0, -2}, 1, GREEN); - DrawSphereWires((Vector3){1, 0, 2}, 2, 16, 16, LIME); + DrawSphere((Vector3){-1.0f, 0.0f, -2.0f}, 1.0f, GREEN); + DrawSphereWires((Vector3){1.0f, 0.0f, 2.0f}, 2.0f, 16, 16, LIME); - DrawCylinder((Vector3){4, 0, -2}, 1, 2, 3, 4, SKYBLUE); - DrawCylinderWires((Vector3){4, 0, -2}, 1, 2, 3, 4, DARKBLUE); - DrawCylinderWires((Vector3){4.5, -1, 2}, 1, 1, 2, 6, BROWN); + DrawCylinder((Vector3){4.0f, 0.0f, -2.0f}, 1.0f, 2.0f, 3.0f, 4, SKYBLUE); + DrawCylinderWires((Vector3){4.0f, 0.0f, -2.0f}, 1.0f, 2.0f, 3.0f, 4, DARKBLUE); + DrawCylinderWires((Vector3){4.5f, -1.0f, 2.0f}, 1.0f, 1.0f, 2.0f, 6, BROWN); - DrawCylinder((Vector3){1, 0, -4}, 0, 1.5, 3, 8, GOLD); - DrawCylinderWires((Vector3){1, 0, -4}, 0, 1.5, 3, 8, PINK); + DrawCylinder((Vector3){1.0f, 0.0f, -4.0f}, 0.0f, 1.5f, 3.0f, 8, GOLD); + DrawCylinderWires((Vector3){1.0f, 0.0f, -4.0f}, 0.0f, 1.5f, 3.0f, 8, PINK); - DrawGrid(10.0, 1.0); // Draw a grid + DrawGrid(10, 1.0f); // Draw a grid End3dMode(); diff --git a/examples/models_heightmap.c b/examples/models_heightmap.c index fec3f5e63..ac578c614 100644 --- a/examples/models_heightmap.c +++ b/examples/models_heightmap.c @@ -21,13 +21,13 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - heightmap loading and drawing"); // Define our custom camera to look into our 3d world - Camera camera = {{ 24.0, 18.0, 24.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }}; + Camera camera = {{ 24.0f, 18.0f, 24.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; Image image = LoadImage("resources/heightmap.png"); // Load heightmap image (RAM) Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM) Model map = LoadHeightmap(image, 32); // Load heightmap model SetModelTexture(&map, texture); // Bind texture to model - Vector3 mapPosition = { -16, 0.0, -16 }; // Set model position (depends on model scaling!) + Vector3 mapPosition = { -16.0f, 0.0f, -16.0f }; // Set model position (depends on model scaling!) UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM diff --git a/examples/models_obj_loading.c b/examples/models_obj_loading.c index dc302f99b..41f4569ad 100644 --- a/examples/models_obj_loading.c +++ b/examples/models_obj_loading.c @@ -21,12 +21,12 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [models] example - obj model loading"); // Define the camera to look into our 3d world - Camera camera = {{ 3.0, 3.0, 3.0 }, { 0.0, 1.5, 0.0 }, { 0.0, 1.0, 0.0 }}; + Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture - SetModelTexture(&dwarf, texture); // Bind texture to model - Vector3 position = { 0.0, 0.0, 0.0 }; // Set model position + SetModelTexture(&dwarf, texture); // Bind texture to model + Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -49,7 +49,7 @@ int main() DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture - DrawGrid(10.0, 1.0); // Draw a grid + DrawGrid(10, 1.0f); // Draw a grid DrawGizmo(position); // Draw gizmo diff --git a/examples/physics_basic_rigidbody.c b/examples/physics_basic_rigidbody.c new file mode 100644 index 000000000..17d6564fa --- /dev/null +++ b/examples/physics_basic_rigidbody.c @@ -0,0 +1,144 @@ +/******************************************************************************************* +* +* raylib [physac] physics example - Basic rigidbody +* +* Welcome to raylib! +* +* To test examples, just press F6 and execute raylib_compile_execute script +* Note that compiled executable is placed in the same folder as .c file +* +* You can find all basic examples on C:\raylib\raylib\examples folder or +* raylib official webpage: www.raylib.com +* +* Enjoy using raylib. :) +* +* This example has been created using raylib 1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#define OBJECT_SIZE 50 +#define PLAYER_INDEX 0 + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [physics] example - basic rigidbody"); + SetTargetFPS(60); // Enable v-sync + InitPhysics(); // Initialize internal physics values (max rigidbodies/colliders available: 1024) + + // Physics initialization + Physics worldPhysics = {true, false, (Vector2){0, -9.81f}}; + + // Set internal physics settings + SetPhysics(worldPhysics); + + // Object initialization + Transform player = (Transform){(Vector2){(screenWidth - OBJECT_SIZE) / 2, (screenHeight - OBJECT_SIZE) / 2}, 0.0f, (Vector2){OBJECT_SIZE, OBJECT_SIZE}}; + AddCollider(PLAYER_INDEX, (Collider){true, RectangleCollider, (Rectangle){player.position.x, player.position.y, player.scale.x, player.scale.y}, 0}); + AddRigidbody(PLAYER_INDEX, (Rigidbody){true, 1.0f, (Vector2){0, 0}, (Vector2){0, 0}, false, false, true, 0.5f, 1.0f}); + + // Floor initialization + // NOTE: floor doesn't need a rigidbody because it's a static physic object, just a collider to collide with other dynamic colliders (with rigidbody) + Transform floor = (Transform){(Vector2){0, screenHeight * 0.8f}, 0.0f, (Vector2){screenWidth, screenHeight * 0.2f}}; + AddCollider(PLAYER_INDEX + 1, (Collider){true, RectangleCollider, (Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, 0}); + + // Object properties initialization + float moveSpeed = 6.0f; + float jumpForce = 4.5f; + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + + // Update object physics + // NOTE: all physics detections and reactions are calculated in ApplyPhysics() function (You will live happier :D) + ApplyPhysics(PLAYER_INDEX, &player.position); + + // Check jump button input + if(IsKeyDown(KEY_SPACE) && GetRigidbody(PLAYER_INDEX).isGrounded) + { + // Reset object Y velocity to avoid double jumping cases but keep the same X velocity that it already has + SetRigidbodyVelocity(PLAYER_INDEX, (Vector2){GetRigidbody(PLAYER_INDEX).velocity.x, 0}); + + // Add jumping force in Y axis + AddRigidbodyForce(PLAYER_INDEX, (Vector2){0, jumpForce}); + } + + // Check movement buttons input + if(IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) + { + // Set rigidbody velocity in X based on moveSpeed value and apply the same Y velocity that it already has + SetRigidbodyVelocity(PLAYER_INDEX, (Vector2){moveSpeed, GetRigidbody(PLAYER_INDEX).velocity.y}); + } + else if(IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) + { + // Set rigidbody velocity in X based on moveSpeed negative value and apply the same Y velocity that it already has + SetRigidbodyVelocity(PLAYER_INDEX, (Vector2){-moveSpeed, GetRigidbody(PLAYER_INDEX).velocity.y}); + } + + // Check debug mode toggle button input + if(IsKeyPressed(KEY_P)) + { + // Update program physics value + worldPhysics.debug = !worldPhysics.debug; + + // Update internal physics value + SetPhysics(worldPhysics); + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + // Draw information + DrawText("Use LEFT / RIGHT to MOVE and SPACE to JUMP", (screenWidth - MeasureText("Use LEFT / RIGHT to MOVE and SPACE to JUMP", 20)) / 2, screenHeight * 0.20f, 20, LIGHTGRAY); + DrawText("Use P to switch DEBUG MODE", (screenWidth - MeasureText("Use P to switch DEBUG MODE", 20)) / 2, screenHeight * 0.3f, 20, LIGHTGRAY); + + // Check if debug mode is enabled + if(worldPhysics.debug) + { + // Draw every internal physics stored collider if it is active + for(int i = 0; i < 2; i++) + { + if(GetCollider(i).enabled) + { + DrawRectangleLines(GetCollider(i).bounds.x, GetCollider(i).bounds.y, GetCollider(i).bounds.width, GetCollider(i).bounds.height, GREEN); + } + } + + } + else + { + // Draw player + DrawRectangleRec((Rectangle){player.position.x, player.position.y, player.scale.x, player.scale.y}, GRAY); + + // Draw floor + DrawRectangleRec((Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, BLACK); + } + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} \ No newline at end of file diff --git a/examples/physics_basic_rigidbody.png b/examples/physics_basic_rigidbody.png new file mode 100644 index 000000000..3d691637b Binary files /dev/null and b/examples/physics_basic_rigidbody.png differ diff --git a/examples/physics_rigidbody_force.c b/examples/physics_rigidbody_force.c new file mode 100644 index 000000000..726e7c671 --- /dev/null +++ b/examples/physics_rigidbody_force.c @@ -0,0 +1,141 @@ +/******************************************************************************************* +* +* raylib [physac] physics example - Rigidbody forces +* +* This example has been created using raylib 1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#define MAX_OBJECTS 5 +#define OBJECTS_OFFSET 150 + +#define FORCE_INTENSITY 250.0f // Customize by user +#define FORCE_RADIUS 100 // Customize by user + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + int screenWidth = 800; + int screenHeight = 450; + + InitWindow(screenWidth, screenHeight, "raylib [physics] example - rigidbodies forces"); + SetTargetFPS(60); // Enable v-sync + InitPhysics(); // Initialize internal physics values (max rigidbodies/colliders available: 1024) + + // Physics initialization + Physics worldPhysics = {true, false, (Vector2){0, -9.81f}}; + + // Set internal physics settings + SetPhysics(worldPhysics); + + // Objects initialization + Transform objects[MAX_OBJECTS]; + for(int i = 0; i < MAX_OBJECTS; i++) + { + objects[i] = (Transform){(Vector2){75 + OBJECTS_OFFSET * i, (screenHeight - 50) / 2}, 0.0f, (Vector2){50, 50}}; + AddCollider(i, (Collider){true, RectangleCollider, (Rectangle){objects[i].position.x, objects[i].position.y, objects[i].scale.x, objects[i].scale.y}, 0}); + AddRigidbody(i, (Rigidbody){true, 1.0f, (Vector2){0, 0}, (Vector2){0, 0}, false, false, true, 0.5f, 0.5f}); + } + + // Floor initialization + // NOTE: floor doesn't need a rigidbody because it's a static physic object, just a collider to collide with other dynamic colliders (with rigidbody) + Transform floor = (Transform){(Vector2){0, screenHeight * 0.8f}, 0.0f, (Vector2){screenWidth, screenHeight * 0.2f}}; + AddCollider(MAX_OBJECTS, (Collider){true, RectangleCollider, (Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, 0}); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + + // Update object physics + // NOTE: all physics detections and reactions are calculated in ApplyPhysics() function (You will live happier :D) + for(int i = 0; i < MAX_OBJECTS; i++) + { + ApplyPhysics(i, &objects[i].position); + } + + // Check foce button input + if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + AddForceAtPosition(GetMousePosition(), FORCE_INTENSITY, FORCE_RADIUS); + } + + // Check debug mode toggle button input + if(IsKeyPressed(KEY_P)) + { + // Update program physics value + worldPhysics.debug = !worldPhysics.debug; + + // Update internal physics value + SetPhysics(worldPhysics); + } + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + // Check if debug mode is enabled + if(worldPhysics.debug) + { + // Draw every internal physics stored collider if it is active (floor included) + for(int i = 0; i < MAX_OBJECTS + 1; i++) + { + if(GetCollider(i).enabled) + { + // Draw collider bounds + DrawRectangleLines(GetCollider(i).bounds.x, GetCollider(i).bounds.y, GetCollider(i).bounds.width, GetCollider(i).bounds.height, GREEN); + + // Check if current collider is not floor + if(i < MAX_OBJECTS) + { + // Draw lines between mouse position and objects if they are in force range + if(CheckCollisionPointCircle(GetMousePosition(), (Vector2){GetCollider(i).bounds.x + GetCollider(i).bounds.width / 2, GetCollider(i).bounds.y + GetCollider(i).bounds.height / 2}, FORCE_RADIUS)) + { + DrawLineV(GetMousePosition(), (Vector2){GetCollider(i).bounds.x + GetCollider(i).bounds.width / 2, GetCollider(i).bounds.y + GetCollider(i).bounds.height / 2}, RED); + } + } + } + } + + // Draw radius circle + DrawCircleLines(GetMousePosition().x, GetMousePosition().y, FORCE_RADIUS, RED); + } + else + { + // Draw objects + for(int i = 0; i < MAX_OBJECTS; i++) + { + DrawRectangleRec((Rectangle){objects[i].position.x, objects[i].position.y, objects[i].scale.x, objects[i].scale.y}, GRAY); + } + + // Draw floor + DrawRectangleRec((Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, BLACK); + } + + + // Draw help messages + DrawText("Use LEFT MOUSE BUTTON to create a force in mouse position", (screenWidth - MeasureText("Use LEFT MOUSE BUTTON to create a force in mouse position", 20)) / 2, screenHeight * 0.20f, 20, LIGHTGRAY); + DrawText("Use P to switch DEBUG MODE", (screenWidth - MeasureText("Use P to switch DEBUG MODE", 20)) / 2, screenHeight * 0.3f, 20, LIGHTGRAY); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/physics_rigidbody_force.png b/examples/physics_rigidbody_force.png new file mode 100644 index 000000000..48afa91b0 Binary files /dev/null and b/examples/physics_rigidbody_force.png differ diff --git a/examples/resources/model/shapes.obj b/examples/resources/model/shapes.obj new file mode 100644 index 000000000..80205310a --- /dev/null +++ b/examples/resources/model/shapes.obj @@ -0,0 +1,6433 @@ +# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware +# File Created: 17.12.2015 16:35:37 + +# +# object Box001 +# + +v -29.206673 -11.629548 3.941377 +v -6.725425 -11.629548 -1.993001 +v -35.141048 -11.629548 -18.539871 +v -12.659802 -11.629548 -24.474247 +v -29.206673 11.621758 3.941377 +v -6.725425 11.621758 -1.993001 +v -35.141048 11.621758 -18.539871 +v -12.659802 11.621758 -24.474247 +v 9.611540 16.536621 -13.505542 +v 9.611540 16.218872 -16.731674 +v 8.982153 16.218872 -16.669687 +v 8.376951 16.218872 -16.486101 +v 7.819195 16.218872 -16.187973 +v 7.330318 16.218872 -15.786763 +v 6.929106 16.218872 -15.297886 +v 6.630980 16.218872 -14.740129 +v 6.447395 16.218872 -14.134929 +v 6.385406 16.218872 -13.505540 +v 6.447397 16.218872 -12.876153 +v 6.630980 16.218872 -12.270952 +v 6.929110 16.218872 -11.713196 +v 7.330320 16.218872 -11.224319 +v 7.819201 16.218872 -10.823108 +v 8.376955 16.218872 -10.524981 +v 8.982157 16.218872 -10.341396 +v 9.611546 16.218872 -10.279408 +v 10.240931 16.218872 -10.341396 +v 10.846130 16.218872 -10.524984 +v 11.403891 16.218872 -10.823111 +v 11.892763 16.218872 -11.224323 +v 12.293978 16.218872 -11.713202 +v 12.592104 16.218872 -12.270958 +v 12.775690 16.218872 -12.876159 +v 12.837675 16.218872 -13.505547 +v 12.775686 16.218872 -14.134933 +v 12.592100 16.218872 -14.740135 +v 12.293974 16.218872 -15.297892 +v 11.892759 16.218872 -15.786766 +v 11.403879 16.218872 -16.187979 +v 10.846123 16.218872 -16.486103 +v 10.240921 16.218872 -16.669687 +v 9.611540 15.277844 -19.833832 +v 8.376951 15.277844 -19.712234 +v 7.189810 15.277844 -19.352119 +v 6.095730 15.277844 -18.767323 +v 5.136763 15.277844 -17.980320 +v 4.349756 15.277844 -17.021351 +v 3.764961 15.277844 -15.927273 +v 3.404844 15.277844 -14.740128 +v 3.283251 15.277844 -13.505539 +v 3.404846 15.277844 -12.270950 +v 3.764965 15.277844 -11.083807 +v 4.349760 15.277844 -9.989729 +v 5.136766 15.277844 -9.030762 +v 6.095734 15.277844 -8.243757 +v 7.189814 15.277844 -7.658960 +v 8.376957 15.277844 -7.298847 +v 9.611546 15.277844 -7.177250 +v 10.846136 15.277844 -7.298848 +v 12.033278 15.277844 -7.658965 +v 13.127356 15.277844 -8.243764 +v 14.086321 15.277844 -9.030769 +v 14.873327 15.277844 -9.989739 +v 15.458120 15.277844 -11.083817 +v 15.818235 15.277844 -12.270962 +v 15.939829 15.277844 -13.505550 +v 15.818232 15.277844 -14.740141 +v 15.458117 15.277844 -15.927283 +v 14.873316 15.277844 -17.021362 +v 14.086309 15.277844 -17.980328 +v 13.127340 15.277844 -18.767330 +v 12.033262 15.277844 -19.352125 +v 10.846117 15.277844 -19.712238 +v 9.611540 13.749696 -22.692797 +v 7.819195 13.749696 -22.516266 +v 6.095732 13.749696 -21.993458 +v 4.507378 13.749696 -21.144464 +v 3.115171 13.749696 -20.001911 +v 1.972616 13.749696 -18.609707 +v 1.123623 13.749696 -17.021351 +v 0.600817 13.749696 -15.297884 +v 0.424284 13.749696 -13.505539 +v 0.600817 13.749696 -11.713193 +v 1.123625 13.749696 -9.989727 +v 1.972622 13.749696 -8.401373 +v 3.115173 13.749696 -7.009167 +v 4.507380 13.749696 -5.866615 +v 6.095739 13.749696 -5.017623 +v 7.819202 13.749696 -4.494817 +v 9.611549 13.749696 -4.318287 +v 11.403894 13.749696 -4.494820 +v 13.127363 13.749696 -5.017629 +v 14.715715 13.749696 -5.866625 +v 16.107920 13.749696 -7.009181 +v 17.250471 13.749696 -8.401387 +v 18.099459 13.749696 -9.989742 +v 18.622267 13.749696 -11.713211 +v 18.798796 13.749696 -13.505556 +v 18.622259 13.749696 -15.297901 +v 18.099455 13.749696 -17.021366 +v 17.250452 13.749696 -18.609722 +v 16.107897 13.749696 -20.001925 +v 14.715693 13.749696 -21.144474 +v 13.127333 13.749696 -21.993465 +v 11.403864 13.749696 -22.516270 +v 9.611540 11.693156 -25.198696 +v 7.330318 11.693156 -24.974016 +v 5.136763 11.693156 -24.308609 +v 3.115171 11.693156 -23.228046 +v 1.343229 11.693156 -21.773851 +v -0.110964 11.693156 -20.001911 +v -1.191528 11.693156 -17.980316 +v -1.856936 11.693156 -15.786760 +v -2.081615 11.693156 -13.505538 +v -1.856934 11.693156 -11.224315 +v -1.191525 11.693156 -9.030760 +v -0.110960 11.693156 -7.009166 +v 1.343235 11.693156 -5.237227 +v 3.115177 11.693156 -3.783033 +v 5.136772 11.693156 -2.702470 +v 7.330328 11.693156 -2.037066 +v 9.611549 11.693156 -1.812386 +v 11.892775 11.693156 -2.037068 +v 14.086332 11.693156 -2.702479 +v 16.107920 11.693156 -3.783048 +v 17.879862 11.693156 -5.237242 +v 19.334051 11.693156 -7.009185 +v 20.414614 11.693156 -9.030780 +v 21.080019 11.693156 -11.224338 +v 21.304697 11.693156 -13.505560 +v 21.080015 11.693156 -15.786782 +v 20.414602 11.693156 -17.980339 +v 19.334028 11.693156 -20.001928 +v 17.879831 11.693156 -21.773867 +v 16.107893 11.693156 -23.228058 +v 14.086294 11.693156 -24.308619 +v 11.892736 11.693156 -24.974022 +v 9.611540 9.187253 -27.255239 +v 6.929108 9.187253 -26.991041 +v 4.349760 9.187253 -26.208607 +v 1.972618 9.187253 -24.938000 +v -0.110964 9.187253 -23.228046 +v -1.820917 9.187253 -21.144463 +v -3.091526 9.187253 -18.767321 +v -3.873960 9.187253 -16.187971 +v -4.138157 9.187253 -13.505537 +v -3.873959 9.187253 -10.823103 +v -3.091520 9.187253 -8.243754 +v -1.820911 9.187253 -5.866612 +v -0.110958 9.187253 -3.783032 +v 1.972626 9.187253 -2.073080 +v 4.349768 9.187253 -0.802473 +v 6.929121 9.187253 -0.020039 +v 9.611553 9.187253 0.244156 +v 12.293989 9.187253 -0.020043 +v 14.873335 9.187253 -0.802485 +v 17.250479 9.187253 -2.073095 +v 19.334059 9.187253 -3.783049 +v 21.044004 9.187253 -5.866634 +v 22.314611 9.187253 -8.243777 +v 23.097048 9.187253 -10.823130 +v 23.361238 9.187253 -13.505564 +v 23.097036 9.187253 -16.187996 +v 22.314596 9.187253 -18.767345 +v 21.043982 9.187253 -21.144485 +v 19.334024 9.187253 -23.228065 +v 17.250437 9.187253 -24.938011 +v 14.873293 9.187253 -26.208616 +v 12.293943 9.187253 -26.991047 +v 9.611538 6.328290 -28.783384 +v 6.630981 6.328290 -28.489828 +v 3.764963 6.328290 -27.620428 +v 1.123625 6.328290 -26.208605 +v -1.191526 6.328290 -24.308609 +v -3.091524 6.328290 -21.993456 +v -4.503347 6.328290 -19.352118 +v -5.372744 6.328290 -16.486097 +v -5.666305 6.328290 -13.505537 +v -5.372743 6.328290 -10.524976 +v -4.503345 6.328290 -7.658957 +v -3.091518 6.328290 -5.017619 +v -1.191521 6.328290 -2.702466 +v 1.123632 6.328290 -0.802471 +v 3.764975 6.328290 0.609350 +v 6.630993 6.328290 1.478745 +v 9.611555 6.328290 1.772303 +v 12.592115 6.328290 1.478741 +v 15.458136 6.328290 0.609339 +v 18.099470 6.328290 -0.802490 +v 20.414621 6.328290 -2.702490 +v 22.314619 6.328290 -5.017643 +v 23.726439 6.328290 -7.658983 +v 24.595831 6.328290 -10.525005 +v 24.889383 6.328290 -13.505566 +v 24.595819 6.328290 -16.486126 +v 23.726416 6.328290 -19.352144 +v 22.314589 6.328290 -21.993481 +v 20.414587 6.328290 -24.308628 +v 18.099432 6.328290 -26.208620 +v 15.458090 6.328290 -27.620440 +v 12.592066 6.328290 -28.489836 +v 9.611540 3.226134 -29.724413 +v 6.447395 3.226134 -29.412773 +v 3.404846 3.226134 -28.489826 +v 0.600817 3.226134 -26.991041 +v -1.856936 3.226134 -24.974018 +v -3.873960 3.226134 -22.516266 +v -5.372746 3.226134 -19.712233 +v -6.295692 3.226134 -16.669682 +v -6.607332 3.226134 -13.505536 +v -6.295691 3.226134 -10.341390 +v -5.372740 3.226134 -7.298840 +v -3.873955 3.226134 -4.494810 +v -1.856928 3.226134 -2.037058 +v 0.600828 3.226134 -0.020035 +v 3.404858 3.226134 1.478746 +v 6.447409 3.226134 2.401691 +v 9.611555 3.226134 2.713330 +v 12.775702 3.226134 2.401687 +v 15.818251 3.226134 1.478735 +v 18.622282 3.226134 -0.020055 +v 21.080030 3.226134 -2.037082 +v 23.097055 3.226134 -4.494838 +v 24.595835 3.226134 -7.298870 +v 25.518774 3.226134 -10.341419 +v 25.830408 3.226134 -13.505567 +v 25.518766 3.226134 -16.669714 +v 24.595812 3.226134 -19.712261 +v 23.097025 3.226134 -22.516289 +v 21.079992 3.226134 -24.974037 +v 18.622236 3.226134 -26.991058 +v 15.818205 3.226134 -28.489840 +v 12.775652 3.226134 -29.412781 +v 9.611538 0.000001 -30.042162 +v 6.385406 0.000001 -29.724417 +v 3.283249 0.000001 -28.783388 +v 0.424286 0.000001 -27.255239 +v -2.081615 0.000001 -25.198698 +v -4.138157 0.000001 -22.692795 +v -5.666304 0.000001 -19.833830 +v -6.607334 0.000001 -16.731672 +v -6.925080 0.000001 -13.505536 +v -6.607332 0.000001 -10.279400 +v -5.666301 0.000001 -7.177244 +v -4.138151 0.000001 -4.318279 +v -2.081610 0.000001 -1.812377 +v 0.424297 0.000001 0.244163 +v 3.283260 0.000001 1.772307 +v 6.385422 0.000001 2.713336 +v 9.611557 0.000001 3.031079 +v 12.837690 0.000001 2.713330 +v 15.939848 0.000001 1.772296 +v 18.798811 0.000001 0.244145 +v 21.304712 0.000001 -1.812400 +v 23.361250 0.000001 -4.318306 +v 24.889395 0.000001 -7.177274 +v 25.830423 0.000001 -10.279431 +v 26.148161 0.000001 -13.505568 +v 25.830408 0.000001 -16.731703 +v 24.889376 0.000001 -19.833858 +v 23.361219 0.000001 -22.692820 +v 21.304674 0.000001 -25.198719 +v 18.798765 0.000001 -27.255259 +v 15.939802 0.000001 -28.783400 +v 12.837637 0.000001 -29.724421 +v 9.611540 -3.226133 -29.724415 +v 6.447395 -3.226133 -29.412775 +v 3.404846 -3.226133 -28.489828 +v 0.600817 -3.226133 -26.991045 +v -1.856936 -3.226133 -24.974018 +v -3.873960 -3.226133 -22.516266 +v -5.372747 -3.226133 -19.712233 +v -6.295694 -3.226133 -16.669683 +v -6.607334 -3.226133 -13.505536 +v -6.295692 -3.226133 -10.341390 +v -5.372742 -3.226133 -7.298840 +v -3.873957 -3.226133 -4.494810 +v -1.856928 -3.226133 -2.037058 +v 0.600826 -3.226133 -0.020033 +v 3.404856 -3.226133 1.478751 +v 6.447409 -3.226133 2.401693 +v 9.611555 -3.226133 2.713333 +v 12.775705 -3.226133 2.401688 +v 15.818251 -3.226133 1.478737 +v 18.622282 -3.226133 -0.020053 +v 21.080030 -3.226133 -2.037082 +v 23.097052 -3.226133 -4.494835 +v 24.595835 -3.226133 -7.298868 +v 25.518778 -3.226133 -10.341420 +v 25.830412 -3.226133 -13.505567 +v 25.518766 -3.226133 -16.669714 +v 24.595812 -3.226133 -19.712261 +v 23.097025 -3.226133 -22.516291 +v 21.079996 -3.226133 -24.974041 +v 18.622236 -3.226133 -26.991062 +v 15.818201 -3.226133 -28.489841 +v 12.775652 -3.226133 -29.412783 +v 9.611538 -6.328289 -28.783388 +v 6.630981 -6.328289 -28.489828 +v 3.764963 -6.328289 -27.620430 +v 1.123625 -6.328289 -26.208607 +v -1.191526 -6.328289 -24.308609 +v -3.091524 -6.328289 -21.993456 +v -4.503351 -6.328289 -19.352118 +v -5.372746 -6.328289 -16.486097 +v -5.666306 -6.328289 -13.505537 +v -5.372745 -6.328289 -10.524975 +v -4.503345 -6.328289 -7.658956 +v -3.091518 -6.328289 -5.017619 +v -1.191521 -6.328289 -2.702466 +v 1.123632 -6.328289 -0.802471 +v 3.764973 -6.328289 0.609352 +v 6.630993 -6.328289 1.478746 +v 9.611555 -6.328289 1.772305 +v 12.592115 -6.328289 1.478741 +v 15.458136 -6.328289 0.609339 +v 18.099474 -6.328289 -0.802486 +v 20.414621 -6.328289 -2.702488 +v 22.314619 -6.328289 -5.017643 +v 23.726439 -6.328289 -7.658984 +v 24.595831 -6.328289 -10.525005 +v 24.889387 -6.328289 -13.505566 +v 24.595819 -6.328289 -16.486126 +v 23.726416 -6.328289 -19.352144 +v 22.314589 -6.328289 -21.993481 +v 20.414591 -6.328289 -24.308630 +v 18.099432 -6.328289 -26.208622 +v 15.458090 -6.328289 -27.620440 +v 12.592066 -6.328289 -28.489836 +v 9.611540 -9.187254 -27.255239 +v 6.929108 -9.187254 -26.991041 +v 4.349760 -9.187254 -26.208607 +v 1.972618 -9.187254 -24.938000 +v -0.110964 -9.187254 -23.228046 +v -1.820917 -9.187254 -21.144463 +v -3.091526 -9.187254 -18.767321 +v -3.873960 -9.187254 -16.187971 +v -4.138157 -9.187254 -13.505537 +v -3.873959 -9.187254 -10.823103 +v -3.091520 -9.187254 -8.243754 +v -1.820911 -9.187254 -5.866612 +v -0.110958 -9.187254 -3.783032 +v 1.972626 -9.187254 -2.073080 +v 4.349768 -9.187254 -0.802473 +v 6.929121 -9.187254 -0.020039 +v 9.611553 -9.187254 0.244156 +v 12.293989 -9.187254 -0.020043 +v 14.873335 -9.187254 -0.802485 +v 17.250479 -9.187254 -2.073095 +v 19.334059 -9.187254 -3.783049 +v 21.044004 -9.187254 -5.866634 +v 22.314611 -9.187254 -8.243777 +v 23.097048 -9.187254 -10.823130 +v 23.361238 -9.187254 -13.505564 +v 23.097036 -9.187254 -16.187996 +v 22.314596 -9.187254 -18.767345 +v 21.043982 -9.187254 -21.144485 +v 19.334024 -9.187254 -23.228065 +v 17.250437 -9.187254 -24.938011 +v 14.873293 -9.187254 -26.208616 +v 12.293943 -9.187254 -26.991047 +v 9.611540 -11.693157 -25.198696 +v 7.330318 -11.693157 -24.974016 +v 5.136763 -11.693157 -24.308609 +v 3.115171 -11.693157 -23.228046 +v 1.343229 -11.693157 -21.773851 +v -0.110964 -11.693157 -20.001911 +v -1.191528 -11.693157 -17.980316 +v -1.856936 -11.693157 -15.786760 +v -2.081615 -11.693157 -13.505538 +v -1.856934 -11.693157 -11.224315 +v -1.191525 -11.693157 -9.030760 +v -0.110960 -11.693157 -7.009166 +v 1.343235 -11.693157 -5.237227 +v 3.115177 -11.693157 -3.783033 +v 5.136772 -11.693157 -2.702470 +v 7.330328 -11.693157 -2.037066 +v 9.611549 -11.693157 -1.812386 +v 11.892775 -11.693157 -2.037068 +v 14.086332 -11.693157 -2.702479 +v 16.107920 -11.693157 -3.783048 +v 17.879862 -11.693157 -5.237242 +v 19.334051 -11.693157 -7.009185 +v 20.414614 -11.693157 -9.030780 +v 21.080019 -11.693157 -11.224338 +v 21.304697 -11.693157 -13.505560 +v 21.080015 -11.693157 -15.786782 +v 20.414602 -11.693157 -17.980339 +v 19.334028 -11.693157 -20.001928 +v 17.879831 -11.693157 -21.773867 +v 16.107893 -11.693157 -23.228058 +v 14.086294 -11.693157 -24.308619 +v 11.892736 -11.693157 -24.974022 +v 9.611540 -13.749699 -22.692795 +v 7.819195 -13.749699 -22.516264 +v 6.095732 -13.749699 -21.993458 +v 4.507378 -13.749699 -21.144464 +v 3.115171 -13.749699 -20.001911 +v 1.972616 -13.749699 -18.609705 +v 1.123623 -13.749699 -17.021349 +v 0.600817 -13.749699 -15.297884 +v 0.424286 -13.749699 -13.505538 +v 0.600817 -13.749699 -11.713193 +v 1.123625 -13.749699 -9.989727 +v 1.972622 -13.749699 -8.401373 +v 3.115175 -13.749699 -7.009168 +v 4.507381 -13.749699 -5.866616 +v 6.095739 -13.749699 -5.017623 +v 7.819206 -13.749699 -4.494817 +v 9.611549 -13.749699 -4.318288 +v 11.403894 -13.749699 -4.494821 +v 13.127359 -13.749699 -5.017631 +v 14.715715 -13.749699 -5.866625 +v 16.107920 -13.749699 -7.009181 +v 17.250467 -13.749699 -8.401387 +v 18.099459 -13.749699 -9.989744 +v 18.622267 -13.749699 -11.713211 +v 18.798796 -13.749699 -13.505556 +v 18.622259 -13.749699 -15.297901 +v 18.099451 -13.749699 -17.021366 +v 17.250452 -13.749699 -18.609718 +v 16.107897 -13.749699 -20.001923 +v 14.715693 -13.749699 -21.144474 +v 13.127333 -13.749699 -21.993464 +v 11.403864 -13.749699 -22.516270 +v 9.611540 -15.277846 -19.833830 +v 8.376951 -15.277846 -19.712233 +v 7.189810 -15.277846 -19.352118 +v 6.095734 -15.277846 -18.767323 +v 5.136765 -15.277846 -17.980316 +v 4.349762 -15.277846 -17.021349 +v 3.764965 -15.277846 -15.927272 +v 3.404848 -15.277846 -14.740128 +v 3.283253 -15.277846 -13.505540 +v 3.404848 -15.277846 -12.270950 +v 3.764967 -15.277846 -11.083808 +v 4.349762 -15.277846 -9.989730 +v 5.136768 -15.277846 -9.030764 +v 6.095736 -15.277846 -8.243760 +v 7.189816 -15.277846 -7.658964 +v 8.376957 -15.277846 -7.298849 +v 9.611546 -15.277846 -7.177253 +v 10.846136 -15.277846 -7.298851 +v 12.033278 -15.277846 -7.658967 +v 13.127356 -15.277846 -8.243767 +v 14.086321 -15.277846 -9.030771 +v 14.873323 -15.277846 -9.989740 +v 15.458120 -15.277846 -11.083818 +v 15.818235 -15.277846 -12.270964 +v 15.939829 -15.277846 -13.505552 +v 15.818228 -15.277846 -14.740139 +v 15.458113 -15.277846 -15.927282 +v 14.873312 -15.277846 -17.021358 +v 14.086306 -15.277846 -17.980324 +v 13.127340 -15.277846 -18.767326 +v 12.033258 -15.277846 -19.352121 +v 10.846113 -15.277846 -19.712234 +v 9.611542 -16.218876 -16.731672 +v 8.982155 -16.218876 -16.669683 +v 8.376953 -16.218876 -16.486097 +v 7.819199 -16.218876 -16.187971 +v 7.330320 -16.218876 -15.786760 +v 6.929110 -16.218876 -15.297883 +v 6.630983 -16.218876 -14.740128 +v 6.447399 -16.218876 -14.134928 +v 6.385410 -16.218876 -13.505540 +v 6.447399 -16.218876 -12.876153 +v 6.630985 -16.218876 -12.270953 +v 6.929111 -16.218876 -11.713198 +v 7.330322 -16.218876 -11.224320 +v 7.819199 -16.218876 -10.823111 +v 8.376955 -16.218876 -10.524984 +v 8.982157 -16.218876 -10.341399 +v 9.611544 -16.218876 -10.279411 +v 10.240929 -16.218876 -10.341400 +v 10.846130 -16.218876 -10.524986 +v 11.403883 -16.218876 -10.823112 +v 11.892759 -16.218876 -11.224325 +v 12.293974 -16.218876 -11.713202 +v 12.592100 -16.218876 -12.270960 +v 12.775686 -16.218876 -12.876160 +v 12.837671 -16.218876 -13.505547 +v 12.775682 -16.218876 -14.134933 +v 12.592093 -16.218876 -14.740133 +v 12.293966 -16.218876 -15.297888 +v 11.892756 -16.218876 -15.786764 +v 11.403879 -16.218876 -16.187975 +v 10.846121 -16.218876 -16.486099 +v 10.240923 -16.218876 -16.669685 +v 9.611540 -16.536621 -13.505542 +v 7.404444 -11.629548 14.999386 +v 6.914089 -11.629548 11.274763 +v 5.476439 -11.629548 7.803965 +v 3.189468 -11.629548 4.823524 +v 0.209024 -11.629548 2.536550 +v -3.261770 -11.629548 1.098902 +v -6.986394 -11.629548 0.608545 +v -10.711016 -11.629548 1.098901 +v -14.181813 -11.629548 2.536551 +v -17.162252 -11.629548 4.823524 +v -19.449226 -11.629548 7.803963 +v -20.886879 -11.629548 11.274757 +v -21.377235 -11.629548 14.999380 +v -20.886881 -11.629548 18.724003 +v -19.449232 -11.629548 22.194799 +v -17.162262 -11.629548 25.175241 +v -14.181819 -11.629548 27.462217 +v -10.711023 -11.629548 28.899866 +v -6.986402 -11.629548 29.390230 +v -3.261778 -11.629548 28.899870 +v 0.209021 -11.629548 27.462225 +v 3.189459 -11.629548 25.175253 +v 5.476435 -11.629548 22.194815 +v 6.914087 -11.629548 18.724018 +v 4.526278 -6.021804 14.999386 +v 4.133991 -6.021804 12.019686 +v 2.983871 -6.021804 9.243050 +v 1.154293 -6.021804 6.858698 +v -1.230059 -6.021804 5.029119 +v -4.006697 -6.021804 3.878999 +v -6.986394 -6.021804 3.486713 +v -9.966091 -6.021804 3.878998 +v -12.742728 -6.021804 5.029119 +v -15.127081 -6.021804 6.858694 +v -16.956659 -6.021804 9.243046 +v -18.106781 -6.021804 12.019682 +v -18.499065 -6.021804 14.999382 +v -18.106783 -6.021804 17.979080 +v -16.956663 -6.021804 20.755716 +v -15.127088 -6.021804 23.140070 +v -12.742735 -6.021804 24.969648 +v -9.966098 -6.021804 26.119772 +v -6.986401 -6.021804 26.512056 +v -4.006702 -6.021804 26.119776 +v -1.230064 -6.021804 24.969656 +v 1.154287 -6.021804 23.140078 +v 2.983870 -6.021804 20.755726 +v 4.133989 -6.021804 17.979094 +v 1.648109 -0.414061 14.999384 +v 1.353897 -0.414061 12.764610 +v 0.491306 -0.414061 10.682133 +v -0.880878 -0.414061 8.893867 +v -2.669142 -0.414061 7.521685 +v -4.751619 -0.414061 6.659094 +v -6.986394 -0.414061 6.364882 +v -9.221169 -0.414061 6.659092 +v -11.303646 -0.414061 7.521683 +v -13.091910 -0.414061 8.893866 +v -14.464094 -0.414061 10.682131 +v -15.326685 -0.414061 12.764608 +v -15.620899 -0.414061 14.999384 +v -15.326687 -0.414061 17.234158 +v -14.464097 -0.414061 19.316635 +v -13.091915 -0.414061 21.104900 +v -11.303650 -0.414061 22.477083 +v -9.221172 -0.414061 23.339674 +v -6.986399 -0.414061 23.633890 +v -4.751623 -0.414061 23.339678 +v -2.669146 -0.414061 22.477091 +v -0.880880 -0.414061 21.104906 +v 0.491302 -0.414061 19.316643 +v 1.353895 -0.414061 17.234167 +v -1.230061 5.193685 14.999384 +v -1.426203 5.193685 13.509537 +v -2.001261 5.193685 12.121216 +v -2.916052 5.193685 10.929041 +v -4.108227 5.193685 10.014252 +v -5.496546 5.193685 9.439192 +v -6.986395 5.193685 9.243050 +v -8.476243 5.193685 9.439192 +v -9.864561 5.193685 10.014252 +v -11.056738 5.193685 10.929039 +v -11.971527 5.193685 12.121216 +v -12.546587 5.193685 13.509535 +v -12.742730 5.193685 14.999382 +v -12.546589 5.193685 16.489231 +v -11.971529 5.193685 17.877550 +v -11.056741 5.193685 19.069729 +v -9.864565 5.193685 19.984518 +v -8.476246 5.193685 20.559580 +v -6.986398 5.193685 20.755722 +v -5.496548 5.193685 20.559580 +v -4.108229 5.193685 19.984522 +v -2.916054 5.193685 19.069735 +v -2.001265 5.193685 17.877556 +v -1.426203 5.193685 16.489239 +v -4.108227 10.801427 14.999386 +v -4.206299 10.801427 14.254461 +v -4.493828 10.801427 13.560303 +v -4.951223 10.801427 12.964212 +v -5.547310 10.801427 12.506819 +v -6.241470 10.801427 12.219290 +v -6.986395 10.801427 12.121216 +v -7.731319 10.801427 12.219288 +v -8.425478 10.801427 12.506819 +v -9.021566 10.801427 12.964212 +v -9.478960 10.801427 13.560303 +v -9.766491 10.801427 14.254459 +v -9.864563 10.801427 14.999384 +v -9.766492 10.801427 15.744308 +v -9.478962 10.801427 16.438467 +v -9.021568 10.801427 17.034555 +v -8.425480 10.801427 17.491951 +v -7.731320 10.801427 17.779482 +v -6.986397 10.801427 17.877552 +v -6.241472 10.801427 17.779484 +v -5.547312 10.801427 17.491953 +v -4.951224 10.801427 17.034559 +v -4.493830 10.801427 16.438471 +v -4.206299 10.801427 15.744314 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +v -6.986395 16.409168 14.999386 +# 634 vertices + +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.000000 1.000000 -0.000000 +vn 0.255228 0.000000 0.966881 +vn 0.255228 0.000000 0.966881 +vn 0.255228 0.000000 0.966881 +vn 0.255228 0.000000 0.966881 +vn 0.255228 0.000000 0.966881 +vn 0.255228 0.000000 0.966881 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn -0.255228 0.000000 -0.966881 +vn -0.255228 0.000000 -0.966881 +vn -0.255228 0.000000 -0.966881 +vn -0.255228 0.000000 -0.966881 +vn -0.255228 0.000000 -0.966881 +vn -0.255228 0.000000 -0.966881 +vn -0.966881 0.000000 0.255228 +vn -0.966881 0.000000 0.255228 +vn -0.966881 0.000000 0.255228 +vn -0.966881 0.000000 0.255228 +vn -0.966881 0.000000 0.255228 +vn -0.966881 0.000000 0.255228 +vn -0.000000 1.000000 0.000000 +vn -0.000000 0.979598 -0.200969 +vn -0.039207 0.979598 -0.197107 +vn -0.000000 1.000000 0.000000 +vn -0.039207 0.979598 -0.197107 +vn -0.076907 0.979598 -0.185671 +vn -0.000000 1.000000 0.000000 +vn -0.076907 0.979598 -0.185671 +vn -0.111652 0.979598 -0.167099 +vn -0.000000 1.000000 0.000000 +vn -0.111652 0.979598 -0.167099 +vn -0.142106 0.979598 -0.142106 +vn -0.000000 1.000000 0.000000 +vn -0.142106 0.979598 -0.142106 +vn -0.167099 0.979598 -0.111652 +vn -0.000000 1.000000 0.000000 +vn -0.167099 0.979598 -0.111652 +vn -0.185671 0.979598 -0.076907 +vn -0.000000 1.000000 0.000000 +vn -0.185671 0.979598 -0.076907 +vn -0.197107 0.979598 -0.039207 +vn -0.000000 1.000000 0.000000 +vn -0.197107 0.979598 -0.039207 +vn -0.200969 0.979598 0.000000 +vn -0.000000 1.000000 0.000000 +vn -0.200969 0.979598 0.000000 +vn -0.197107 0.979598 0.039207 +vn -0.000000 1.000000 0.000000 +vn -0.197107 0.979598 0.039207 +vn -0.185671 0.979598 0.076907 +vn -0.000000 1.000000 0.000000 +vn -0.185671 0.979598 0.076907 +vn -0.167099 0.979598 0.111652 +vn -0.000000 1.000000 0.000000 +vn -0.167099 0.979598 0.111652 +vn -0.142106 0.979598 0.142107 +vn -0.000000 1.000000 0.000000 +vn -0.142106 0.979598 0.142107 +vn -0.111652 0.979598 0.167099 +vn -0.000000 1.000000 0.000000 +vn -0.111652 0.979598 0.167099 +vn -0.076907 0.979598 0.185671 +vn -0.000000 1.000000 0.000000 +vn -0.076907 0.979598 0.185671 +vn -0.039207 0.979598 0.197107 +vn -0.000000 1.000000 0.000000 +vn -0.039207 0.979598 0.197107 +vn 0.000000 0.979598 0.200969 +vn -0.000000 1.000000 0.000000 +vn 0.000000 0.979598 0.200969 +vn 0.039207 0.979598 0.197107 +vn -0.000000 1.000000 0.000000 +vn 0.039207 0.979598 0.197107 +vn 0.076908 0.979598 0.185671 +vn -0.000000 1.000000 0.000000 +vn 0.076908 0.979598 0.185671 +vn 0.111652 0.979598 0.167099 +vn -0.000000 1.000000 0.000000 +vn 0.111652 0.979598 0.167099 +vn 0.142107 0.979598 0.142106 +vn -0.000000 1.000000 0.000000 +vn 0.142107 0.979598 0.142106 +vn 0.167100 0.979598 0.111652 +vn -0.000000 1.000000 0.000000 +vn 0.167100 0.979598 0.111652 +vn 0.185671 0.979598 0.076907 +vn -0.000000 1.000000 0.000000 +vn 0.185671 0.979598 0.076907 +vn 0.197107 0.979598 0.039206 +vn -0.000000 1.000000 0.000000 +vn 0.197107 0.979598 0.039206 +vn 0.200969 0.979598 -0.000001 +vn -0.000000 1.000000 0.000000 +vn 0.200969 0.979598 -0.000001 +vn 0.197107 0.979598 -0.039207 +vn -0.000000 1.000000 0.000000 +vn 0.197107 0.979598 -0.039207 +vn 0.185671 0.979598 -0.076908 +vn -0.000000 1.000000 0.000000 +vn 0.185671 0.979598 -0.076908 +vn 0.167099 0.979598 -0.111653 +vn -0.000000 1.000000 0.000000 +vn 0.167099 0.979598 -0.111653 +vn 0.142106 0.979598 -0.142107 +vn -0.000000 1.000000 0.000000 +vn 0.142106 0.979598 -0.142107 +vn 0.111652 0.979598 -0.167100 +vn -0.000000 1.000000 0.000000 +vn 0.111652 0.979598 -0.167100 +vn 0.076907 0.979598 -0.185671 +vn -0.000000 1.000000 0.000000 +vn 0.076907 0.979598 -0.185671 +vn 0.039207 0.979598 -0.197107 +vn -0.000000 1.000000 0.000000 +vn 0.039207 0.979598 -0.197107 +vn -0.000000 0.979598 -0.200969 +vn -0.075673 0.921707 -0.380434 +vn -0.039207 0.979598 -0.197107 +vn -0.000000 0.979598 -0.200969 +vn -0.000000 0.979598 -0.200969 +vn -0.000000 0.921707 -0.387887 +vn -0.075673 0.921707 -0.380434 +vn -0.148438 0.921707 -0.358361 +vn -0.076907 0.979598 -0.185671 +vn -0.039207 0.979598 -0.197107 +vn -0.039207 0.979598 -0.197107 +vn -0.075673 0.921707 -0.380434 +vn -0.148438 0.921707 -0.358361 +vn -0.215499 0.921707 -0.322516 +vn -0.111652 0.979598 -0.167099 +vn -0.076907 0.979598 -0.185671 +vn -0.076907 0.979598 -0.185671 +vn -0.148438 0.921707 -0.358361 +vn -0.215499 0.921707 -0.322516 +vn -0.274278 0.921707 -0.274278 +vn -0.142106 0.979598 -0.142106 +vn -0.111652 0.979598 -0.167099 +vn -0.111652 0.979598 -0.167099 +vn -0.215499 0.921707 -0.322516 +vn -0.274278 0.921707 -0.274278 +vn -0.322516 0.921707 -0.215499 +vn -0.167099 0.979598 -0.111652 +vn -0.142106 0.979598 -0.142106 +vn -0.142106 0.979598 -0.142106 +vn -0.274278 0.921707 -0.274278 +vn -0.322516 0.921707 -0.215499 +vn -0.358361 0.921707 -0.148438 +vn -0.185671 0.979598 -0.076907 +vn -0.167099 0.979598 -0.111652 +vn -0.167099 0.979598 -0.111652 +vn -0.322516 0.921707 -0.215499 +vn -0.358361 0.921707 -0.148438 +vn -0.380434 0.921707 -0.075673 +vn -0.197107 0.979598 -0.039207 +vn -0.185671 0.979598 -0.076907 +vn -0.185671 0.979598 -0.076907 +vn -0.358361 0.921707 -0.148438 +vn -0.380434 0.921707 -0.075673 +vn -0.387887 0.921707 0.000000 +vn -0.200969 0.979598 0.000000 +vn -0.197107 0.979598 -0.039207 +vn -0.197107 0.979598 -0.039207 +vn -0.380434 0.921707 -0.075673 +vn -0.387887 0.921707 0.000000 +vn -0.380434 0.921707 0.075673 +vn -0.197107 0.979598 0.039207 +vn -0.200969 0.979598 0.000000 +vn -0.200969 0.979598 0.000000 +vn -0.387887 0.921707 0.000000 +vn -0.380434 0.921707 0.075673 +vn -0.358361 0.921707 0.148438 +vn -0.185671 0.979598 0.076907 +vn -0.197107 0.979598 0.039207 +vn -0.197107 0.979598 0.039207 +vn -0.380434 0.921707 0.075673 +vn -0.358361 0.921707 0.148438 +vn -0.322516 0.921707 0.215498 +vn -0.167099 0.979598 0.111652 +vn -0.185671 0.979598 0.076907 +vn -0.185671 0.979598 0.076907 +vn -0.358361 0.921707 0.148438 +vn -0.322516 0.921707 0.215498 +vn -0.274277 0.921707 0.274278 +vn -0.142106 0.979598 0.142107 +vn -0.167099 0.979598 0.111652 +vn -0.167099 0.979598 0.111652 +vn -0.322516 0.921707 0.215498 +vn -0.274277 0.921707 0.274278 +vn -0.215498 0.921707 0.322516 +vn -0.111652 0.979598 0.167099 +vn -0.142106 0.979598 0.142107 +vn -0.142106 0.979598 0.142107 +vn -0.274277 0.921707 0.274278 +vn -0.215498 0.921707 0.322516 +vn -0.148438 0.921707 0.358361 +vn -0.076907 0.979598 0.185671 +vn -0.111652 0.979598 0.167099 +vn -0.111652 0.979598 0.167099 +vn -0.215498 0.921707 0.322516 +vn -0.148438 0.921707 0.358361 +vn -0.075673 0.921707 0.380434 +vn -0.039207 0.979598 0.197107 +vn -0.076907 0.979598 0.185671 +vn -0.076907 0.979598 0.185671 +vn -0.148438 0.921707 0.358361 +vn -0.075673 0.921707 0.380434 +vn 0.000000 0.921707 0.387887 +vn 0.000000 0.979598 0.200969 +vn -0.039207 0.979598 0.197107 +vn -0.039207 0.979598 0.197107 +vn -0.075673 0.921707 0.380434 +vn 0.000000 0.921707 0.387887 +vn 0.075673 0.921707 0.380434 +vn 0.039207 0.979598 0.197107 +vn 0.000000 0.979598 0.200969 +vn 0.000000 0.979598 0.200969 +vn 0.000000 0.921707 0.387887 +vn 0.075673 0.921707 0.380434 +vn 0.148438 0.921707 0.358361 +vn 0.076908 0.979598 0.185671 +vn 0.039207 0.979598 0.197107 +vn 0.039207 0.979598 0.197107 +vn 0.075673 0.921707 0.380434 +vn 0.148438 0.921707 0.358361 +vn 0.215499 0.921707 0.322516 +vn 0.111652 0.979598 0.167099 +vn 0.076908 0.979598 0.185671 +vn 0.076908 0.979598 0.185671 +vn 0.148438 0.921707 0.358361 +vn 0.215499 0.921707 0.322516 +vn 0.274278 0.921707 0.274277 +vn 0.142107 0.979598 0.142106 +vn 0.111652 0.979598 0.167099 +vn 0.111652 0.979598 0.167099 +vn 0.215499 0.921707 0.322516 +vn 0.274278 0.921707 0.274277 +vn 0.322517 0.921707 0.215498 +vn 0.167100 0.979598 0.111652 +vn 0.142107 0.979598 0.142106 +vn 0.142107 0.979598 0.142106 +vn 0.274278 0.921707 0.274277 +vn 0.322517 0.921707 0.215498 +vn 0.358361 0.921707 0.148437 +vn 0.185671 0.979598 0.076907 +vn 0.167100 0.979598 0.111652 +vn 0.167100 0.979598 0.111652 +vn 0.322517 0.921707 0.215498 +vn 0.358361 0.921707 0.148437 +vn 0.380434 0.921707 0.075673 +vn 0.197107 0.979598 0.039206 +vn 0.185671 0.979598 0.076907 +vn 0.185671 0.979598 0.076907 +vn 0.358361 0.921707 0.148437 +vn 0.380434 0.921707 0.075673 +vn 0.387887 0.921707 -0.000001 +vn 0.200969 0.979598 -0.000001 +vn 0.197107 0.979598 0.039206 +vn 0.197107 0.979598 0.039206 +vn 0.380434 0.921707 0.075673 +vn 0.387887 0.921707 -0.000001 +vn 0.380434 0.921707 -0.075674 +vn 0.197107 0.979598 -0.039207 +vn 0.200969 0.979598 -0.000001 +vn 0.200969 0.979598 -0.000001 +vn 0.387887 0.921707 -0.000001 +vn 0.380434 0.921707 -0.075674 +vn 0.358361 0.921707 -0.148438 +vn 0.185671 0.979598 -0.076908 +vn 0.197107 0.979598 -0.039207 +vn 0.197107 0.979598 -0.039207 +vn 0.380434 0.921707 -0.075674 +vn 0.358361 0.921707 -0.148438 +vn 0.322516 0.921707 -0.215499 +vn 0.167099 0.979598 -0.111653 +vn 0.185671 0.979598 -0.076908 +vn 0.185671 0.979598 -0.076908 +vn 0.358361 0.921707 -0.148438 +vn 0.322516 0.921707 -0.215499 +vn 0.274277 0.921707 -0.274278 +vn 0.142106 0.979598 -0.142107 +vn 0.167099 0.979598 -0.111653 +vn 0.167099 0.979598 -0.111653 +vn 0.322516 0.921707 -0.215499 +vn 0.274277 0.921707 -0.274278 +vn 0.215498 0.921707 -0.322517 +vn 0.111652 0.979598 -0.167100 +vn 0.142106 0.979598 -0.142107 +vn 0.142106 0.979598 -0.142107 +vn 0.274277 0.921707 -0.274278 +vn 0.215498 0.921707 -0.322517 +vn 0.148437 0.921707 -0.358361 +vn 0.076907 0.979598 -0.185671 +vn 0.111652 0.979598 -0.167100 +vn 0.111652 0.979598 -0.167100 +vn 0.215498 0.921707 -0.322517 +vn 0.148437 0.921707 -0.358361 +vn 0.075672 0.921707 -0.380434 +vn 0.039207 0.979598 -0.197107 +vn 0.076907 0.979598 -0.185671 +vn 0.076907 0.979598 -0.185671 +vn 0.148437 0.921707 -0.358361 +vn 0.075672 0.921707 -0.380434 +vn -0.000000 0.921707 -0.387887 +vn -0.000000 0.979598 -0.200969 +vn 0.039207 0.979598 -0.197107 +vn 0.039207 0.979598 -0.197107 +vn 0.075672 0.921707 -0.380434 +vn -0.000000 0.921707 -0.387887 +vn -0.109207 0.828645 -0.549019 +vn -0.075673 0.921707 -0.380434 +vn -0.000000 0.921707 -0.387887 +vn -0.000000 0.921707 -0.387887 +vn -0.000000 0.828645 -0.559775 +vn -0.109207 0.828645 -0.549019 +vn -0.214217 0.828645 -0.517165 +vn -0.148438 0.921707 -0.358361 +vn -0.075673 0.921707 -0.380434 +vn -0.075673 0.921707 -0.380434 +vn -0.109207 0.828645 -0.549019 +vn -0.214217 0.828645 -0.517165 +vn -0.310994 0.828645 -0.465436 +vn -0.215499 0.921707 -0.322516 +vn -0.148438 0.921707 -0.358361 +vn -0.148438 0.921707 -0.358361 +vn -0.214217 0.828645 -0.517165 +vn -0.310994 0.828645 -0.465436 +vn -0.395821 0.828645 -0.395821 +vn -0.274278 0.921707 -0.274278 +vn -0.215499 0.921707 -0.322516 +vn -0.215499 0.921707 -0.322516 +vn -0.310994 0.828645 -0.465436 +vn -0.395821 0.828645 -0.395821 +vn -0.465436 0.828645 -0.310995 +vn -0.322516 0.921707 -0.215499 +vn -0.274278 0.921707 -0.274278 +vn -0.274278 0.921707 -0.274278 +vn -0.395821 0.828645 -0.395821 +vn -0.465436 0.828645 -0.310995 +vn -0.517165 0.828645 -0.214216 +vn -0.358361 0.921707 -0.148438 +vn -0.322516 0.921707 -0.215499 +vn -0.322516 0.921707 -0.215499 +vn -0.465436 0.828645 -0.310995 +vn -0.517165 0.828645 -0.214216 +vn -0.549019 0.828645 -0.109207 +vn -0.380434 0.921707 -0.075673 +vn -0.358361 0.921707 -0.148438 +vn -0.358361 0.921707 -0.148438 +vn -0.517165 0.828645 -0.214216 +vn -0.549019 0.828645 -0.109207 +vn -0.559775 0.828645 -0.000000 +vn -0.387887 0.921707 0.000000 +vn -0.380434 0.921707 -0.075673 +vn -0.380434 0.921707 -0.075673 +vn -0.549019 0.828645 -0.109207 +vn -0.559775 0.828645 -0.000000 +vn -0.549019 0.828645 0.109207 +vn -0.380434 0.921707 0.075673 +vn -0.387887 0.921707 0.000000 +vn -0.387887 0.921707 0.000000 +vn -0.559775 0.828645 -0.000000 +vn -0.549019 0.828645 0.109207 +vn -0.517165 0.828645 0.214217 +vn -0.358361 0.921707 0.148438 +vn -0.380434 0.921707 0.075673 +vn -0.380434 0.921707 0.075673 +vn -0.549019 0.828645 0.109207 +vn -0.517165 0.828645 0.214217 +vn -0.465436 0.828645 0.310995 +vn -0.322516 0.921707 0.215498 +vn -0.358361 0.921707 0.148438 +vn -0.358361 0.921707 0.148438 +vn -0.517165 0.828645 0.214217 +vn -0.465436 0.828645 0.310995 +vn -0.395821 0.828645 0.395821 +vn -0.274277 0.921707 0.274278 +vn -0.322516 0.921707 0.215498 +vn -0.322516 0.921707 0.215498 +vn -0.465436 0.828645 0.310995 +vn -0.395821 0.828645 0.395821 +vn -0.310994 0.828645 0.465436 +vn -0.215498 0.921707 0.322516 +vn -0.274277 0.921707 0.274278 +vn -0.274277 0.921707 0.274278 +vn -0.395821 0.828645 0.395821 +vn -0.310994 0.828645 0.465436 +vn -0.214216 0.828645 0.517165 +vn -0.148438 0.921707 0.358361 +vn -0.215498 0.921707 0.322516 +vn -0.215498 0.921707 0.322516 +vn -0.310994 0.828645 0.465436 +vn -0.214216 0.828645 0.517165 +vn -0.109206 0.828645 0.549019 +vn -0.075673 0.921707 0.380434 +vn -0.148438 0.921707 0.358361 +vn -0.148438 0.921707 0.358361 +vn -0.214216 0.828645 0.517165 +vn -0.109206 0.828645 0.549019 +vn 0.000001 0.828645 0.559775 +vn 0.000000 0.921707 0.387887 +vn -0.075673 0.921707 0.380434 +vn -0.075673 0.921707 0.380434 +vn -0.109206 0.828645 0.549019 +vn 0.000001 0.828645 0.559775 +vn 0.109207 0.828645 0.549019 +vn 0.075673 0.921707 0.380434 +vn 0.000000 0.921707 0.387887 +vn 0.000000 0.921707 0.387887 +vn 0.000001 0.828645 0.559775 +vn 0.109207 0.828645 0.549019 +vn 0.214217 0.828645 0.517165 +vn 0.148438 0.921707 0.358361 +vn 0.075673 0.921707 0.380434 +vn 0.075673 0.921707 0.380434 +vn 0.109207 0.828645 0.549019 +vn 0.214217 0.828645 0.517165 +vn 0.310995 0.828645 0.465436 +vn 0.215499 0.921707 0.322516 +vn 0.148438 0.921707 0.358361 +vn 0.148438 0.921707 0.358361 +vn 0.214217 0.828645 0.517165 +vn 0.310995 0.828645 0.465436 +vn 0.395821 0.828645 0.395820 +vn 0.274278 0.921707 0.274277 +vn 0.215499 0.921707 0.322516 +vn 0.215499 0.921707 0.322516 +vn 0.310995 0.828645 0.465436 +vn 0.395821 0.828645 0.395820 +vn 0.465436 0.828645 0.310994 +vn 0.322517 0.921707 0.215498 +vn 0.274278 0.921707 0.274277 +vn 0.274278 0.921707 0.274277 +vn 0.395821 0.828645 0.395820 +vn 0.465436 0.828645 0.310994 +vn 0.517165 0.828645 0.214216 +vn 0.358361 0.921707 0.148437 +vn 0.322517 0.921707 0.215498 +vn 0.322517 0.921707 0.215498 +vn 0.465436 0.828645 0.310994 +vn 0.517165 0.828645 0.214216 +vn 0.549019 0.828645 0.109206 +vn 0.380434 0.921707 0.075673 +vn 0.358361 0.921707 0.148437 +vn 0.358361 0.921707 0.148437 +vn 0.517165 0.828645 0.214216 +vn 0.549019 0.828645 0.109206 +vn 0.559775 0.828645 -0.000001 +vn 0.387887 0.921707 -0.000001 +vn 0.380434 0.921707 0.075673 +vn 0.380434 0.921707 0.075673 +vn 0.549019 0.828645 0.109206 +vn 0.559775 0.828645 -0.000001 +vn 0.549019 0.828645 -0.109208 +vn 0.380434 0.921707 -0.075674 +vn 0.387887 0.921707 -0.000001 +vn 0.387887 0.921707 -0.000001 +vn 0.559775 0.828645 -0.000001 +vn 0.549019 0.828645 -0.109208 +vn 0.517165 0.828645 -0.214217 +vn 0.358361 0.921707 -0.148438 +vn 0.380434 0.921707 -0.075674 +vn 0.380434 0.921707 -0.075674 +vn 0.549019 0.828645 -0.109208 +vn 0.517165 0.828645 -0.214217 +vn 0.465435 0.828645 -0.310995 +vn 0.322516 0.921707 -0.215499 +vn 0.358361 0.921707 -0.148438 +vn 0.358361 0.921707 -0.148438 +vn 0.517165 0.828645 -0.214217 +vn 0.465435 0.828645 -0.310995 +vn 0.395820 0.828645 -0.395822 +vn 0.274277 0.921707 -0.274278 +vn 0.322516 0.921707 -0.215499 +vn 0.322516 0.921707 -0.215499 +vn 0.465435 0.828645 -0.310995 +vn 0.395820 0.828645 -0.395822 +vn 0.310993 0.828645 -0.465437 +vn 0.215498 0.921707 -0.322517 +vn 0.274277 0.921707 -0.274278 +vn 0.274277 0.921707 -0.274278 +vn 0.395820 0.828645 -0.395822 +vn 0.310993 0.828645 -0.465437 +vn 0.214216 0.828645 -0.517165 +vn 0.148437 0.921707 -0.358361 +vn 0.215498 0.921707 -0.322517 +vn 0.215498 0.921707 -0.322517 +vn 0.310993 0.828645 -0.465437 +vn 0.214216 0.828645 -0.517165 +vn 0.109206 0.828645 -0.549019 +vn 0.075672 0.921707 -0.380434 +vn 0.148437 0.921707 -0.358361 +vn 0.148437 0.921707 -0.358361 +vn 0.214216 0.828645 -0.517165 +vn 0.109206 0.828645 -0.549019 +vn -0.000000 0.828645 -0.559775 +vn -0.000000 0.921707 -0.387887 +vn 0.075672 0.921707 -0.380434 +vn 0.075672 0.921707 -0.380434 +vn 0.109206 0.828645 -0.549019 +vn -0.000000 0.828645 -0.559775 +vn -0.138542 0.704059 -0.696496 +vn -0.109207 0.828645 -0.549019 +vn -0.000000 0.828645 -0.559775 +vn -0.000000 0.828645 -0.559775 +vn -0.000000 0.704059 -0.710141 +vn -0.138542 0.704059 -0.696496 +vn -0.271759 0.704059 -0.656085 +vn -0.214217 0.828645 -0.517165 +vn -0.109207 0.828645 -0.549019 +vn -0.109207 0.828645 -0.549019 +vn -0.138542 0.704059 -0.696496 +vn -0.271759 0.704059 -0.656085 +vn -0.394533 0.704059 -0.590461 +vn -0.310994 0.828645 -0.465436 +vn -0.214217 0.828645 -0.517165 +vn -0.214217 0.828645 -0.517165 +vn -0.271759 0.704059 -0.656085 +vn -0.394533 0.704059 -0.590461 +vn -0.502146 0.704059 -0.502146 +vn -0.395821 0.828645 -0.395821 +vn -0.310994 0.828645 -0.465436 +vn -0.310994 0.828645 -0.465436 +vn -0.394533 0.704059 -0.590461 +vn -0.502146 0.704059 -0.502146 +vn -0.590461 0.704059 -0.394533 +vn -0.465436 0.828645 -0.310995 +vn -0.395821 0.828645 -0.395821 +vn -0.395821 0.828645 -0.395821 +vn -0.502146 0.704059 -0.502146 +vn -0.590461 0.704059 -0.394533 +vn -0.656085 0.704059 -0.271759 +vn -0.517165 0.828645 -0.214216 +vn -0.465436 0.828645 -0.310995 +vn -0.465436 0.828645 -0.310995 +vn -0.590461 0.704059 -0.394533 +vn -0.656085 0.704059 -0.271759 +vn -0.696496 0.704059 -0.138541 +vn -0.549019 0.828645 -0.109207 +vn -0.517165 0.828645 -0.214216 +vn -0.517165 0.828645 -0.214216 +vn -0.656085 0.704059 -0.271759 +vn -0.696496 0.704059 -0.138541 +vn -0.710141 0.704059 0.000000 +vn -0.559775 0.828645 -0.000000 +vn -0.549019 0.828645 -0.109207 +vn -0.549019 0.828645 -0.109207 +vn -0.696496 0.704059 -0.138541 +vn -0.710141 0.704059 0.000000 +vn -0.696496 0.704059 0.138542 +vn -0.549019 0.828645 0.109207 +vn -0.559775 0.828645 -0.000000 +vn -0.559775 0.828645 -0.000000 +vn -0.710141 0.704059 0.000000 +vn -0.696496 0.704059 0.138542 +vn -0.656085 0.704059 0.271760 +vn -0.517165 0.828645 0.214217 +vn -0.549019 0.828645 0.109207 +vn -0.549019 0.828645 0.109207 +vn -0.696496 0.704059 0.138542 +vn -0.656085 0.704059 0.271760 +vn -0.590461 0.704059 0.394534 +vn -0.465436 0.828645 0.310995 +vn -0.517165 0.828645 0.214217 +vn -0.517165 0.828645 0.214217 +vn -0.656085 0.704059 0.271760 +vn -0.590461 0.704059 0.394534 +vn -0.502145 0.704059 0.502146 +vn -0.395821 0.828645 0.395821 +vn -0.465436 0.828645 0.310995 +vn -0.465436 0.828645 0.310995 +vn -0.590461 0.704059 0.394534 +vn -0.502145 0.704059 0.502146 +vn -0.394533 0.704059 0.590461 +vn -0.310994 0.828645 0.465436 +vn -0.395821 0.828645 0.395821 +vn -0.395821 0.828645 0.395821 +vn -0.502145 0.704059 0.502146 +vn -0.394533 0.704059 0.590461 +vn -0.271759 0.704059 0.656085 +vn -0.214216 0.828645 0.517165 +vn -0.310994 0.828645 0.465436 +vn -0.310994 0.828645 0.465436 +vn -0.394533 0.704059 0.590461 +vn -0.271759 0.704059 0.656085 +vn -0.138541 0.704059 0.696496 +vn -0.109206 0.828645 0.549019 +vn -0.214216 0.828645 0.517165 +vn -0.214216 0.828645 0.517165 +vn -0.271759 0.704059 0.656085 +vn -0.138541 0.704059 0.696496 +vn 0.000001 0.704059 0.710142 +vn 0.000001 0.828645 0.559775 +vn -0.109206 0.828645 0.549019 +vn -0.109206 0.828645 0.549019 +vn -0.138541 0.704059 0.696496 +vn 0.000001 0.704059 0.710142 +vn 0.138542 0.704059 0.696496 +vn 0.109207 0.828645 0.549019 +vn 0.000001 0.828645 0.559775 +vn 0.000001 0.828645 0.559775 +vn 0.000001 0.704059 0.710142 +vn 0.138542 0.704059 0.696496 +vn 0.271760 0.704059 0.656085 +vn 0.214217 0.828645 0.517165 +vn 0.109207 0.828645 0.549019 +vn 0.109207 0.828645 0.549019 +vn 0.138542 0.704059 0.696496 +vn 0.271760 0.704059 0.656085 +vn 0.394534 0.704059 0.590460 +vn 0.310995 0.828645 0.465436 +vn 0.214217 0.828645 0.517165 +vn 0.214217 0.828645 0.517165 +vn 0.271760 0.704059 0.656085 +vn 0.394534 0.704059 0.590460 +vn 0.502146 0.704059 0.502145 +vn 0.395821 0.828645 0.395820 +vn 0.310995 0.828645 0.465436 +vn 0.310995 0.828645 0.465436 +vn 0.394534 0.704059 0.590460 +vn 0.502146 0.704059 0.502145 +vn 0.590461 0.704059 0.394533 +vn 0.465436 0.828645 0.310994 +vn 0.395821 0.828645 0.395820 +vn 0.395821 0.828645 0.395820 +vn 0.502146 0.704059 0.502145 +vn 0.590461 0.704059 0.394533 +vn 0.656086 0.704059 0.271758 +vn 0.517165 0.828645 0.214216 +vn 0.465436 0.828645 0.310994 +vn 0.465436 0.828645 0.310994 +vn 0.590461 0.704059 0.394533 +vn 0.656086 0.704059 0.271758 +vn 0.696496 0.704059 0.138541 +vn 0.549019 0.828645 0.109206 +vn 0.517165 0.828645 0.214216 +vn 0.517165 0.828645 0.214216 +vn 0.656086 0.704059 0.271758 +vn 0.696496 0.704059 0.138541 +vn 0.710141 0.704059 -0.000001 +vn 0.559775 0.828645 -0.000001 +vn 0.549019 0.828645 0.109206 +vn 0.549019 0.828645 0.109206 +vn 0.696496 0.704059 0.138541 +vn 0.710141 0.704059 -0.000001 +vn 0.696496 0.704059 -0.138543 +vn 0.549019 0.828645 -0.109208 +vn 0.559775 0.828645 -0.000001 +vn 0.559775 0.828645 -0.000001 +vn 0.710141 0.704059 -0.000001 +vn 0.696496 0.704059 -0.138543 +vn 0.656085 0.704059 -0.271761 +vn 0.517165 0.828645 -0.214217 +vn 0.549019 0.828645 -0.109208 +vn 0.549019 0.828645 -0.109208 +vn 0.696496 0.704059 -0.138543 +vn 0.656085 0.704059 -0.271761 +vn 0.590460 0.704059 -0.394535 +vn 0.465435 0.828645 -0.310995 +vn 0.517165 0.828645 -0.214217 +vn 0.517165 0.828645 -0.214217 +vn 0.656085 0.704059 -0.271761 +vn 0.590460 0.704059 -0.394535 +vn 0.502145 0.704059 -0.502147 +vn 0.395820 0.828645 -0.395822 +vn 0.465435 0.828645 -0.310995 +vn 0.465435 0.828645 -0.310995 +vn 0.590460 0.704059 -0.394535 +vn 0.502145 0.704059 -0.502147 +vn 0.394532 0.704059 -0.590462 +vn 0.310993 0.828645 -0.465437 +vn 0.395820 0.828645 -0.395822 +vn 0.395820 0.828645 -0.395822 +vn 0.502145 0.704059 -0.502147 +vn 0.394532 0.704059 -0.590462 +vn 0.271758 0.704059 -0.656086 +vn 0.214216 0.828645 -0.517165 +vn 0.310993 0.828645 -0.465437 +vn 0.310993 0.828645 -0.465437 +vn 0.394532 0.704059 -0.590462 +vn 0.271758 0.704059 -0.656086 +vn 0.138540 0.704059 -0.696496 +vn 0.109206 0.828645 -0.549019 +vn 0.214216 0.828645 -0.517165 +vn 0.214216 0.828645 -0.517165 +vn 0.271758 0.704059 -0.656086 +vn 0.138540 0.704059 -0.696496 +vn -0.000000 0.704059 -0.710141 +vn -0.000000 0.828645 -0.559775 +vn 0.109206 0.828645 -0.549019 +vn 0.109206 0.828645 -0.549019 +vn 0.138540 0.704059 -0.696496 +vn -0.000000 0.704059 -0.710141 +vn -0.162576 0.552761 -0.817327 +vn -0.138542 0.704059 -0.696496 +vn -0.000000 0.704059 -0.710141 +vn -0.000000 0.704059 -0.710141 +vn -0.000000 0.552761 -0.833340 +vn -0.162576 0.552761 -0.817327 +vn -0.318905 0.552761 -0.769906 +vn -0.271759 0.704059 -0.656085 +vn -0.138542 0.704059 -0.696496 +vn -0.138542 0.704059 -0.696496 +vn -0.162576 0.552761 -0.817327 +vn -0.318905 0.552761 -0.769906 +vn -0.462979 0.552761 -0.692897 +vn -0.394533 0.704059 -0.590461 +vn -0.271759 0.704059 -0.656085 +vn -0.271759 0.704059 -0.656085 +vn -0.318905 0.552761 -0.769906 +vn -0.462979 0.552761 -0.692897 +vn -0.589260 0.552761 -0.589260 +vn -0.502146 0.704059 -0.502146 +vn -0.394533 0.704059 -0.590461 +vn -0.394533 0.704059 -0.590461 +vn -0.462979 0.552761 -0.692897 +vn -0.589260 0.552761 -0.589260 +vn -0.692897 0.552761 -0.462979 +vn -0.590461 0.704059 -0.394533 +vn -0.502146 0.704059 -0.502146 +vn -0.502146 0.704059 -0.502146 +vn -0.589260 0.552761 -0.589260 +vn -0.692897 0.552761 -0.462979 +vn -0.769906 0.552761 -0.318905 +vn -0.656085 0.704059 -0.271759 +vn -0.590461 0.704059 -0.394533 +vn -0.590461 0.704059 -0.394533 +vn -0.692897 0.552761 -0.462979 +vn -0.769906 0.552761 -0.318905 +vn -0.817327 0.552761 -0.162576 +vn -0.696496 0.704059 -0.138541 +vn -0.656085 0.704059 -0.271759 +vn -0.656085 0.704059 -0.271759 +vn -0.769906 0.552761 -0.318905 +vn -0.817327 0.552761 -0.162576 +vn -0.833340 0.552761 0.000000 +vn -0.710141 0.704059 0.000000 +vn -0.696496 0.704059 -0.138541 +vn -0.696496 0.704059 -0.138541 +vn -0.817327 0.552761 -0.162576 +vn -0.833340 0.552761 0.000000 +vn -0.817327 0.552761 0.162577 +vn -0.696496 0.704059 0.138542 +vn -0.710141 0.704059 0.000000 +vn -0.710141 0.704059 0.000000 +vn -0.833340 0.552761 0.000000 +vn -0.817327 0.552761 0.162577 +vn -0.769905 0.552761 0.318906 +vn -0.656085 0.704059 0.271760 +vn -0.696496 0.704059 0.138542 +vn -0.696496 0.704059 0.138542 +vn -0.817327 0.552761 0.162577 +vn -0.769905 0.552761 0.318906 +vn -0.692896 0.552761 0.462979 +vn -0.590461 0.704059 0.394534 +vn -0.656085 0.704059 0.271760 +vn -0.656085 0.704059 0.271760 +vn -0.769905 0.552761 0.318906 +vn -0.692896 0.552761 0.462979 +vn -0.589260 0.552761 0.589260 +vn -0.502145 0.704059 0.502146 +vn -0.590461 0.704059 0.394534 +vn -0.590461 0.704059 0.394534 +vn -0.692896 0.552761 0.462979 +vn -0.589260 0.552761 0.589260 +vn -0.462978 0.552761 0.692897 +vn -0.394533 0.704059 0.590461 +vn -0.502145 0.704059 0.502146 +vn -0.502145 0.704059 0.502146 +vn -0.589260 0.552761 0.589260 +vn -0.462978 0.552761 0.692897 +vn -0.318905 0.552761 0.769906 +vn -0.271759 0.704059 0.656085 +vn -0.394533 0.704059 0.590461 +vn -0.394533 0.704059 0.590461 +vn -0.462978 0.552761 0.692897 +vn -0.318905 0.552761 0.769906 +vn -0.162576 0.552761 0.817328 +vn -0.138541 0.704059 0.696496 +vn -0.271759 0.704059 0.656085 +vn -0.271759 0.704059 0.656085 +vn -0.318905 0.552761 0.769906 +vn -0.162576 0.552761 0.817328 +vn 0.000001 0.552761 0.833340 +vn 0.000001 0.704059 0.710142 +vn -0.138541 0.704059 0.696496 +vn -0.138541 0.704059 0.696496 +vn -0.162576 0.552761 0.817328 +vn 0.000001 0.552761 0.833340 +vn 0.162577 0.552761 0.817327 +vn 0.138542 0.704059 0.696496 +vn 0.000001 0.704059 0.710142 +vn 0.000001 0.704059 0.710142 +vn 0.000001 0.552761 0.833340 +vn 0.162577 0.552761 0.817327 +vn 0.318906 0.552761 0.769905 +vn 0.271760 0.704059 0.656085 +vn 0.138542 0.704059 0.696496 +vn 0.138542 0.704059 0.696496 +vn 0.162577 0.552761 0.817327 +vn 0.318906 0.552761 0.769905 +vn 0.462980 0.552761 0.692896 +vn 0.394534 0.704059 0.590460 +vn 0.271760 0.704059 0.656085 +vn 0.271760 0.704059 0.656085 +vn 0.318906 0.552761 0.769905 +vn 0.462980 0.552761 0.692896 +vn 0.589261 0.552761 0.589259 +vn 0.502146 0.704059 0.502145 +vn 0.394534 0.704059 0.590460 +vn 0.394534 0.704059 0.590460 +vn 0.462980 0.552761 0.692896 +vn 0.589261 0.552761 0.589259 +vn 0.692897 0.552761 0.462978 +vn 0.590461 0.704059 0.394533 +vn 0.502146 0.704059 0.502145 +vn 0.502146 0.704059 0.502145 +vn 0.589261 0.552761 0.589259 +vn 0.692897 0.552761 0.462978 +vn 0.769906 0.552761 0.318904 +vn 0.656086 0.704059 0.271758 +vn 0.590461 0.704059 0.394533 +vn 0.590461 0.704059 0.394533 +vn 0.692897 0.552761 0.462978 +vn 0.769906 0.552761 0.318904 +vn 0.817328 0.552761 0.162575 +vn 0.696496 0.704059 0.138541 +vn 0.656086 0.704059 0.271758 +vn 0.656086 0.704059 0.271758 +vn 0.769906 0.552761 0.318904 +vn 0.817328 0.552761 0.162575 +vn 0.833340 0.552761 -0.000001 +vn 0.710141 0.704059 -0.000001 +vn 0.696496 0.704059 0.138541 +vn 0.696496 0.704059 0.138541 +vn 0.817328 0.552761 0.162575 +vn 0.833340 0.552761 -0.000001 +vn 0.817327 0.552761 -0.162578 +vn 0.696496 0.704059 -0.138543 +vn 0.710141 0.704059 -0.000001 +vn 0.710141 0.704059 -0.000001 +vn 0.833340 0.552761 -0.000001 +vn 0.817327 0.552761 -0.162578 +vn 0.769905 0.552761 -0.318907 +vn 0.656085 0.704059 -0.271761 +vn 0.696496 0.704059 -0.138543 +vn 0.696496 0.704059 -0.138543 +vn 0.817327 0.552761 -0.162578 +vn 0.769905 0.552761 -0.318907 +vn 0.692896 0.552761 -0.462980 +vn 0.590460 0.704059 -0.394535 +vn 0.656085 0.704059 -0.271761 +vn 0.656085 0.704059 -0.271761 +vn 0.769905 0.552761 -0.318907 +vn 0.692896 0.552761 -0.462980 +vn 0.589259 0.552761 -0.589261 +vn 0.502145 0.704059 -0.502147 +vn 0.590460 0.704059 -0.394535 +vn 0.590460 0.704059 -0.394535 +vn 0.692896 0.552761 -0.462980 +vn 0.589259 0.552761 -0.589261 +vn 0.462977 0.552761 -0.692898 +vn 0.394532 0.704059 -0.590462 +vn 0.502145 0.704059 -0.502147 +vn 0.502145 0.704059 -0.502147 +vn 0.589259 0.552761 -0.589261 +vn 0.462977 0.552761 -0.692898 +vn 0.318904 0.552761 -0.769906 +vn 0.271758 0.704059 -0.656086 +vn 0.394532 0.704059 -0.590462 +vn 0.394532 0.704059 -0.590462 +vn 0.462977 0.552761 -0.692898 +vn 0.318904 0.552761 -0.769906 +vn 0.162575 0.552761 -0.817328 +vn 0.138540 0.704059 -0.696496 +vn 0.271758 0.704059 -0.656086 +vn 0.271758 0.704059 -0.656086 +vn 0.318904 0.552761 -0.769906 +vn 0.162575 0.552761 -0.817328 +vn -0.000000 0.552761 -0.833340 +vn -0.000000 0.704059 -0.710141 +vn 0.138540 0.704059 -0.696496 +vn 0.138540 0.704059 -0.696496 +vn 0.162575 0.552761 -0.817328 +vn -0.000000 0.552761 -0.833340 +vn -0.180413 0.380537 -0.906996 +vn -0.162576 0.552761 -0.817327 +vn -0.000000 0.552761 -0.833340 +vn -0.000000 0.552761 -0.833340 +vn -0.000001 0.380537 -0.924766 +vn -0.180413 0.380537 -0.906996 +vn -0.353893 0.380537 -0.854372 +vn -0.318905 0.552761 -0.769906 +vn -0.162576 0.552761 -0.817327 +vn -0.162576 0.552761 -0.817327 +vn -0.180413 0.380537 -0.906996 +vn -0.353893 0.380537 -0.854372 +vn -0.513772 0.380537 -0.768915 +vn -0.462979 0.552761 -0.692897 +vn -0.318905 0.552761 -0.769906 +vn -0.318905 0.552761 -0.769906 +vn -0.353893 0.380537 -0.854372 +vn -0.513772 0.380537 -0.768915 +vn -0.653908 0.380537 -0.653908 +vn -0.589260 0.552761 -0.589260 +vn -0.462979 0.552761 -0.692897 +vn -0.462979 0.552761 -0.692897 +vn -0.513772 0.380537 -0.768915 +vn -0.653908 0.380537 -0.653908 +vn -0.768915 0.380537 -0.513772 +vn -0.692897 0.552761 -0.462979 +vn -0.589260 0.552761 -0.589260 +vn -0.589260 0.552761 -0.589260 +vn -0.653908 0.380537 -0.653908 +vn -0.768915 0.380537 -0.513772 +vn -0.854372 0.380537 -0.353892 +vn -0.769906 0.552761 -0.318905 +vn -0.692897 0.552761 -0.462979 +vn -0.692897 0.552761 -0.462979 +vn -0.768915 0.380537 -0.513772 +vn -0.854372 0.380537 -0.353892 +vn -0.906997 0.380537 -0.180412 +vn -0.817327 0.552761 -0.162576 +vn -0.769906 0.552761 -0.318905 +vn -0.769906 0.552761 -0.318905 +vn -0.854372 0.380537 -0.353892 +vn -0.906997 0.380537 -0.180412 +vn -0.924766 0.380537 0.000000 +vn -0.833340 0.552761 0.000000 +vn -0.817327 0.552761 -0.162576 +vn -0.817327 0.552761 -0.162576 +vn -0.906997 0.380537 -0.180412 +vn -0.924766 0.380537 0.000000 +vn -0.906996 0.380537 0.180413 +vn -0.817327 0.552761 0.162577 +vn -0.833340 0.552761 0.000000 +vn -0.833340 0.552761 0.000000 +vn -0.924766 0.380537 0.000000 +vn -0.906996 0.380537 0.180413 +vn -0.854372 0.380537 0.353893 +vn -0.769905 0.552761 0.318906 +vn -0.817327 0.552761 0.162577 +vn -0.817327 0.552761 0.162577 +vn -0.906996 0.380537 0.180413 +vn -0.854372 0.380537 0.353893 +vn -0.768914 0.380537 0.513773 +vn -0.692896 0.552761 0.462979 +vn -0.769905 0.552761 0.318906 +vn -0.769905 0.552761 0.318906 +vn -0.854372 0.380537 0.353893 +vn -0.768914 0.380537 0.513773 +vn -0.653907 0.380537 0.653908 +vn -0.589260 0.552761 0.589260 +vn -0.692896 0.552761 0.462979 +vn -0.692896 0.552761 0.462979 +vn -0.768914 0.380537 0.513773 +vn -0.653907 0.380537 0.653908 +vn -0.513772 0.380537 0.768915 +vn -0.462978 0.552761 0.692897 +vn -0.589260 0.552761 0.589260 +vn -0.589260 0.552761 0.589260 +vn -0.653907 0.380537 0.653908 +vn -0.513772 0.380537 0.768915 +vn -0.353892 0.380537 0.854372 +vn -0.318905 0.552761 0.769906 +vn -0.462978 0.552761 0.692897 +vn -0.462978 0.552761 0.692897 +vn -0.513772 0.380537 0.768915 +vn -0.353892 0.380537 0.854372 +vn -0.180412 0.380537 0.906997 +vn -0.162576 0.552761 0.817328 +vn -0.318905 0.552761 0.769906 +vn -0.318905 0.552761 0.769906 +vn -0.353892 0.380537 0.854372 +vn -0.180412 0.380537 0.906997 +vn 0.000001 0.380537 0.924766 +vn 0.000001 0.552761 0.833340 +vn -0.162576 0.552761 0.817328 +vn -0.162576 0.552761 0.817328 +vn -0.180412 0.380537 0.906997 +vn 0.000001 0.380537 0.924766 +vn 0.180414 0.380537 0.906996 +vn 0.162577 0.552761 0.817327 +vn 0.000001 0.552761 0.833340 +vn 0.000001 0.552761 0.833340 +vn 0.000001 0.380537 0.924766 +vn 0.180414 0.380537 0.906996 +vn 0.353894 0.380537 0.854372 +vn 0.318906 0.552761 0.769905 +vn 0.162577 0.552761 0.817327 +vn 0.162577 0.552761 0.817327 +vn 0.180414 0.380537 0.906996 +vn 0.353894 0.380537 0.854372 +vn 0.513773 0.380537 0.768914 +vn 0.462980 0.552761 0.692896 +vn 0.318906 0.552761 0.769905 +vn 0.318906 0.552761 0.769905 +vn 0.353894 0.380537 0.854372 +vn 0.513773 0.380537 0.768914 +vn 0.653909 0.380537 0.653907 +vn 0.589261 0.552761 0.589259 +vn 0.462980 0.552761 0.692896 +vn 0.462980 0.552761 0.692896 +vn 0.513773 0.380537 0.768914 +vn 0.653909 0.380537 0.653907 +vn 0.768915 0.380537 0.513771 +vn 0.692897 0.552761 0.462978 +vn 0.589261 0.552761 0.589259 +vn 0.589261 0.552761 0.589259 +vn 0.653909 0.380537 0.653907 +vn 0.768915 0.380537 0.513771 +vn 0.854373 0.380537 0.353891 +vn 0.769906 0.552761 0.318904 +vn 0.692897 0.552761 0.462978 +vn 0.692897 0.552761 0.462978 +vn 0.768915 0.380537 0.513771 +vn 0.854373 0.380537 0.353891 +vn 0.906997 0.380537 0.180411 +vn 0.817328 0.552761 0.162575 +vn 0.769906 0.552761 0.318904 +vn 0.769906 0.552761 0.318904 +vn 0.854373 0.380537 0.353891 +vn 0.906997 0.380537 0.180411 +vn 0.924766 0.380537 -0.000001 +vn 0.833340 0.552761 -0.000001 +vn 0.817328 0.552761 0.162575 +vn 0.817328 0.552761 0.162575 +vn 0.906997 0.380537 0.180411 +vn 0.924766 0.380537 -0.000001 +vn 0.906996 0.380537 -0.180414 +vn 0.817327 0.552761 -0.162578 +vn 0.833340 0.552761 -0.000001 +vn 0.833340 0.552761 -0.000001 +vn 0.924766 0.380537 -0.000001 +vn 0.906996 0.380537 -0.180414 +vn 0.854371 0.380537 -0.353894 +vn 0.769905 0.552761 -0.318907 +vn 0.817327 0.552761 -0.162578 +vn 0.817327 0.552761 -0.162578 +vn 0.906996 0.380537 -0.180414 +vn 0.854371 0.380537 -0.353894 +vn 0.768913 0.380537 -0.513774 +vn 0.692896 0.552761 -0.462980 +vn 0.769905 0.552761 -0.318907 +vn 0.769905 0.552761 -0.318907 +vn 0.854371 0.380537 -0.353894 +vn 0.768913 0.380537 -0.513774 +vn 0.653907 0.380537 -0.653909 +vn 0.589259 0.552761 -0.589261 +vn 0.692896 0.552761 -0.462980 +vn 0.692896 0.552761 -0.462980 +vn 0.768913 0.380537 -0.513774 +vn 0.653907 0.380537 -0.653909 +vn 0.513771 0.380537 -0.768915 +vn 0.462977 0.552761 -0.692898 +vn 0.589259 0.552761 -0.589261 +vn 0.589259 0.552761 -0.589261 +vn 0.653907 0.380537 -0.653909 +vn 0.513771 0.380537 -0.768915 +vn 0.353891 0.380537 -0.854373 +vn 0.318904 0.552761 -0.769906 +vn 0.462977 0.552761 -0.692898 +vn 0.462977 0.552761 -0.692898 +vn 0.513771 0.380537 -0.768915 +vn 0.353891 0.380537 -0.854373 +vn 0.180411 0.380537 -0.906997 +vn 0.162575 0.552761 -0.817328 +vn 0.318904 0.552761 -0.769906 +vn 0.318904 0.552761 -0.769906 +vn 0.353891 0.380537 -0.854373 +vn 0.180411 0.380537 -0.906997 +vn -0.000001 0.380537 -0.924766 +vn -0.000000 0.552761 -0.833340 +vn 0.162575 0.552761 -0.817328 +vn 0.162575 0.552761 -0.817328 +vn 0.180411 0.380537 -0.906997 +vn -0.000001 0.380537 -0.924766 +vn -0.191387 0.193930 -0.962165 +vn -0.180413 0.380537 -0.906996 +vn -0.000001 0.380537 -0.924766 +vn -0.000001 0.380537 -0.924766 +vn -0.000001 0.193930 -0.981015 +vn -0.191387 0.193930 -0.962165 +vn -0.375418 0.193930 -0.906340 +vn -0.353893 0.380537 -0.854372 +vn -0.180413 0.380537 -0.906996 +vn -0.180413 0.380537 -0.906996 +vn -0.191387 0.193930 -0.962165 +vn -0.375418 0.193930 -0.906340 +vn -0.545023 0.193930 -0.815684 +vn -0.513772 0.380537 -0.768915 +vn -0.353893 0.380537 -0.854372 +vn -0.353893 0.380537 -0.854372 +vn -0.375418 0.193930 -0.906340 +vn -0.545023 0.193930 -0.815684 +vn -0.693682 0.193930 -0.693683 +vn -0.653908 0.380537 -0.653908 +vn -0.513772 0.380537 -0.768915 +vn -0.513772 0.380537 -0.768915 +vn -0.545023 0.193930 -0.815684 +vn -0.693682 0.193930 -0.693683 +vn -0.815684 0.193930 -0.545023 +vn -0.768915 0.380537 -0.513772 +vn -0.653908 0.380537 -0.653908 +vn -0.653908 0.380537 -0.653908 +vn -0.693682 0.193930 -0.693683 +vn -0.815684 0.193930 -0.545023 +vn -0.906340 0.193930 -0.375418 +vn -0.854372 0.380537 -0.353892 +vn -0.768915 0.380537 -0.513772 +vn -0.768915 0.380537 -0.513772 +vn -0.815684 0.193930 -0.545023 +vn -0.906340 0.193930 -0.375418 +vn -0.962165 0.193930 -0.191386 +vn -0.906997 0.380537 -0.180412 +vn -0.854372 0.380537 -0.353892 +vn -0.854372 0.380537 -0.353892 +vn -0.906340 0.193930 -0.375418 +vn -0.962165 0.193930 -0.191386 +vn -0.981015 0.193930 0.000000 +vn -0.924766 0.380537 0.000000 +vn -0.906997 0.380537 -0.180412 +vn -0.906997 0.380537 -0.180412 +vn -0.962165 0.193930 -0.191386 +vn -0.981015 0.193930 0.000000 +vn -0.962165 0.193930 0.191387 +vn -0.906996 0.380537 0.180413 +vn -0.924766 0.380537 0.000000 +vn -0.924766 0.380537 0.000000 +vn -0.981015 0.193930 0.000000 +vn -0.962165 0.193930 0.191387 +vn -0.906340 0.193930 0.375419 +vn -0.854372 0.380537 0.353893 +vn -0.906996 0.380537 0.180413 +vn -0.906996 0.380537 0.180413 +vn -0.962165 0.193930 0.191387 +vn -0.906340 0.193930 0.375419 +vn -0.815684 0.193930 0.545023 +vn -0.768914 0.380537 0.513773 +vn -0.854372 0.380537 0.353893 +vn -0.854372 0.380537 0.353893 +vn -0.906340 0.193930 0.375419 +vn -0.815684 0.193930 0.545023 +vn -0.693682 0.193930 0.693683 +vn -0.653907 0.380537 0.653908 +vn -0.768914 0.380537 0.513773 +vn -0.768914 0.380537 0.513773 +vn -0.815684 0.193930 0.545023 +vn -0.693682 0.193930 0.693683 +vn -0.545022 0.193930 0.815685 +vn -0.513772 0.380537 0.768915 +vn -0.653907 0.380537 0.653908 +vn -0.653907 0.380537 0.653908 +vn -0.693682 0.193930 0.693683 +vn -0.545022 0.193930 0.815685 +vn -0.375417 0.193930 0.906340 +vn -0.353892 0.380537 0.854372 +vn -0.513772 0.380537 0.768915 +vn -0.513772 0.380537 0.768915 +vn -0.545022 0.193930 0.815685 +vn -0.375417 0.193930 0.906340 +vn -0.191386 0.193930 0.962166 +vn -0.180412 0.380537 0.906997 +vn -0.353892 0.380537 0.854372 +vn -0.353892 0.380537 0.854372 +vn -0.375417 0.193930 0.906340 +vn -0.191386 0.193930 0.962166 +vn 0.000001 0.193930 0.981015 +vn 0.000001 0.380537 0.924766 +vn -0.180412 0.380537 0.906997 +vn -0.180412 0.380537 0.906997 +vn -0.191386 0.193930 0.962166 +vn 0.000001 0.193930 0.981015 +vn 0.191388 0.193930 0.962165 +vn 0.180414 0.380537 0.906996 +vn 0.000001 0.380537 0.924766 +vn 0.000001 0.380537 0.924766 +vn 0.000001 0.193930 0.981015 +vn 0.191388 0.193930 0.962165 +vn 0.375419 0.193930 0.906339 +vn 0.353894 0.380537 0.854372 +vn 0.180414 0.380537 0.906996 +vn 0.180414 0.380537 0.906996 +vn 0.191388 0.193930 0.962165 +vn 0.375419 0.193930 0.906339 +vn 0.545024 0.193930 0.815684 +vn 0.513773 0.380537 0.768914 +vn 0.353894 0.380537 0.854372 +vn 0.353894 0.380537 0.854372 +vn 0.375419 0.193930 0.906339 +vn 0.545024 0.193930 0.815684 +vn 0.693683 0.193930 0.693682 +vn 0.653909 0.380537 0.653907 +vn 0.513773 0.380537 0.768914 +vn 0.513773 0.380537 0.768914 +vn 0.545024 0.193930 0.815684 +vn 0.693683 0.193930 0.693682 +vn 0.815685 0.193930 0.545022 +vn 0.768915 0.380537 0.513771 +vn 0.653909 0.380537 0.653907 +vn 0.653909 0.380537 0.653907 +vn 0.693683 0.193930 0.693682 +vn 0.815685 0.193930 0.545022 +vn 0.906341 0.193930 0.375417 +vn 0.854373 0.380537 0.353891 +vn 0.768915 0.380537 0.513771 +vn 0.768915 0.380537 0.513771 +vn 0.815685 0.193930 0.545022 +vn 0.906341 0.193930 0.375417 +vn 0.962166 0.193931 0.191385 +vn 0.906997 0.380537 0.180411 +vn 0.854373 0.380537 0.353891 +vn 0.854373 0.380537 0.353891 +vn 0.906341 0.193930 0.375417 +vn 0.962166 0.193931 0.191385 +vn 0.981015 0.193930 -0.000001 +vn 0.924766 0.380537 -0.000001 +vn 0.906997 0.380537 0.180411 +vn 0.906997 0.380537 0.180411 +vn 0.962166 0.193931 0.191385 +vn 0.981015 0.193930 -0.000001 +vn 0.962165 0.193930 -0.191388 +vn 0.906996 0.380537 -0.180414 +vn 0.924766 0.380537 -0.000001 +vn 0.924766 0.380537 -0.000001 +vn 0.981015 0.193930 -0.000001 +vn 0.962165 0.193930 -0.191388 +vn 0.906339 0.193930 -0.375420 +vn 0.854371 0.380537 -0.353894 +vn 0.906996 0.380537 -0.180414 +vn 0.906996 0.380537 -0.180414 +vn 0.962165 0.193930 -0.191388 +vn 0.906339 0.193930 -0.375420 +vn 0.815683 0.193930 -0.545025 +vn 0.768913 0.380537 -0.513774 +vn 0.854371 0.380537 -0.353894 +vn 0.854371 0.380537 -0.353894 +vn 0.906339 0.193930 -0.375420 +vn 0.815683 0.193930 -0.545025 +vn 0.693681 0.193930 -0.693684 +vn 0.653907 0.380537 -0.653909 +vn 0.768913 0.380537 -0.513774 +vn 0.768913 0.380537 -0.513774 +vn 0.815683 0.193930 -0.545025 +vn 0.693681 0.193930 -0.693684 +vn 0.545021 0.193931 -0.815685 +vn 0.513771 0.380537 -0.768915 +vn 0.653907 0.380537 -0.653909 +vn 0.653907 0.380537 -0.653909 +vn 0.693681 0.193930 -0.693684 +vn 0.545021 0.193931 -0.815685 +vn 0.375416 0.193930 -0.906341 +vn 0.353891 0.380537 -0.854373 +vn 0.513771 0.380537 -0.768915 +vn 0.513771 0.380537 -0.768915 +vn 0.545021 0.193931 -0.815685 +vn 0.375416 0.193930 -0.906341 +vn 0.191385 0.193930 -0.962166 +vn 0.180411 0.380537 -0.906997 +vn 0.353891 0.380537 -0.854373 +vn 0.353891 0.380537 -0.854373 +vn 0.375416 0.193930 -0.906341 +vn 0.191385 0.193930 -0.962166 +vn -0.000001 0.193930 -0.981015 +vn -0.000001 0.380537 -0.924766 +vn 0.180411 0.380537 -0.906997 +vn 0.180411 0.380537 -0.906997 +vn 0.191385 0.193930 -0.962166 +vn -0.000001 0.193930 -0.981015 +vn -0.195090 0.000000 -0.980785 +vn -0.191387 0.193930 -0.962165 +vn -0.000001 0.193930 -0.981015 +vn -0.000001 0.193930 -0.981015 +vn -0.000000 0.000000 -1.000000 +vn -0.195090 0.000000 -0.980785 +vn -0.382683 0.000000 -0.923880 +vn -0.375418 0.193930 -0.906340 +vn -0.191387 0.193930 -0.962165 +vn -0.191387 0.193930 -0.962165 +vn -0.195090 0.000000 -0.980785 +vn -0.382683 0.000000 -0.923880 +vn -0.555570 0.000000 -0.831469 +vn -0.545023 0.193930 -0.815684 +vn -0.375418 0.193930 -0.906340 +vn -0.375418 0.193930 -0.906340 +vn -0.382683 0.000000 -0.923880 +vn -0.555570 0.000000 -0.831469 +vn -0.707107 0.000000 -0.707107 +vn -0.693682 0.193930 -0.693683 +vn -0.545023 0.193930 -0.815684 +vn -0.545023 0.193930 -0.815684 +vn -0.555570 0.000000 -0.831469 +vn -0.707107 0.000000 -0.707107 +vn -0.831470 0.000000 -0.555570 +vn -0.815684 0.193930 -0.545023 +vn -0.693682 0.193930 -0.693683 +vn -0.693682 0.193930 -0.693683 +vn -0.707107 0.000000 -0.707107 +vn -0.831470 0.000000 -0.555570 +vn -0.923880 0.000000 -0.382683 +vn -0.906340 0.193930 -0.375418 +vn -0.815684 0.193930 -0.545023 +vn -0.815684 0.193930 -0.545023 +vn -0.831470 0.000000 -0.555570 +vn -0.923880 0.000000 -0.382683 +vn -0.980785 0.000000 -0.195090 +vn -0.962165 0.193930 -0.191386 +vn -0.906340 0.193930 -0.375418 +vn -0.906340 0.193930 -0.375418 +vn -0.923880 0.000000 -0.382683 +vn -0.980785 0.000000 -0.195090 +vn -1.000000 0.000000 0.000000 +vn -0.981015 0.193930 0.000000 +vn -0.962165 0.193930 -0.191386 +vn -0.962165 0.193930 -0.191386 +vn -0.980785 0.000000 -0.195090 +vn -1.000000 0.000000 0.000000 +vn -0.980785 0.000000 0.195091 +vn -0.962165 0.193930 0.191387 +vn -0.981015 0.193930 0.000000 +vn -0.981015 0.193930 0.000000 +vn -1.000000 0.000000 0.000000 +vn -0.980785 0.000000 0.195091 +vn -0.923879 0.000000 0.382684 +vn -0.906340 0.193930 0.375419 +vn -0.962165 0.193930 0.191387 +vn -0.962165 0.193930 0.191387 +vn -0.980785 0.000000 0.195091 +vn -0.923879 0.000000 0.382684 +vn -0.831469 0.000000 0.555570 +vn -0.815684 0.193930 0.545023 +vn -0.906340 0.193930 0.375419 +vn -0.906340 0.193930 0.375419 +vn -0.923879 0.000000 0.382684 +vn -0.831469 0.000000 0.555570 +vn -0.707106 0.000000 0.707107 +vn -0.693682 0.193930 0.693683 +vn -0.815684 0.193930 0.545023 +vn -0.815684 0.193930 0.545023 +vn -0.831469 0.000000 0.555570 +vn -0.707106 0.000000 0.707107 +vn -0.555570 0.000000 0.831470 +vn -0.545022 0.193930 0.815685 +vn -0.693682 0.193930 0.693683 +vn -0.693682 0.193930 0.693683 +vn -0.707106 0.000000 0.707107 +vn -0.555570 0.000000 0.831470 +vn -0.382683 0.000000 0.923880 +vn -0.375417 0.193930 0.906340 +vn -0.545022 0.193930 0.815685 +vn -0.545022 0.193930 0.815685 +vn -0.555570 0.000000 0.831470 +vn -0.382683 0.000000 0.923880 +vn -0.195090 0.000000 0.980785 +vn -0.191386 0.193930 0.962166 +vn -0.375417 0.193930 0.906340 +vn -0.375417 0.193930 0.906340 +vn -0.382683 0.000000 0.923880 +vn -0.195090 0.000000 0.980785 +vn 0.000001 0.000000 1.000000 +vn 0.000001 0.193930 0.981015 +vn -0.191386 0.193930 0.962166 +vn -0.191386 0.193930 0.962166 +vn -0.195090 0.000000 0.980785 +vn 0.000001 0.000000 1.000000 +vn 0.195092 0.000000 0.980785 +vn 0.191388 0.193930 0.962165 +vn 0.000001 0.193930 0.981015 +vn 0.000001 0.193930 0.981015 +vn 0.000001 0.000000 1.000000 +vn 0.195092 0.000000 0.980785 +vn 0.382685 0.000000 0.923879 +vn 0.375419 0.193930 0.906339 +vn 0.191388 0.193930 0.962165 +vn 0.191388 0.193930 0.962165 +vn 0.195092 0.000000 0.980785 +vn 0.382685 0.000000 0.923879 +vn 0.555571 0.000000 0.831469 +vn 0.545024 0.193930 0.815684 +vn 0.375419 0.193930 0.906339 +vn 0.375419 0.193930 0.906339 +vn 0.382685 0.000000 0.923879 +vn 0.555571 0.000000 0.831469 +vn 0.707108 0.000000 0.707106 +vn 0.693683 0.193930 0.693682 +vn 0.545024 0.193930 0.815684 +vn 0.545024 0.193930 0.815684 +vn 0.555571 0.000000 0.831469 +vn 0.707108 0.000000 0.707106 +vn 0.831470 -0.000000 0.555569 +vn 0.815685 0.193930 0.545022 +vn 0.693683 0.193930 0.693682 +vn 0.693683 0.193930 0.693682 +vn 0.707108 0.000000 0.707106 +vn 0.831470 -0.000000 0.555569 +vn 0.923880 0.000000 0.382682 +vn 0.906341 0.193930 0.375417 +vn 0.815685 0.193930 0.545022 +vn 0.815685 0.193930 0.545022 +vn 0.831470 -0.000000 0.555569 +vn 0.923880 0.000000 0.382682 +vn 0.980786 0.000000 0.195089 +vn 0.962166 0.193931 0.191385 +vn 0.906341 0.193930 0.375417 +vn 0.906341 0.193930 0.375417 +vn 0.923880 0.000000 0.382682 +vn 0.980786 0.000000 0.195089 +vn 1.000000 0.000001 -0.000002 +vn 0.981015 0.193930 -0.000001 +vn 0.962166 0.193931 0.191385 +vn 0.962166 0.193931 0.191385 +vn 0.980786 0.000000 0.195089 +vn 1.000000 0.000001 -0.000002 +vn 0.980785 0.000000 -0.195092 +vn 0.962165 0.193930 -0.191388 +vn 0.981015 0.193930 -0.000001 +vn 0.981015 0.193930 -0.000001 +vn 1.000000 0.000001 -0.000002 +vn 0.980785 0.000000 -0.195092 +vn 0.923879 -0.000000 -0.382685 +vn 0.906339 0.193930 -0.375420 +vn 0.962165 0.193930 -0.191388 +vn 0.962165 0.193930 -0.191388 +vn 0.980785 0.000000 -0.195092 +vn 0.923879 -0.000000 -0.382685 +vn 0.831469 0.000000 -0.555572 +vn 0.815683 0.193930 -0.545025 +vn 0.906339 0.193930 -0.375420 +vn 0.906339 0.193930 -0.375420 +vn 0.923879 -0.000000 -0.382685 +vn 0.831469 0.000000 -0.555572 +vn 0.707106 0.000000 -0.707108 +vn 0.693681 0.193930 -0.693684 +vn 0.815683 0.193930 -0.545025 +vn 0.815683 0.193930 -0.545025 +vn 0.831469 0.000000 -0.555572 +vn 0.707106 0.000000 -0.707108 +vn 0.555569 0.000000 -0.831471 +vn 0.545021 0.193931 -0.815685 +vn 0.693681 0.193930 -0.693684 +vn 0.693681 0.193930 -0.693684 +vn 0.707106 0.000000 -0.707108 +vn 0.555569 0.000000 -0.831471 +vn 0.382681 0.000000 -0.923880 +vn 0.375416 0.193930 -0.906341 +vn 0.545021 0.193931 -0.815685 +vn 0.545021 0.193931 -0.815685 +vn 0.555569 0.000000 -0.831471 +vn 0.382681 0.000000 -0.923880 +vn 0.195089 0.000000 -0.980786 +vn 0.191385 0.193930 -0.962166 +vn 0.375416 0.193930 -0.906341 +vn 0.375416 0.193930 -0.906341 +vn 0.382681 0.000000 -0.923880 +vn 0.195089 0.000000 -0.980786 +vn -0.000000 0.000000 -1.000000 +vn -0.000001 0.193930 -0.981015 +vn 0.191385 0.193930 -0.962166 +vn 0.191385 0.193930 -0.962166 +vn 0.195089 0.000000 -0.980786 +vn -0.000000 0.000000 -1.000000 +vn -0.191387 -0.193930 -0.962165 +vn -0.195090 0.000000 -0.980785 +vn -0.000000 0.000000 -1.000000 +vn -0.000000 0.000000 -1.000000 +vn -0.000001 -0.193930 -0.981015 +vn -0.191387 -0.193930 -0.962165 +vn -0.375418 -0.193930 -0.906340 +vn -0.382683 0.000000 -0.923880 +vn -0.195090 0.000000 -0.980785 +vn -0.195090 0.000000 -0.980785 +vn -0.191387 -0.193930 -0.962165 +vn -0.375418 -0.193930 -0.906340 +vn -0.545023 -0.193930 -0.815684 +vn -0.555570 0.000000 -0.831469 +vn -0.382683 0.000000 -0.923880 +vn -0.382683 0.000000 -0.923880 +vn -0.375418 -0.193930 -0.906340 +vn -0.545023 -0.193930 -0.815684 +vn -0.693683 -0.193930 -0.693683 +vn -0.707107 0.000000 -0.707107 +vn -0.555570 0.000000 -0.831469 +vn -0.555570 0.000000 -0.831469 +vn -0.545023 -0.193930 -0.815684 +vn -0.693683 -0.193930 -0.693683 +vn -0.815684 -0.193930 -0.545023 +vn -0.831470 0.000000 -0.555570 +vn -0.707107 0.000000 -0.707107 +vn -0.707107 0.000000 -0.707107 +vn -0.693683 -0.193930 -0.693683 +vn -0.815684 -0.193930 -0.545023 +vn -0.906340 -0.193930 -0.375418 +vn -0.923880 0.000000 -0.382683 +vn -0.831470 0.000000 -0.555570 +vn -0.831470 0.000000 -0.555570 +vn -0.815684 -0.193930 -0.545023 +vn -0.906340 -0.193930 -0.375418 +vn -0.962165 -0.193930 -0.191386 +vn -0.980785 0.000000 -0.195090 +vn -0.923880 0.000000 -0.382683 +vn -0.923880 0.000000 -0.382683 +vn -0.906340 -0.193930 -0.375418 +vn -0.962165 -0.193930 -0.191386 +vn -0.981015 -0.193930 0.000000 +vn -1.000000 0.000000 0.000000 +vn -0.980785 0.000000 -0.195090 +vn -0.980785 0.000000 -0.195090 +vn -0.962165 -0.193930 -0.191386 +vn -0.981015 -0.193930 0.000000 +vn -0.962165 -0.193930 0.191387 +vn -0.980785 0.000000 0.195091 +vn -1.000000 0.000000 0.000000 +vn -1.000000 0.000000 0.000000 +vn -0.981015 -0.193930 0.000000 +vn -0.962165 -0.193930 0.191387 +vn -0.906340 -0.193930 0.375419 +vn -0.923879 0.000000 0.382684 +vn -0.980785 0.000000 0.195091 +vn -0.980785 0.000000 0.195091 +vn -0.962165 -0.193930 0.191387 +vn -0.906340 -0.193930 0.375419 +vn -0.815684 -0.193930 0.545023 +vn -0.831469 0.000000 0.555570 +vn -0.923879 0.000000 0.382684 +vn -0.923879 0.000000 0.382684 +vn -0.906340 -0.193930 0.375419 +vn -0.815684 -0.193930 0.545023 +vn -0.693682 -0.193930 0.693683 +vn -0.707106 0.000000 0.707107 +vn -0.831469 0.000000 0.555570 +vn -0.831469 0.000000 0.555570 +vn -0.815684 -0.193930 0.545023 +vn -0.693682 -0.193930 0.693683 +vn -0.545023 -0.193930 0.815685 +vn -0.555570 0.000000 0.831470 +vn -0.707106 0.000000 0.707107 +vn -0.707106 0.000000 0.707107 +vn -0.693682 -0.193930 0.693683 +vn -0.545023 -0.193930 0.815685 +vn -0.375417 -0.193930 0.906340 +vn -0.382683 0.000000 0.923880 +vn -0.555570 0.000000 0.831470 +vn -0.555570 0.000000 0.831470 +vn -0.545023 -0.193930 0.815685 +vn -0.375417 -0.193930 0.906340 +vn -0.191386 -0.193930 0.962166 +vn -0.195090 0.000000 0.980785 +vn -0.382683 0.000000 0.923880 +vn -0.382683 0.000000 0.923880 +vn -0.375417 -0.193930 0.906340 +vn -0.191386 -0.193930 0.962166 +vn 0.000001 -0.193930 0.981015 +vn 0.000001 0.000000 1.000000 +vn -0.195090 0.000000 0.980785 +vn -0.195090 0.000000 0.980785 +vn -0.191386 -0.193930 0.962166 +vn 0.000001 -0.193930 0.981015 +vn 0.191388 -0.193930 0.962165 +vn 0.195092 0.000000 0.980785 +vn 0.000001 0.000000 1.000000 +vn 0.000001 0.000000 1.000000 +vn 0.000001 -0.193930 0.981015 +vn 0.191388 -0.193930 0.962165 +vn 0.375419 -0.193930 0.906340 +vn 0.382685 0.000000 0.923879 +vn 0.195092 0.000000 0.980785 +vn 0.195092 0.000000 0.980785 +vn 0.191388 -0.193930 0.962165 +vn 0.375419 -0.193930 0.906340 +vn 0.545024 -0.193930 0.815684 +vn 0.555571 0.000000 0.831469 +vn 0.382685 0.000000 0.923879 +vn 0.382685 0.000000 0.923879 +vn 0.375419 -0.193930 0.906340 +vn 0.545024 -0.193930 0.815684 +vn 0.693684 -0.193930 0.693682 +vn 0.707108 0.000000 0.707106 +vn 0.555571 0.000000 0.831469 +vn 0.555571 0.000000 0.831469 +vn 0.545024 -0.193930 0.815684 +vn 0.693684 -0.193930 0.693682 +vn 0.815685 -0.193930 0.545022 +vn 0.831470 -0.000000 0.555569 +vn 0.707108 0.000000 0.707106 +vn 0.707108 0.000000 0.707106 +vn 0.693684 -0.193930 0.693682 +vn 0.815685 -0.193930 0.545022 +vn 0.906340 -0.193930 0.375417 +vn 0.923880 0.000000 0.382682 +vn 0.831470 -0.000000 0.555569 +vn 0.831470 -0.000000 0.555569 +vn 0.815685 -0.193930 0.545022 +vn 0.906340 -0.193930 0.375417 +vn 0.962166 -0.193930 0.191385 +vn 0.980786 0.000000 0.195089 +vn 0.923880 0.000000 0.382682 +vn 0.923880 0.000000 0.382682 +vn 0.906340 -0.193930 0.375417 +vn 0.962166 -0.193930 0.191385 +vn 0.981015 -0.193930 -0.000002 +vn 1.000000 0.000001 -0.000002 +vn 0.980786 0.000000 0.195089 +vn 0.980786 0.000000 0.195089 +vn 0.962166 -0.193930 0.191385 +vn 0.981015 -0.193930 -0.000002 +vn 0.962165 -0.193930 -0.191388 +vn 0.980785 0.000000 -0.195092 +vn 1.000000 0.000001 -0.000002 +vn 1.000000 0.000001 -0.000002 +vn 0.981015 -0.193930 -0.000002 +vn 0.962165 -0.193930 -0.191388 +vn 0.906339 -0.193930 -0.375420 +vn 0.923879 -0.000000 -0.382685 +vn 0.980785 0.000000 -0.195092 +vn 0.980785 0.000000 -0.195092 +vn 0.962165 -0.193930 -0.191388 +vn 0.906339 -0.193930 -0.375420 +vn 0.815684 -0.193930 -0.545024 +vn 0.831469 0.000000 -0.555572 +vn 0.923879 -0.000000 -0.382685 +vn 0.923879 -0.000000 -0.382685 +vn 0.906339 -0.193930 -0.375420 +vn 0.815684 -0.193930 -0.545024 +vn 0.693681 -0.193930 -0.693684 +vn 0.707106 0.000000 -0.707108 +vn 0.831469 0.000000 -0.555572 +vn 0.831469 0.000000 -0.555572 +vn 0.815684 -0.193930 -0.545024 +vn 0.693681 -0.193930 -0.693684 +vn 0.545021 -0.193930 -0.815686 +vn 0.555569 0.000000 -0.831471 +vn 0.707106 0.000000 -0.707108 +vn 0.707106 0.000000 -0.707108 +vn 0.693681 -0.193930 -0.693684 +vn 0.545021 -0.193930 -0.815686 +vn 0.375416 -0.193930 -0.906341 +vn 0.382681 0.000000 -0.923880 +vn 0.555569 0.000000 -0.831471 +vn 0.555569 0.000000 -0.831471 +vn 0.545021 -0.193930 -0.815686 +vn 0.375416 -0.193930 -0.906341 +vn 0.191385 -0.193930 -0.962166 +vn 0.195089 0.000000 -0.980786 +vn 0.382681 0.000000 -0.923880 +vn 0.382681 0.000000 -0.923880 +vn 0.375416 -0.193930 -0.906341 +vn 0.191385 -0.193930 -0.962166 +vn -0.000001 -0.193930 -0.981015 +vn -0.000000 0.000000 -1.000000 +vn 0.195089 0.000000 -0.980786 +vn 0.195089 0.000000 -0.980786 +vn 0.191385 -0.193930 -0.962166 +vn -0.000001 -0.193930 -0.981015 +vn -0.180413 -0.380537 -0.906996 +vn -0.191387 -0.193930 -0.962165 +vn -0.000001 -0.193930 -0.981015 +vn -0.000001 -0.193930 -0.981015 +vn -0.000001 -0.380537 -0.924766 +vn -0.180413 -0.380537 -0.906996 +vn -0.353893 -0.380537 -0.854372 +vn -0.375418 -0.193930 -0.906340 +vn -0.191387 -0.193930 -0.962165 +vn -0.191387 -0.193930 -0.962165 +vn -0.180413 -0.380537 -0.906996 +vn -0.353893 -0.380537 -0.854372 +vn -0.513772 -0.380537 -0.768914 +vn -0.545023 -0.193930 -0.815684 +vn -0.375418 -0.193930 -0.906340 +vn -0.375418 -0.193930 -0.906340 +vn -0.353893 -0.380537 -0.854372 +vn -0.513772 -0.380537 -0.768914 +vn -0.653908 -0.380537 -0.653908 +vn -0.693683 -0.193930 -0.693683 +vn -0.545023 -0.193930 -0.815684 +vn -0.545023 -0.193930 -0.815684 +vn -0.513772 -0.380537 -0.768914 +vn -0.653908 -0.380537 -0.653908 +vn -0.768914 -0.380537 -0.513772 +vn -0.815684 -0.193930 -0.545023 +vn -0.693683 -0.193930 -0.693683 +vn -0.693683 -0.193930 -0.693683 +vn -0.653908 -0.380537 -0.653908 +vn -0.768914 -0.380537 -0.513772 +vn -0.854372 -0.380537 -0.353892 +vn -0.906340 -0.193930 -0.375418 +vn -0.815684 -0.193930 -0.545023 +vn -0.815684 -0.193930 -0.545023 +vn -0.768914 -0.380537 -0.513772 +vn -0.854372 -0.380537 -0.353892 +vn -0.906996 -0.380537 -0.180413 +vn -0.962165 -0.193930 -0.191386 +vn -0.906340 -0.193930 -0.375418 +vn -0.906340 -0.193930 -0.375418 +vn -0.854372 -0.380537 -0.353892 +vn -0.906996 -0.380537 -0.180413 +vn -0.924766 -0.380537 0.000000 +vn -0.981015 -0.193930 0.000000 +vn -0.962165 -0.193930 -0.191386 +vn -0.962165 -0.193930 -0.191386 +vn -0.906996 -0.380537 -0.180413 +vn -0.924766 -0.380537 0.000000 +vn -0.906996 -0.380537 0.180413 +vn -0.962165 -0.193930 0.191387 +vn -0.981015 -0.193930 0.000000 +vn -0.981015 -0.193930 0.000000 +vn -0.924766 -0.380537 0.000000 +vn -0.906996 -0.380537 0.180413 +vn -0.854372 -0.380537 0.353893 +vn -0.906340 -0.193930 0.375419 +vn -0.962165 -0.193930 0.191387 +vn -0.962165 -0.193930 0.191387 +vn -0.906996 -0.380537 0.180413 +vn -0.854372 -0.380537 0.353893 +vn -0.768914 -0.380537 0.513773 +vn -0.815684 -0.193930 0.545023 +vn -0.906340 -0.193930 0.375419 +vn -0.906340 -0.193930 0.375419 +vn -0.854372 -0.380537 0.353893 +vn -0.768914 -0.380537 0.513773 +vn -0.653908 -0.380537 0.653908 +vn -0.693682 -0.193930 0.693683 +vn -0.815684 -0.193930 0.545023 +vn -0.815684 -0.193930 0.545023 +vn -0.768914 -0.380537 0.513773 +vn -0.653908 -0.380537 0.653908 +vn -0.513772 -0.380537 0.768915 +vn -0.545023 -0.193930 0.815685 +vn -0.693682 -0.193930 0.693683 +vn -0.693682 -0.193930 0.693683 +vn -0.653908 -0.380537 0.653908 +vn -0.513772 -0.380537 0.768915 +vn -0.353892 -0.380537 0.854372 +vn -0.375417 -0.193930 0.906340 +vn -0.545023 -0.193930 0.815685 +vn -0.545023 -0.193930 0.815685 +vn -0.513772 -0.380537 0.768915 +vn -0.353892 -0.380537 0.854372 +vn -0.180412 -0.380537 0.906997 +vn -0.191386 -0.193930 0.962166 +vn -0.375417 -0.193930 0.906340 +vn -0.375417 -0.193930 0.906340 +vn -0.353892 -0.380537 0.854372 +vn -0.180412 -0.380537 0.906997 +vn 0.000001 -0.380537 0.924766 +vn 0.000001 -0.193930 0.981015 +vn -0.191386 -0.193930 0.962166 +vn -0.191386 -0.193930 0.962166 +vn -0.180412 -0.380537 0.906997 +vn 0.000001 -0.380537 0.924766 +vn 0.180414 -0.380537 0.906996 +vn 0.191388 -0.193930 0.962165 +vn 0.000001 -0.193930 0.981015 +vn 0.000001 -0.193930 0.981015 +vn 0.000001 -0.380537 0.924766 +vn 0.180414 -0.380537 0.906996 +vn 0.353893 -0.380537 0.854372 +vn 0.375419 -0.193930 0.906340 +vn 0.191388 -0.193930 0.962165 +vn 0.191388 -0.193930 0.962165 +vn 0.180414 -0.380537 0.906996 +vn 0.353893 -0.380537 0.854372 +vn 0.513773 -0.380537 0.768914 +vn 0.545024 -0.193930 0.815684 +vn 0.375419 -0.193930 0.906340 +vn 0.375419 -0.193930 0.906340 +vn 0.353893 -0.380537 0.854372 +vn 0.513773 -0.380537 0.768914 +vn 0.653909 -0.380537 0.653907 +vn 0.693684 -0.193930 0.693682 +vn 0.545024 -0.193930 0.815684 +vn 0.545024 -0.193930 0.815684 +vn 0.513773 -0.380537 0.768914 +vn 0.653909 -0.380537 0.653907 +vn 0.768915 -0.380537 0.513771 +vn 0.815685 -0.193930 0.545022 +vn 0.693684 -0.193930 0.693682 +vn 0.693684 -0.193930 0.693682 +vn 0.653909 -0.380537 0.653907 +vn 0.768915 -0.380537 0.513771 +vn 0.854373 -0.380537 0.353891 +vn 0.906340 -0.193930 0.375417 +vn 0.815685 -0.193930 0.545022 +vn 0.815685 -0.193930 0.545022 +vn 0.768915 -0.380537 0.513771 +vn 0.854373 -0.380537 0.353891 +vn 0.906997 -0.380537 0.180411 +vn 0.962166 -0.193930 0.191385 +vn 0.906340 -0.193930 0.375417 +vn 0.906340 -0.193930 0.375417 +vn 0.854373 -0.380537 0.353891 +vn 0.906997 -0.380537 0.180411 +vn 0.924766 -0.380537 -0.000002 +vn 0.981015 -0.193930 -0.000002 +vn 0.962166 -0.193930 0.191385 +vn 0.962166 -0.193930 0.191385 +vn 0.906997 -0.380537 0.180411 +vn 0.924766 -0.380537 -0.000002 +vn 0.906996 -0.380537 -0.180414 +vn 0.962165 -0.193930 -0.191388 +vn 0.981015 -0.193930 -0.000002 +vn 0.981015 -0.193930 -0.000002 +vn 0.924766 -0.380537 -0.000002 +vn 0.906996 -0.380537 -0.180414 +vn 0.854371 -0.380537 -0.353894 +vn 0.906339 -0.193930 -0.375420 +vn 0.962165 -0.193930 -0.191388 +vn 0.962165 -0.193930 -0.191388 +vn 0.906996 -0.380537 -0.180414 +vn 0.854371 -0.380537 -0.353894 +vn 0.768914 -0.380537 -0.513774 +vn 0.815684 -0.193930 -0.545024 +vn 0.906339 -0.193930 -0.375420 +vn 0.906339 -0.193930 -0.375420 +vn 0.854371 -0.380537 -0.353894 +vn 0.768914 -0.380537 -0.513774 +vn 0.653907 -0.380537 -0.653909 +vn 0.693681 -0.193930 -0.693684 +vn 0.815684 -0.193930 -0.545024 +vn 0.815684 -0.193930 -0.545024 +vn 0.768914 -0.380537 -0.513774 +vn 0.653907 -0.380537 -0.653909 +vn 0.513770 -0.380537 -0.768916 +vn 0.545021 -0.193930 -0.815686 +vn 0.693681 -0.193930 -0.693684 +vn 0.693681 -0.193930 -0.693684 +vn 0.653907 -0.380537 -0.653909 +vn 0.513770 -0.380537 -0.768916 +vn 0.353891 -0.380537 -0.854373 +vn 0.375416 -0.193930 -0.906341 +vn 0.545021 -0.193930 -0.815686 +vn 0.545021 -0.193930 -0.815686 +vn 0.513770 -0.380537 -0.768916 +vn 0.353891 -0.380537 -0.854373 +vn 0.180412 -0.380537 -0.906997 +vn 0.191385 -0.193930 -0.962166 +vn 0.375416 -0.193930 -0.906341 +vn 0.375416 -0.193930 -0.906341 +vn 0.353891 -0.380537 -0.854373 +vn 0.180412 -0.380537 -0.906997 +vn -0.000001 -0.380537 -0.924766 +vn -0.000001 -0.193930 -0.981015 +vn 0.191385 -0.193930 -0.962166 +vn 0.191385 -0.193930 -0.962166 +vn 0.180412 -0.380537 -0.906997 +vn -0.000001 -0.380537 -0.924766 +vn -0.162576 -0.552761 -0.817327 +vn -0.180413 -0.380537 -0.906996 +vn -0.000001 -0.380537 -0.924766 +vn -0.000001 -0.380537 -0.924766 +vn -0.000001 -0.552761 -0.833340 +vn -0.162576 -0.552761 -0.817327 +vn -0.318905 -0.552761 -0.769906 +vn -0.353893 -0.380537 -0.854372 +vn -0.180413 -0.380537 -0.906996 +vn -0.180413 -0.380537 -0.906996 +vn -0.162576 -0.552761 -0.817327 +vn -0.318905 -0.552761 -0.769906 +vn -0.462979 -0.552761 -0.692897 +vn -0.513772 -0.380537 -0.768914 +vn -0.353893 -0.380537 -0.854372 +vn -0.353893 -0.380537 -0.854372 +vn -0.318905 -0.552761 -0.769906 +vn -0.462979 -0.552761 -0.692897 +vn -0.589260 -0.552761 -0.589260 +vn -0.653908 -0.380537 -0.653908 +vn -0.513772 -0.380537 -0.768914 +vn -0.513772 -0.380537 -0.768914 +vn -0.462979 -0.552761 -0.692897 +vn -0.589260 -0.552761 -0.589260 +vn -0.692897 -0.552761 -0.462979 +vn -0.768914 -0.380537 -0.513772 +vn -0.653908 -0.380537 -0.653908 +vn -0.653908 -0.380537 -0.653908 +vn -0.589260 -0.552761 -0.589260 +vn -0.692897 -0.552761 -0.462979 +vn -0.769906 -0.552761 -0.318905 +vn -0.854372 -0.380537 -0.353892 +vn -0.768914 -0.380537 -0.513772 +vn -0.768914 -0.380537 -0.513772 +vn -0.692897 -0.552761 -0.462979 +vn -0.769906 -0.552761 -0.318905 +vn -0.817327 -0.552761 -0.162576 +vn -0.906996 -0.380537 -0.180413 +vn -0.854372 -0.380537 -0.353892 +vn -0.854372 -0.380537 -0.353892 +vn -0.769906 -0.552761 -0.318905 +vn -0.817327 -0.552761 -0.162576 +vn -0.833340 -0.552761 0.000000 +vn -0.924766 -0.380537 0.000000 +vn -0.906996 -0.380537 -0.180413 +vn -0.906996 -0.380537 -0.180413 +vn -0.817327 -0.552761 -0.162576 +vn -0.833340 -0.552761 0.000000 +vn -0.817327 -0.552761 0.162577 +vn -0.906996 -0.380537 0.180413 +vn -0.924766 -0.380537 0.000000 +vn -0.924766 -0.380537 0.000000 +vn -0.833340 -0.552761 0.000000 +vn -0.817327 -0.552761 0.162577 +vn -0.769905 -0.552761 0.318906 +vn -0.854372 -0.380537 0.353893 +vn -0.906996 -0.380537 0.180413 +vn -0.906996 -0.380537 0.180413 +vn -0.817327 -0.552761 0.162577 +vn -0.769905 -0.552761 0.318906 +vn -0.692896 -0.552761 0.462979 +vn -0.768914 -0.380537 0.513773 +vn -0.854372 -0.380537 0.353893 +vn -0.854372 -0.380537 0.353893 +vn -0.769905 -0.552761 0.318906 +vn -0.692896 -0.552761 0.462979 +vn -0.589260 -0.552761 0.589260 +vn -0.653908 -0.380537 0.653908 +vn -0.768914 -0.380537 0.513773 +vn -0.768914 -0.380537 0.513773 +vn -0.692896 -0.552761 0.462979 +vn -0.589260 -0.552761 0.589260 +vn -0.462978 -0.552761 0.692897 +vn -0.513772 -0.380537 0.768915 +vn -0.653908 -0.380537 0.653908 +vn -0.653908 -0.380537 0.653908 +vn -0.589260 -0.552761 0.589260 +vn -0.462978 -0.552761 0.692897 +vn -0.318905 -0.552761 0.769906 +vn -0.353892 -0.380537 0.854372 +vn -0.513772 -0.380537 0.768915 +vn -0.513772 -0.380537 0.768915 +vn -0.462978 -0.552761 0.692897 +vn -0.318905 -0.552761 0.769906 +vn -0.162576 -0.552761 0.817327 +vn -0.180412 -0.380537 0.906997 +vn -0.353892 -0.380537 0.854372 +vn -0.353892 -0.380537 0.854372 +vn -0.318905 -0.552761 0.769906 +vn -0.162576 -0.552761 0.817327 +vn 0.000001 -0.552761 0.833340 +vn 0.000001 -0.380537 0.924766 +vn -0.180412 -0.380537 0.906997 +vn -0.180412 -0.380537 0.906997 +vn -0.162576 -0.552761 0.817327 +vn 0.000001 -0.552761 0.833340 +vn 0.162577 -0.552761 0.817327 +vn 0.180414 -0.380537 0.906996 +vn 0.000001 -0.380537 0.924766 +vn 0.000001 -0.380537 0.924766 +vn 0.000001 -0.552761 0.833340 +vn 0.162577 -0.552761 0.817327 +vn 0.318906 -0.552761 0.769905 +vn 0.353893 -0.380537 0.854372 +vn 0.180414 -0.380537 0.906996 +vn 0.180414 -0.380537 0.906996 +vn 0.162577 -0.552761 0.817327 +vn 0.318906 -0.552761 0.769905 +vn 0.462979 -0.552761 0.692896 +vn 0.513773 -0.380537 0.768914 +vn 0.353893 -0.380537 0.854372 +vn 0.353893 -0.380537 0.854372 +vn 0.318906 -0.552761 0.769905 +vn 0.462979 -0.552761 0.692896 +vn 0.589261 -0.552761 0.589259 +vn 0.653909 -0.380537 0.653907 +vn 0.513773 -0.380537 0.768914 +vn 0.513773 -0.380537 0.768914 +vn 0.462979 -0.552761 0.692896 +vn 0.589261 -0.552761 0.589259 +vn 0.692897 -0.552761 0.462978 +vn 0.768915 -0.380537 0.513771 +vn 0.653909 -0.380537 0.653907 +vn 0.653909 -0.380537 0.653907 +vn 0.589261 -0.552761 0.589259 +vn 0.692897 -0.552761 0.462978 +vn 0.769906 -0.552761 0.318904 +vn 0.854373 -0.380537 0.353891 +vn 0.768915 -0.380537 0.513771 +vn 0.768915 -0.380537 0.513771 +vn 0.692897 -0.552761 0.462978 +vn 0.769906 -0.552761 0.318904 +vn 0.817327 -0.552761 0.162576 +vn 0.906997 -0.380537 0.180411 +vn 0.854373 -0.380537 0.353891 +vn 0.854373 -0.380537 0.353891 +vn 0.769906 -0.552761 0.318904 +vn 0.817327 -0.552761 0.162576 +vn 0.833340 -0.552761 -0.000001 +vn 0.924766 -0.380537 -0.000002 +vn 0.906997 -0.380537 0.180411 +vn 0.906997 -0.380537 0.180411 +vn 0.817327 -0.552761 0.162576 +vn 0.833340 -0.552761 -0.000001 +vn 0.817327 -0.552761 -0.162578 +vn 0.906996 -0.380537 -0.180414 +vn 0.924766 -0.380537 -0.000002 +vn 0.924766 -0.380537 -0.000002 +vn 0.833340 -0.552761 -0.000001 +vn 0.817327 -0.552761 -0.162578 +vn 0.769905 -0.552761 -0.318907 +vn 0.854371 -0.380537 -0.353894 +vn 0.906996 -0.380537 -0.180414 +vn 0.906996 -0.380537 -0.180414 +vn 0.817327 -0.552761 -0.162578 +vn 0.769905 -0.552761 -0.318907 +vn 0.692896 -0.552761 -0.462980 +vn 0.768914 -0.380537 -0.513774 +vn 0.854371 -0.380537 -0.353894 +vn 0.854371 -0.380537 -0.353894 +vn 0.769905 -0.552761 -0.318907 +vn 0.692896 -0.552761 -0.462980 +vn 0.589259 -0.552761 -0.589261 +vn 0.653907 -0.380537 -0.653909 +vn 0.768914 -0.380537 -0.513774 +vn 0.768914 -0.380537 -0.513774 +vn 0.692896 -0.552761 -0.462980 +vn 0.589259 -0.552761 -0.589261 +vn 0.462977 -0.552761 -0.692898 +vn 0.513770 -0.380537 -0.768916 +vn 0.653907 -0.380537 -0.653909 +vn 0.653907 -0.380537 -0.653909 +vn 0.589259 -0.552761 -0.589261 +vn 0.462977 -0.552761 -0.692898 +vn 0.318904 -0.552761 -0.769906 +vn 0.353891 -0.380537 -0.854373 +vn 0.513770 -0.380537 -0.768916 +vn 0.513770 -0.380537 -0.768916 +vn 0.462977 -0.552761 -0.692898 +vn 0.318904 -0.552761 -0.769906 +vn 0.162575 -0.552761 -0.817328 +vn 0.180412 -0.380537 -0.906997 +vn 0.353891 -0.380537 -0.854373 +vn 0.353891 -0.380537 -0.854373 +vn 0.318904 -0.552761 -0.769906 +vn 0.162575 -0.552761 -0.817328 +vn -0.000001 -0.552761 -0.833340 +vn -0.000001 -0.380537 -0.924766 +vn 0.180412 -0.380537 -0.906997 +vn 0.180412 -0.380537 -0.906997 +vn 0.162575 -0.552761 -0.817328 +vn -0.000001 -0.552761 -0.833340 +vn -0.138542 -0.704059 -0.696496 +vn -0.162576 -0.552761 -0.817327 +vn -0.000001 -0.552761 -0.833340 +vn -0.000001 -0.552761 -0.833340 +vn -0.000000 -0.704059 -0.710141 +vn -0.138542 -0.704059 -0.696496 +vn -0.271759 -0.704059 -0.656085 +vn -0.318905 -0.552761 -0.769906 +vn -0.162576 -0.552761 -0.817327 +vn -0.162576 -0.552761 -0.817327 +vn -0.138542 -0.704059 -0.696496 +vn -0.271759 -0.704059 -0.656085 +vn -0.394533 -0.704059 -0.590461 +vn -0.462979 -0.552761 -0.692897 +vn -0.318905 -0.552761 -0.769906 +vn -0.318905 -0.552761 -0.769906 +vn -0.271759 -0.704059 -0.656085 +vn -0.394533 -0.704059 -0.590461 +vn -0.502146 -0.704059 -0.502146 +vn -0.589260 -0.552761 -0.589260 +vn -0.462979 -0.552761 -0.692897 +vn -0.462979 -0.552761 -0.692897 +vn -0.394533 -0.704059 -0.590461 +vn -0.502146 -0.704059 -0.502146 +vn -0.590461 -0.704059 -0.394533 +vn -0.692897 -0.552761 -0.462979 +vn -0.589260 -0.552761 -0.589260 +vn -0.589260 -0.552761 -0.589260 +vn -0.502146 -0.704059 -0.502146 +vn -0.590461 -0.704059 -0.394533 +vn -0.656085 -0.704059 -0.271759 +vn -0.769906 -0.552761 -0.318905 +vn -0.692897 -0.552761 -0.462979 +vn -0.692897 -0.552761 -0.462979 +vn -0.590461 -0.704059 -0.394533 +vn -0.656085 -0.704059 -0.271759 +vn -0.696496 -0.704059 -0.138541 +vn -0.817327 -0.552761 -0.162576 +vn -0.769906 -0.552761 -0.318905 +vn -0.769906 -0.552761 -0.318905 +vn -0.656085 -0.704059 -0.271759 +vn -0.696496 -0.704059 -0.138541 +vn -0.710141 -0.704059 0.000000 +vn -0.833340 -0.552761 0.000000 +vn -0.817327 -0.552761 -0.162576 +vn -0.817327 -0.552761 -0.162576 +vn -0.696496 -0.704059 -0.138541 +vn -0.710141 -0.704059 0.000000 +vn -0.696496 -0.704059 0.138542 +vn -0.817327 -0.552761 0.162577 +vn -0.833340 -0.552761 0.000000 +vn -0.833340 -0.552761 0.000000 +vn -0.710141 -0.704059 0.000000 +vn -0.696496 -0.704059 0.138542 +vn -0.656085 -0.704059 0.271760 +vn -0.769905 -0.552761 0.318906 +vn -0.817327 -0.552761 0.162577 +vn -0.817327 -0.552761 0.162577 +vn -0.696496 -0.704059 0.138542 +vn -0.656085 -0.704059 0.271760 +vn -0.590461 -0.704059 0.394534 +vn -0.692896 -0.552761 0.462979 +vn -0.769905 -0.552761 0.318906 +vn -0.769905 -0.552761 0.318906 +vn -0.656085 -0.704059 0.271760 +vn -0.590461 -0.704059 0.394534 +vn -0.502146 -0.704059 0.502146 +vn -0.589260 -0.552761 0.589260 +vn -0.692896 -0.552761 0.462979 +vn -0.692896 -0.552761 0.462979 +vn -0.590461 -0.704059 0.394534 +vn -0.502146 -0.704059 0.502146 +vn -0.394533 -0.704059 0.590461 +vn -0.462978 -0.552761 0.692897 +vn -0.589260 -0.552761 0.589260 +vn -0.589260 -0.552761 0.589260 +vn -0.502146 -0.704059 0.502146 +vn -0.394533 -0.704059 0.590461 +vn -0.271759 -0.704059 0.656085 +vn -0.318905 -0.552761 0.769906 +vn -0.462978 -0.552761 0.692897 +vn -0.462978 -0.552761 0.692897 +vn -0.394533 -0.704059 0.590461 +vn -0.271759 -0.704059 0.656085 +vn -0.138541 -0.704059 0.696496 +vn -0.162576 -0.552761 0.817327 +vn -0.318905 -0.552761 0.769906 +vn -0.318905 -0.552761 0.769906 +vn -0.271759 -0.704059 0.656085 +vn -0.138541 -0.704059 0.696496 +vn 0.000001 -0.704059 0.710142 +vn 0.000001 -0.552761 0.833340 +vn -0.162576 -0.552761 0.817327 +vn -0.162576 -0.552761 0.817327 +vn -0.138541 -0.704059 0.696496 +vn 0.000001 -0.704059 0.710142 +vn 0.138542 -0.704059 0.696496 +vn 0.162577 -0.552761 0.817327 +vn 0.000001 -0.552761 0.833340 +vn 0.000001 -0.552761 0.833340 +vn 0.000001 -0.704059 0.710142 +vn 0.138542 -0.704059 0.696496 +vn 0.271760 -0.704059 0.656085 +vn 0.318906 -0.552761 0.769905 +vn 0.162577 -0.552761 0.817327 +vn 0.162577 -0.552761 0.817327 +vn 0.138542 -0.704059 0.696496 +vn 0.271760 -0.704059 0.656085 +vn 0.394534 -0.704059 0.590461 +vn 0.462979 -0.552761 0.692896 +vn 0.318906 -0.552761 0.769905 +vn 0.318906 -0.552761 0.769905 +vn 0.271760 -0.704059 0.656085 +vn 0.394534 -0.704059 0.590461 +vn 0.502146 -0.704059 0.502145 +vn 0.589261 -0.552761 0.589259 +vn 0.462979 -0.552761 0.692896 +vn 0.462979 -0.552761 0.692896 +vn 0.394534 -0.704059 0.590461 +vn 0.502146 -0.704059 0.502145 +vn 0.590462 -0.704059 0.394533 +vn 0.692897 -0.552761 0.462978 +vn 0.589261 -0.552761 0.589259 +vn 0.589261 -0.552761 0.589259 +vn 0.502146 -0.704059 0.502145 +vn 0.590462 -0.704059 0.394533 +vn 0.656086 -0.704059 0.271758 +vn 0.769906 -0.552761 0.318904 +vn 0.692897 -0.552761 0.462978 +vn 0.692897 -0.552761 0.462978 +vn 0.590462 -0.704059 0.394533 +vn 0.656086 -0.704059 0.271758 +vn 0.696496 -0.704059 0.138541 +vn 0.817327 -0.552761 0.162576 +vn 0.769906 -0.552761 0.318904 +vn 0.769906 -0.552761 0.318904 +vn 0.656086 -0.704059 0.271758 +vn 0.696496 -0.704059 0.138541 +vn 0.710141 -0.704059 -0.000001 +vn 0.833340 -0.552761 -0.000001 +vn 0.817327 -0.552761 0.162576 +vn 0.817327 -0.552761 0.162576 +vn 0.696496 -0.704059 0.138541 +vn 0.710141 -0.704059 -0.000001 +vn 0.696496 -0.704059 -0.138543 +vn 0.817327 -0.552761 -0.162578 +vn 0.833340 -0.552761 -0.000001 +vn 0.833340 -0.552761 -0.000001 +vn 0.710141 -0.704059 -0.000001 +vn 0.696496 -0.704059 -0.138543 +vn 0.656085 -0.704059 -0.271761 +vn 0.769905 -0.552761 -0.318907 +vn 0.817327 -0.552761 -0.162578 +vn 0.817327 -0.552761 -0.162578 +vn 0.696496 -0.704059 -0.138543 +vn 0.656085 -0.704059 -0.271761 +vn 0.590460 -0.704059 -0.394535 +vn 0.692896 -0.552761 -0.462980 +vn 0.769905 -0.552761 -0.318907 +vn 0.769905 -0.552761 -0.318907 +vn 0.656085 -0.704059 -0.271761 +vn 0.590460 -0.704059 -0.394535 +vn 0.502145 -0.704059 -0.502147 +vn 0.589259 -0.552761 -0.589261 +vn 0.692896 -0.552761 -0.462980 +vn 0.692896 -0.552761 -0.462980 +vn 0.590460 -0.704059 -0.394535 +vn 0.502145 -0.704059 -0.502147 +vn 0.394532 -0.704059 -0.590462 +vn 0.462977 -0.552761 -0.692898 +vn 0.589259 -0.552761 -0.589261 +vn 0.589259 -0.552761 -0.589261 +vn 0.502145 -0.704059 -0.502147 +vn 0.394532 -0.704059 -0.590462 +vn 0.271758 -0.704059 -0.656086 +vn 0.318904 -0.552761 -0.769906 +vn 0.462977 -0.552761 -0.692898 +vn 0.462977 -0.552761 -0.692898 +vn 0.394532 -0.704059 -0.590462 +vn 0.271758 -0.704059 -0.656086 +vn 0.138541 -0.704059 -0.696497 +vn 0.162575 -0.552761 -0.817328 +vn 0.318904 -0.552761 -0.769906 +vn 0.318904 -0.552761 -0.769906 +vn 0.271758 -0.704059 -0.656086 +vn 0.138541 -0.704059 -0.696497 +vn -0.000000 -0.704059 -0.710141 +vn -0.000001 -0.552761 -0.833340 +vn 0.162575 -0.552761 -0.817328 +vn 0.162575 -0.552761 -0.817328 +vn 0.138541 -0.704059 -0.696497 +vn -0.000000 -0.704059 -0.710141 +vn -0.109207 -0.828645 -0.549019 +vn -0.138542 -0.704059 -0.696496 +vn -0.000000 -0.704059 -0.710141 +vn -0.000000 -0.704059 -0.710141 +vn -0.000000 -0.828645 -0.559775 +vn -0.109207 -0.828645 -0.549019 +vn -0.214217 -0.828645 -0.517165 +vn -0.271759 -0.704059 -0.656085 +vn -0.138542 -0.704059 -0.696496 +vn -0.138542 -0.704059 -0.696496 +vn -0.109207 -0.828645 -0.549019 +vn -0.214217 -0.828645 -0.517165 +vn -0.310994 -0.828645 -0.465436 +vn -0.394533 -0.704059 -0.590461 +vn -0.271759 -0.704059 -0.656085 +vn -0.271759 -0.704059 -0.656085 +vn -0.214217 -0.828645 -0.517165 +vn -0.310994 -0.828645 -0.465436 +vn -0.395821 -0.828645 -0.395821 +vn -0.502146 -0.704059 -0.502146 +vn -0.394533 -0.704059 -0.590461 +vn -0.394533 -0.704059 -0.590461 +vn -0.310994 -0.828645 -0.465436 +vn -0.395821 -0.828645 -0.395821 +vn -0.465436 -0.828645 -0.310994 +vn -0.590461 -0.704059 -0.394533 +vn -0.502146 -0.704059 -0.502146 +vn -0.502146 -0.704059 -0.502146 +vn -0.395821 -0.828645 -0.395821 +vn -0.465436 -0.828645 -0.310994 +vn -0.517165 -0.828645 -0.214216 +vn -0.656085 -0.704059 -0.271759 +vn -0.590461 -0.704059 -0.394533 +vn -0.590461 -0.704059 -0.394533 +vn -0.465436 -0.828645 -0.310994 +vn -0.517165 -0.828645 -0.214216 +vn -0.549019 -0.828645 -0.109206 +vn -0.696496 -0.704059 -0.138541 +vn -0.656085 -0.704059 -0.271759 +vn -0.656085 -0.704059 -0.271759 +vn -0.517165 -0.828645 -0.214216 +vn -0.549019 -0.828645 -0.109206 +vn -0.559775 -0.828645 0.000000 +vn -0.710141 -0.704059 0.000000 +vn -0.696496 -0.704059 -0.138541 +vn -0.696496 -0.704059 -0.138541 +vn -0.549019 -0.828645 -0.109206 +vn -0.559775 -0.828645 0.000000 +vn -0.549019 -0.828645 0.109207 +vn -0.696496 -0.704059 0.138542 +vn -0.710141 -0.704059 0.000000 +vn -0.710141 -0.704059 0.000000 +vn -0.559775 -0.828645 0.000000 +vn -0.549019 -0.828645 0.109207 +vn -0.517165 -0.828645 0.214217 +vn -0.656085 -0.704059 0.271760 +vn -0.696496 -0.704059 0.138542 +vn -0.696496 -0.704059 0.138542 +vn -0.549019 -0.828645 0.109207 +vn -0.517165 -0.828645 0.214217 +vn -0.465436 -0.828645 0.310995 +vn -0.590461 -0.704059 0.394534 +vn -0.656085 -0.704059 0.271760 +vn -0.656085 -0.704059 0.271760 +vn -0.517165 -0.828645 0.214217 +vn -0.465436 -0.828645 0.310995 +vn -0.395820 -0.828645 0.395821 +vn -0.502146 -0.704059 0.502146 +vn -0.590461 -0.704059 0.394534 +vn -0.590461 -0.704059 0.394534 +vn -0.465436 -0.828645 0.310995 +vn -0.395820 -0.828645 0.395821 +vn -0.310994 -0.828645 0.465436 +vn -0.394533 -0.704059 0.590461 +vn -0.502146 -0.704059 0.502146 +vn -0.502146 -0.704059 0.502146 +vn -0.395820 -0.828645 0.395821 +vn -0.310994 -0.828645 0.465436 +vn -0.214216 -0.828645 0.517165 +vn -0.271759 -0.704059 0.656085 +vn -0.394533 -0.704059 0.590461 +vn -0.394533 -0.704059 0.590461 +vn -0.310994 -0.828645 0.465436 +vn -0.214216 -0.828645 0.517165 +vn -0.109206 -0.828645 0.549019 +vn -0.138541 -0.704059 0.696496 +vn -0.271759 -0.704059 0.656085 +vn -0.271759 -0.704059 0.656085 +vn -0.214216 -0.828645 0.517165 +vn -0.109206 -0.828645 0.549019 +vn 0.000001 -0.828645 0.559775 +vn 0.000001 -0.704059 0.710142 +vn -0.138541 -0.704059 0.696496 +vn -0.138541 -0.704059 0.696496 +vn -0.109206 -0.828645 0.549019 +vn 0.000001 -0.828645 0.559775 +vn 0.109207 -0.828645 0.549019 +vn 0.138542 -0.704059 0.696496 +vn 0.000001 -0.704059 0.710142 +vn 0.000001 -0.704059 0.710142 +vn 0.000001 -0.828645 0.559775 +vn 0.109207 -0.828645 0.549019 +vn 0.214217 -0.828645 0.517164 +vn 0.271760 -0.704059 0.656085 +vn 0.138542 -0.704059 0.696496 +vn 0.138542 -0.704059 0.696496 +vn 0.109207 -0.828645 0.549019 +vn 0.214217 -0.828645 0.517164 +vn 0.310995 -0.828645 0.465436 +vn 0.394534 -0.704059 0.590461 +vn 0.271760 -0.704059 0.656085 +vn 0.271760 -0.704059 0.656085 +vn 0.214217 -0.828645 0.517164 +vn 0.310995 -0.828645 0.465436 +vn 0.395821 -0.828645 0.395820 +vn 0.502146 -0.704059 0.502145 +vn 0.394534 -0.704059 0.590461 +vn 0.394534 -0.704059 0.590461 +vn 0.310995 -0.828645 0.465436 +vn 0.395821 -0.828645 0.395820 +vn 0.465436 -0.828645 0.310994 +vn 0.590462 -0.704059 0.394533 +vn 0.502146 -0.704059 0.502145 +vn 0.502146 -0.704059 0.502145 +vn 0.395821 -0.828645 0.395820 +vn 0.465436 -0.828645 0.310994 +vn 0.517165 -0.828645 0.214216 +vn 0.656086 -0.704059 0.271758 +vn 0.590462 -0.704059 0.394533 +vn 0.590462 -0.704059 0.394533 +vn 0.465436 -0.828645 0.310994 +vn 0.517165 -0.828645 0.214216 +vn 0.549019 -0.828645 0.109206 +vn 0.696496 -0.704059 0.138541 +vn 0.656086 -0.704059 0.271758 +vn 0.656086 -0.704059 0.271758 +vn 0.517165 -0.828645 0.214216 +vn 0.549019 -0.828645 0.109206 +vn 0.559775 -0.828645 -0.000001 +vn 0.710141 -0.704059 -0.000001 +vn 0.696496 -0.704059 0.138541 +vn 0.696496 -0.704059 0.138541 +vn 0.549019 -0.828645 0.109206 +vn 0.559775 -0.828645 -0.000001 +vn 0.549019 -0.828645 -0.109208 +vn 0.696496 -0.704059 -0.138543 +vn 0.710141 -0.704059 -0.000001 +vn 0.710141 -0.704059 -0.000001 +vn 0.559775 -0.828645 -0.000001 +vn 0.549019 -0.828645 -0.109208 +vn 0.517164 -0.828645 -0.214218 +vn 0.656085 -0.704059 -0.271761 +vn 0.696496 -0.704059 -0.138543 +vn 0.696496 -0.704059 -0.138543 +vn 0.549019 -0.828645 -0.109208 +vn 0.517164 -0.828645 -0.214218 +vn 0.465435 -0.828645 -0.310995 +vn 0.590460 -0.704059 -0.394535 +vn 0.656085 -0.704059 -0.271761 +vn 0.656085 -0.704059 -0.271761 +vn 0.517164 -0.828645 -0.214218 +vn 0.465435 -0.828645 -0.310995 +vn 0.395820 -0.828645 -0.395821 +vn 0.502145 -0.704059 -0.502147 +vn 0.590460 -0.704059 -0.394535 +vn 0.590460 -0.704059 -0.394535 +vn 0.465435 -0.828645 -0.310995 +vn 0.395820 -0.828645 -0.395821 +vn 0.310994 -0.828645 -0.465436 +vn 0.394532 -0.704059 -0.590462 +vn 0.502145 -0.704059 -0.502147 +vn 0.502145 -0.704059 -0.502147 +vn 0.395820 -0.828645 -0.395821 +vn 0.310994 -0.828645 -0.465436 +vn 0.214215 -0.828645 -0.517165 +vn 0.271758 -0.704059 -0.656086 +vn 0.394532 -0.704059 -0.590462 +vn 0.394532 -0.704059 -0.590462 +vn 0.310994 -0.828645 -0.465436 +vn 0.214215 -0.828645 -0.517165 +vn 0.109206 -0.828645 -0.549019 +vn 0.138541 -0.704059 -0.696497 +vn 0.271758 -0.704059 -0.656086 +vn 0.271758 -0.704059 -0.656086 +vn 0.214215 -0.828645 -0.517165 +vn 0.109206 -0.828645 -0.549019 +vn -0.000000 -0.828645 -0.559775 +vn -0.000000 -0.704059 -0.710141 +vn 0.138541 -0.704059 -0.696497 +vn 0.138541 -0.704059 -0.696497 +vn 0.109206 -0.828645 -0.549019 +vn -0.000000 -0.828645 -0.559775 +vn -0.075673 -0.921707 -0.380434 +vn -0.109207 -0.828645 -0.549019 +vn -0.000000 -0.828645 -0.559775 +vn -0.000000 -0.828645 -0.559775 +vn -0.000000 -0.921707 -0.387887 +vn -0.075673 -0.921707 -0.380434 +vn -0.148438 -0.921707 -0.358361 +vn -0.214217 -0.828645 -0.517165 +vn -0.109207 -0.828645 -0.549019 +vn -0.109207 -0.828645 -0.549019 +vn -0.075673 -0.921707 -0.380434 +vn -0.148438 -0.921707 -0.358361 +vn -0.215498 -0.921707 -0.322516 +vn -0.310994 -0.828645 -0.465436 +vn -0.214217 -0.828645 -0.517165 +vn -0.214217 -0.828645 -0.517165 +vn -0.148438 -0.921707 -0.358361 +vn -0.215498 -0.921707 -0.322516 +vn -0.274278 -0.921707 -0.274277 +vn -0.395821 -0.828645 -0.395821 +vn -0.310994 -0.828645 -0.465436 +vn -0.310994 -0.828645 -0.465436 +vn -0.215498 -0.921707 -0.322516 +vn -0.274278 -0.921707 -0.274277 +vn -0.322516 -0.921707 -0.215498 +vn -0.465436 -0.828645 -0.310994 +vn -0.395821 -0.828645 -0.395821 +vn -0.395821 -0.828645 -0.395821 +vn -0.274278 -0.921707 -0.274277 +vn -0.322516 -0.921707 -0.215498 +vn -0.358361 -0.921707 -0.148438 +vn -0.517165 -0.828645 -0.214216 +vn -0.465436 -0.828645 -0.310994 +vn -0.465436 -0.828645 -0.310994 +vn -0.322516 -0.921707 -0.215498 +vn -0.358361 -0.921707 -0.148438 +vn -0.380434 -0.921707 -0.075673 +vn -0.549019 -0.828645 -0.109206 +vn -0.517165 -0.828645 -0.214216 +vn -0.517165 -0.828645 -0.214216 +vn -0.358361 -0.921707 -0.148438 +vn -0.380434 -0.921707 -0.075673 +vn -0.387887 -0.921707 0.000000 +vn -0.559775 -0.828645 0.000000 +vn -0.549019 -0.828645 -0.109206 +vn -0.549019 -0.828645 -0.109206 +vn -0.380434 -0.921707 -0.075673 +vn -0.387887 -0.921707 0.000000 +vn -0.380434 -0.921707 0.075673 +vn -0.549019 -0.828645 0.109207 +vn -0.559775 -0.828645 0.000000 +vn -0.559775 -0.828645 0.000000 +vn -0.387887 -0.921707 0.000000 +vn -0.380434 -0.921707 0.075673 +vn -0.358361 -0.921707 0.148438 +vn -0.517165 -0.828645 0.214217 +vn -0.549019 -0.828645 0.109207 +vn -0.549019 -0.828645 0.109207 +vn -0.380434 -0.921707 0.075673 +vn -0.358361 -0.921707 0.148438 +vn -0.322516 -0.921707 0.215499 +vn -0.465436 -0.828645 0.310995 +vn -0.517165 -0.828645 0.214217 +vn -0.517165 -0.828645 0.214217 +vn -0.358361 -0.921707 0.148438 +vn -0.322516 -0.921707 0.215499 +vn -0.274277 -0.921707 0.274278 +vn -0.395820 -0.828645 0.395821 +vn -0.465436 -0.828645 0.310995 +vn -0.465436 -0.828645 0.310995 +vn -0.322516 -0.921707 0.215499 +vn -0.274277 -0.921707 0.274278 +vn -0.215498 -0.921707 0.322516 +vn -0.310994 -0.828645 0.465436 +vn -0.395820 -0.828645 0.395821 +vn -0.395820 -0.828645 0.395821 +vn -0.274277 -0.921707 0.274278 +vn -0.215498 -0.921707 0.322516 +vn -0.148438 -0.921707 0.358361 +vn -0.214216 -0.828645 0.517165 +vn -0.310994 -0.828645 0.465436 +vn -0.310994 -0.828645 0.465436 +vn -0.215498 -0.921707 0.322516 +vn -0.148438 -0.921707 0.358361 +vn -0.075673 -0.921707 0.380434 +vn -0.109206 -0.828645 0.549019 +vn -0.214216 -0.828645 0.517165 +vn -0.214216 -0.828645 0.517165 +vn -0.148438 -0.921707 0.358361 +vn -0.075673 -0.921707 0.380434 +vn 0.000000 -0.921707 0.387887 +vn 0.000001 -0.828645 0.559775 +vn -0.109206 -0.828645 0.549019 +vn -0.109206 -0.828645 0.549019 +vn -0.075673 -0.921707 0.380434 +vn 0.000000 -0.921707 0.387887 +vn 0.075673 -0.921707 0.380434 +vn 0.109207 -0.828645 0.549019 +vn 0.000001 -0.828645 0.559775 +vn 0.000001 -0.828645 0.559775 +vn 0.000000 -0.921707 0.387887 +vn 0.075673 -0.921707 0.380434 +vn 0.148438 -0.921707 0.358361 +vn 0.214217 -0.828645 0.517164 +vn 0.109207 -0.828645 0.549019 +vn 0.109207 -0.828645 0.549019 +vn 0.075673 -0.921707 0.380434 +vn 0.148438 -0.921707 0.358361 +vn 0.215499 -0.921707 0.322516 +vn 0.310995 -0.828645 0.465436 +vn 0.214217 -0.828645 0.517164 +vn 0.214217 -0.828645 0.517164 +vn 0.148438 -0.921707 0.358361 +vn 0.215499 -0.921707 0.322516 +vn 0.274278 -0.921707 0.274277 +vn 0.395821 -0.828645 0.395820 +vn 0.310995 -0.828645 0.465436 +vn 0.310995 -0.828645 0.465436 +vn 0.215499 -0.921707 0.322516 +vn 0.274278 -0.921707 0.274277 +vn 0.322516 -0.921707 0.215498 +vn 0.465436 -0.828645 0.310994 +vn 0.395821 -0.828645 0.395820 +vn 0.395821 -0.828645 0.395820 +vn 0.274278 -0.921707 0.274277 +vn 0.322516 -0.921707 0.215498 +vn 0.358361 -0.921707 0.148437 +vn 0.517165 -0.828645 0.214216 +vn 0.465436 -0.828645 0.310994 +vn 0.465436 -0.828645 0.310994 +vn 0.322516 -0.921707 0.215498 +vn 0.358361 -0.921707 0.148437 +vn 0.380434 -0.921707 0.075672 +vn 0.549019 -0.828645 0.109206 +vn 0.517165 -0.828645 0.214216 +vn 0.517165 -0.828645 0.214216 +vn 0.358361 -0.921707 0.148437 +vn 0.380434 -0.921707 0.075672 +vn 0.387887 -0.921707 -0.000001 +vn 0.559775 -0.828645 -0.000001 +vn 0.549019 -0.828645 0.109206 +vn 0.549019 -0.828645 0.109206 +vn 0.380434 -0.921707 0.075672 +vn 0.387887 -0.921707 -0.000001 +vn 0.380433 -0.921707 -0.075674 +vn 0.549019 -0.828645 -0.109208 +vn 0.559775 -0.828645 -0.000001 +vn 0.559775 -0.828645 -0.000001 +vn 0.387887 -0.921707 -0.000001 +vn 0.380433 -0.921707 -0.075674 +vn 0.358360 -0.921707 -0.148438 +vn 0.517164 -0.828645 -0.214218 +vn 0.549019 -0.828645 -0.109208 +vn 0.549019 -0.828645 -0.109208 +vn 0.380433 -0.921707 -0.075674 +vn 0.358360 -0.921707 -0.148438 +vn 0.322516 -0.921707 -0.215499 +vn 0.465435 -0.828645 -0.310995 +vn 0.517164 -0.828645 -0.214218 +vn 0.517164 -0.828645 -0.214218 +vn 0.358360 -0.921707 -0.148438 +vn 0.322516 -0.921707 -0.215499 +vn 0.274277 -0.921707 -0.274278 +vn 0.395820 -0.828645 -0.395821 +vn 0.465435 -0.828645 -0.310995 +vn 0.465435 -0.828645 -0.310995 +vn 0.322516 -0.921707 -0.215499 +vn 0.274277 -0.921707 -0.274278 +vn 0.215498 -0.921707 -0.322516 +vn 0.310994 -0.828645 -0.465436 +vn 0.395820 -0.828645 -0.395821 +vn 0.395820 -0.828645 -0.395821 +vn 0.274277 -0.921707 -0.274278 +vn 0.215498 -0.921707 -0.322516 +vn 0.148437 -0.921707 -0.358361 +vn 0.214215 -0.828645 -0.517165 +vn 0.310994 -0.828645 -0.465436 +vn 0.310994 -0.828645 -0.465436 +vn 0.215498 -0.921707 -0.322516 +vn 0.148437 -0.921707 -0.358361 +vn 0.075672 -0.921707 -0.380434 +vn 0.109206 -0.828645 -0.549019 +vn 0.214215 -0.828645 -0.517165 +vn 0.214215 -0.828645 -0.517165 +vn 0.148437 -0.921707 -0.358361 +vn 0.075672 -0.921707 -0.380434 +vn -0.000000 -0.921707 -0.387887 +vn -0.000000 -0.828645 -0.559775 +vn 0.109206 -0.828645 -0.549019 +vn 0.109206 -0.828645 -0.549019 +vn 0.075672 -0.921707 -0.380434 +vn -0.000000 -0.921707 -0.387887 +vn -0.039207 -0.979598 -0.197107 +vn -0.075673 -0.921707 -0.380434 +vn -0.000000 -0.921707 -0.387887 +vn -0.000000 -0.921707 -0.387887 +vn -0.000000 -0.979598 -0.200969 +vn -0.039207 -0.979598 -0.197107 +vn -0.076907 -0.979598 -0.185671 +vn -0.148438 -0.921707 -0.358361 +vn -0.075673 -0.921707 -0.380434 +vn -0.075673 -0.921707 -0.380434 +vn -0.039207 -0.979598 -0.197107 +vn -0.076907 -0.979598 -0.185671 +vn -0.111652 -0.979598 -0.167099 +vn -0.215498 -0.921707 -0.322516 +vn -0.148438 -0.921707 -0.358361 +vn -0.148438 -0.921707 -0.358361 +vn -0.076907 -0.979598 -0.185671 +vn -0.111652 -0.979598 -0.167099 +vn -0.142106 -0.979598 -0.142106 +vn -0.274278 -0.921707 -0.274277 +vn -0.215498 -0.921707 -0.322516 +vn -0.215498 -0.921707 -0.322516 +vn -0.111652 -0.979598 -0.167099 +vn -0.142106 -0.979598 -0.142106 +vn -0.167099 -0.979598 -0.111652 +vn -0.322516 -0.921707 -0.215498 +vn -0.274278 -0.921707 -0.274277 +vn -0.274278 -0.921707 -0.274277 +vn -0.142106 -0.979598 -0.142106 +vn -0.167099 -0.979598 -0.111652 +vn -0.185671 -0.979598 -0.076907 +vn -0.358361 -0.921707 -0.148438 +vn -0.322516 -0.921707 -0.215498 +vn -0.322516 -0.921707 -0.215498 +vn -0.167099 -0.979598 -0.111652 +vn -0.185671 -0.979598 -0.076907 +vn -0.197107 -0.979598 -0.039207 +vn -0.380434 -0.921707 -0.075673 +vn -0.358361 -0.921707 -0.148438 +vn -0.358361 -0.921707 -0.148438 +vn -0.185671 -0.979598 -0.076907 +vn -0.197107 -0.979598 -0.039207 +vn -0.200969 -0.979598 -0.000000 +vn -0.387887 -0.921707 0.000000 +vn -0.380434 -0.921707 -0.075673 +vn -0.380434 -0.921707 -0.075673 +vn -0.197107 -0.979598 -0.039207 +vn -0.200969 -0.979598 -0.000000 +vn -0.197107 -0.979598 0.039207 +vn -0.380434 -0.921707 0.075673 +vn -0.387887 -0.921707 0.000000 +vn -0.387887 -0.921707 0.000000 +vn -0.200969 -0.979598 -0.000000 +vn -0.197107 -0.979598 0.039207 +vn -0.185671 -0.979598 0.076907 +vn -0.358361 -0.921707 0.148438 +vn -0.380434 -0.921707 0.075673 +vn -0.380434 -0.921707 0.075673 +vn -0.197107 -0.979598 0.039207 +vn -0.185671 -0.979598 0.076907 +vn -0.167099 -0.979598 0.111652 +vn -0.322516 -0.921707 0.215499 +vn -0.358361 -0.921707 0.148438 +vn -0.358361 -0.921707 0.148438 +vn -0.185671 -0.979598 0.076907 +vn -0.167099 -0.979598 0.111652 +vn -0.142106 -0.979598 0.142106 +vn -0.274277 -0.921707 0.274278 +vn -0.322516 -0.921707 0.215499 +vn -0.322516 -0.921707 0.215499 +vn -0.167099 -0.979598 0.111652 +vn -0.142106 -0.979598 0.142106 +vn -0.111652 -0.979598 0.167100 +vn -0.215498 -0.921707 0.322516 +vn -0.274277 -0.921707 0.274278 +vn -0.274277 -0.921707 0.274278 +vn -0.142106 -0.979598 0.142106 +vn -0.111652 -0.979598 0.167100 +vn -0.076907 -0.979598 0.185671 +vn -0.148438 -0.921707 0.358361 +vn -0.215498 -0.921707 0.322516 +vn -0.215498 -0.921707 0.322516 +vn -0.111652 -0.979598 0.167100 +vn -0.076907 -0.979598 0.185671 +vn -0.039207 -0.979598 0.197107 +vn -0.075673 -0.921707 0.380434 +vn -0.148438 -0.921707 0.358361 +vn -0.148438 -0.921707 0.358361 +vn -0.076907 -0.979598 0.185671 +vn -0.039207 -0.979598 0.197107 +vn 0.000000 -0.979598 0.200969 +vn 0.000000 -0.921707 0.387887 +vn -0.075673 -0.921707 0.380434 +vn -0.075673 -0.921707 0.380434 +vn -0.039207 -0.979598 0.197107 +vn 0.000000 -0.979598 0.200969 +vn 0.039207 -0.979598 0.197107 +vn 0.075673 -0.921707 0.380434 +vn 0.000000 -0.921707 0.387887 +vn 0.000000 -0.921707 0.387887 +vn 0.000000 -0.979598 0.200969 +vn 0.039207 -0.979598 0.197107 +vn 0.076908 -0.979598 0.185671 +vn 0.148438 -0.921707 0.358361 +vn 0.075673 -0.921707 0.380434 +vn 0.075673 -0.921707 0.380434 +vn 0.039207 -0.979598 0.197107 +vn 0.076908 -0.979598 0.185671 +vn 0.111653 -0.979598 0.167099 +vn 0.215499 -0.921707 0.322516 +vn 0.148438 -0.921707 0.358361 +vn 0.148438 -0.921707 0.358361 +vn 0.076908 -0.979598 0.185671 +vn 0.111653 -0.979598 0.167099 +vn 0.142106 -0.979598 0.142106 +vn 0.274278 -0.921707 0.274277 +vn 0.215499 -0.921707 0.322516 +vn 0.215499 -0.921707 0.322516 +vn 0.111653 -0.979598 0.167099 +vn 0.142106 -0.979598 0.142106 +vn 0.167099 -0.979598 0.111652 +vn 0.322516 -0.921707 0.215498 +vn 0.274278 -0.921707 0.274277 +vn 0.274278 -0.921707 0.274277 +vn 0.142106 -0.979598 0.142106 +vn 0.167099 -0.979598 0.111652 +vn 0.185671 -0.979598 0.076907 +vn 0.358361 -0.921707 0.148437 +vn 0.322516 -0.921707 0.215498 +vn 0.322516 -0.921707 0.215498 +vn 0.167099 -0.979598 0.111652 +vn 0.185671 -0.979598 0.076907 +vn 0.197107 -0.979598 0.039207 +vn 0.380434 -0.921707 0.075672 +vn 0.358361 -0.921707 0.148437 +vn 0.358361 -0.921707 0.148437 +vn 0.185671 -0.979598 0.076907 +vn 0.197107 -0.979598 0.039207 +vn 0.200969 -0.979598 -0.000000 +vn 0.387887 -0.921707 -0.000001 +vn 0.380434 -0.921707 0.075672 +vn 0.380434 -0.921707 0.075672 +vn 0.197107 -0.979598 0.039207 +vn 0.200969 -0.979598 -0.000000 +vn 0.197107 -0.979598 -0.039207 +vn 0.380433 -0.921707 -0.075674 +vn 0.387887 -0.921707 -0.000001 +vn 0.387887 -0.921707 -0.000001 +vn 0.200969 -0.979598 -0.000000 +vn 0.197107 -0.979598 -0.039207 +vn 0.185671 -0.979598 -0.076908 +vn 0.358360 -0.921707 -0.148438 +vn 0.380433 -0.921707 -0.075674 +vn 0.380433 -0.921707 -0.075674 +vn 0.197107 -0.979598 -0.039207 +vn 0.185671 -0.979598 -0.076908 +vn 0.167099 -0.979598 -0.111652 +vn 0.322516 -0.921707 -0.215499 +vn 0.358360 -0.921707 -0.148438 +vn 0.358360 -0.921707 -0.148438 +vn 0.185671 -0.979598 -0.076908 +vn 0.167099 -0.979598 -0.111652 +vn 0.142106 -0.979598 -0.142106 +vn 0.274277 -0.921707 -0.274278 +vn 0.322516 -0.921707 -0.215499 +vn 0.322516 -0.921707 -0.215499 +vn 0.167099 -0.979598 -0.111652 +vn 0.142106 -0.979598 -0.142106 +vn 0.111652 -0.979598 -0.167100 +vn 0.215498 -0.921707 -0.322516 +vn 0.274277 -0.921707 -0.274278 +vn 0.274277 -0.921707 -0.274278 +vn 0.142106 -0.979598 -0.142106 +vn 0.111652 -0.979598 -0.167100 +vn 0.076907 -0.979598 -0.185671 +vn 0.148437 -0.921707 -0.358361 +vn 0.215498 -0.921707 -0.322516 +vn 0.215498 -0.921707 -0.322516 +vn 0.111652 -0.979598 -0.167100 +vn 0.076907 -0.979598 -0.185671 +vn 0.039207 -0.979598 -0.197107 +vn 0.075672 -0.921707 -0.380434 +vn 0.148437 -0.921707 -0.358361 +vn 0.148437 -0.921707 -0.358361 +vn 0.076907 -0.979598 -0.185671 +vn 0.039207 -0.979598 -0.197107 +vn -0.000000 -0.979598 -0.200969 +vn -0.000000 -0.921707 -0.387887 +vn 0.075672 -0.921707 -0.380434 +vn 0.075672 -0.921707 -0.380434 +vn 0.039207 -0.979598 -0.197107 +vn -0.000000 -0.979598 -0.200969 +vn -0.000000 -1.000000 -0.000000 +vn -0.039207 -0.979598 -0.197107 +vn -0.000000 -0.979598 -0.200969 +vn -0.000000 -1.000000 -0.000000 +vn -0.076907 -0.979598 -0.185671 +vn -0.039207 -0.979598 -0.197107 +vn -0.000000 -1.000000 -0.000000 +vn -0.111652 -0.979598 -0.167099 +vn -0.076907 -0.979598 -0.185671 +vn -0.000000 -1.000000 -0.000000 +vn -0.142106 -0.979598 -0.142106 +vn -0.111652 -0.979598 -0.167099 +vn -0.000000 -1.000000 -0.000000 +vn -0.167099 -0.979598 -0.111652 +vn -0.142106 -0.979598 -0.142106 +vn -0.000000 -1.000000 -0.000000 +vn -0.185671 -0.979598 -0.076907 +vn -0.167099 -0.979598 -0.111652 +vn -0.000000 -1.000000 -0.000000 +vn -0.197107 -0.979598 -0.039207 +vn -0.185671 -0.979598 -0.076907 +vn -0.000000 -1.000000 -0.000000 +vn -0.200969 -0.979598 -0.000000 +vn -0.197107 -0.979598 -0.039207 +vn -0.000000 -1.000000 -0.000000 +vn -0.197107 -0.979598 0.039207 +vn -0.200969 -0.979598 -0.000000 +vn -0.000000 -1.000000 -0.000000 +vn -0.185671 -0.979598 0.076907 +vn -0.197107 -0.979598 0.039207 +vn -0.000000 -1.000000 -0.000000 +vn -0.167099 -0.979598 0.111652 +vn -0.185671 -0.979598 0.076907 +vn -0.000000 -1.000000 -0.000000 +vn -0.142106 -0.979598 0.142106 +vn -0.167099 -0.979598 0.111652 +vn -0.000000 -1.000000 -0.000000 +vn -0.111652 -0.979598 0.167100 +vn -0.142106 -0.979598 0.142106 +vn -0.000000 -1.000000 -0.000000 +vn -0.076907 -0.979598 0.185671 +vn -0.111652 -0.979598 0.167100 +vn -0.000000 -1.000000 -0.000000 +vn -0.039207 -0.979598 0.197107 +vn -0.076907 -0.979598 0.185671 +vn -0.000000 -1.000000 -0.000000 +vn 0.000000 -0.979598 0.200969 +vn -0.039207 -0.979598 0.197107 +vn -0.000000 -1.000000 -0.000000 +vn 0.039207 -0.979598 0.197107 +vn 0.000000 -0.979598 0.200969 +vn -0.000000 -1.000000 -0.000000 +vn 0.076908 -0.979598 0.185671 +vn 0.039207 -0.979598 0.197107 +vn -0.000000 -1.000000 -0.000000 +vn 0.111653 -0.979598 0.167099 +vn 0.076908 -0.979598 0.185671 +vn -0.000000 -1.000000 -0.000000 +vn 0.142106 -0.979598 0.142106 +vn 0.111653 -0.979598 0.167099 +vn -0.000000 -1.000000 -0.000000 +vn 0.167099 -0.979598 0.111652 +vn 0.142106 -0.979598 0.142106 +vn -0.000000 -1.000000 -0.000000 +vn 0.185671 -0.979598 0.076907 +vn 0.167099 -0.979598 0.111652 +vn -0.000000 -1.000000 -0.000000 +vn 0.197107 -0.979598 0.039207 +vn 0.185671 -0.979598 0.076907 +vn -0.000000 -1.000000 -0.000000 +vn 0.200969 -0.979598 -0.000000 +vn 0.197107 -0.979598 0.039207 +vn -0.000000 -1.000000 -0.000000 +vn 0.197107 -0.979598 -0.039207 +vn 0.200969 -0.979598 -0.000000 +vn -0.000000 -1.000000 -0.000000 +vn 0.185671 -0.979598 -0.076908 +vn 0.197107 -0.979598 -0.039207 +vn -0.000000 -1.000000 -0.000000 +vn 0.167099 -0.979598 -0.111652 +vn 0.185671 -0.979598 -0.076908 +vn -0.000000 -1.000000 -0.000000 +vn 0.142106 -0.979598 -0.142106 +vn 0.167099 -0.979598 -0.111652 +vn -0.000000 -1.000000 -0.000000 +vn 0.111652 -0.979598 -0.167100 +vn 0.142106 -0.979598 -0.142106 +vn -0.000000 -1.000000 -0.000000 +vn 0.076907 -0.979598 -0.185671 +vn 0.111652 -0.979598 -0.167100 +vn -0.000000 -1.000000 -0.000000 +vn 0.039207 -0.979598 -0.197107 +vn 0.076907 -0.979598 -0.185671 +vn -0.000000 -1.000000 -0.000000 +vn -0.000000 -0.979598 -0.200969 +vn 0.039207 -0.979598 -0.197107 +vn 0.889663 0.456618 -0.000000 +vn 0.859348 0.456618 -0.230262 +vn 0.859348 0.456618 -0.230262 +vn 0.859348 0.456618 -0.230262 +vn 0.889663 0.456618 0.000000 +vn 0.889663 0.456618 -0.000000 +vn 0.859348 0.456618 -0.230262 +vn 0.770470 0.456619 -0.444831 +vn 0.770470 0.456618 -0.444831 +vn 0.770470 0.456618 -0.444831 +vn 0.859348 0.456618 -0.230262 +vn 0.859348 0.456618 -0.230262 +vn 0.770470 0.456619 -0.444831 +vn 0.629086 0.456619 -0.629086 +vn 0.629087 0.456618 -0.629086 +vn 0.629087 0.456618 -0.629086 +vn 0.770470 0.456618 -0.444831 +vn 0.770470 0.456619 -0.444831 +vn 0.629086 0.456619 -0.629086 +vn 0.444831 0.456619 -0.770471 +vn 0.444831 0.456618 -0.770471 +vn 0.444831 0.456618 -0.770471 +vn 0.629087 0.456618 -0.629086 +vn 0.629086 0.456619 -0.629086 +vn 0.444831 0.456619 -0.770471 +vn 0.230262 0.456618 -0.859348 +vn 0.230262 0.456618 -0.859348 +vn 0.230262 0.456618 -0.859348 +vn 0.444831 0.456618 -0.770471 +vn 0.444831 0.456619 -0.770471 +vn 0.230262 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn 0.000000 0.456618 -0.889663 +vn 0.000000 0.456618 -0.889663 +vn 0.230262 0.456618 -0.859348 +vn 0.230262 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn -0.230261 0.456618 -0.859348 +vn -0.230262 0.456618 -0.859348 +vn -0.230262 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn 0.000000 0.456618 -0.889663 +vn -0.230261 0.456618 -0.859348 +vn -0.444831 0.456618 -0.770470 +vn -0.444831 0.456618 -0.770471 +vn -0.444831 0.456618 -0.770471 +vn -0.230262 0.456618 -0.859348 +vn -0.230261 0.456618 -0.859348 +vn -0.444831 0.456618 -0.770470 +vn -0.629086 0.456618 -0.629086 +vn -0.629086 0.456618 -0.629087 +vn -0.629086 0.456618 -0.629087 +vn -0.444831 0.456618 -0.770471 +vn -0.444831 0.456618 -0.770470 +vn -0.629086 0.456618 -0.629086 +vn -0.770470 0.456618 -0.444832 +vn -0.770470 0.456618 -0.444832 +vn -0.770470 0.456618 -0.444832 +vn -0.629086 0.456618 -0.629087 +vn -0.629086 0.456618 -0.629086 +vn -0.770470 0.456618 -0.444832 +vn -0.859348 0.456618 -0.230262 +vn -0.859348 0.456618 -0.230262 +vn -0.859348 0.456618 -0.230262 +vn -0.770470 0.456618 -0.444832 +vn -0.770470 0.456618 -0.444832 +vn -0.859348 0.456618 -0.230262 +vn -0.889663 0.456618 -0.000000 +vn -0.889663 0.456618 -0.000000 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 -0.230262 +vn -0.859348 0.456618 -0.230262 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 0.230261 +vn -0.859348 0.456618 0.230261 +vn -0.859348 0.456618 0.230261 +vn -0.889663 0.456618 -0.000000 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 0.230261 +vn -0.770471 0.456618 0.444831 +vn -0.770471 0.456618 0.444831 +vn -0.770471 0.456618 0.444831 +vn -0.859348 0.456618 0.230261 +vn -0.859348 0.456618 0.230261 +vn -0.770471 0.456618 0.444831 +vn -0.629087 0.456618 0.629086 +vn -0.629087 0.456618 0.629086 +vn -0.629087 0.456618 0.629086 +vn -0.770471 0.456618 0.444831 +vn -0.770471 0.456618 0.444831 +vn -0.629087 0.456618 0.629086 +vn -0.444832 0.456618 0.770470 +vn -0.444832 0.456618 0.770470 +vn -0.444832 0.456618 0.770470 +vn -0.629087 0.456618 0.629086 +vn -0.629087 0.456618 0.629086 +vn -0.444832 0.456618 0.770470 +vn -0.230262 0.456618 0.859348 +vn -0.230262 0.456618 0.859348 +vn -0.230262 0.456618 0.859348 +vn -0.444832 0.456618 0.770470 +vn -0.444832 0.456618 0.770470 +vn -0.230262 0.456618 0.859348 +vn -0.000001 0.456619 0.889663 +vn -0.000000 0.456618 0.889663 +vn -0.000000 0.456618 0.889663 +vn -0.230262 0.456618 0.859348 +vn -0.230262 0.456618 0.859348 +vn -0.000001 0.456619 0.889663 +vn 0.230261 0.456618 0.859348 +vn 0.230261 0.456618 0.859348 +vn 0.230261 0.456618 0.859348 +vn -0.000000 0.456618 0.889663 +vn -0.000001 0.456619 0.889663 +vn 0.230261 0.456618 0.859348 +vn 0.444831 0.456619 0.770471 +vn 0.444831 0.456618 0.770471 +vn 0.444831 0.456618 0.770471 +vn 0.230261 0.456618 0.859348 +vn 0.230261 0.456618 0.859348 +vn 0.444831 0.456619 0.770471 +vn 0.629086 0.456618 0.629087 +vn 0.629086 0.456618 0.629087 +vn 0.629086 0.456618 0.629087 +vn 0.444831 0.456618 0.770471 +vn 0.444831 0.456619 0.770471 +vn 0.629086 0.456618 0.629087 +vn 0.770470 0.456618 0.444832 +vn 0.770470 0.456618 0.444832 +vn 0.770470 0.456618 0.444832 +vn 0.629086 0.456618 0.629087 +vn 0.629086 0.456618 0.629087 +vn 0.770470 0.456618 0.444832 +vn 0.859348 0.456619 0.230262 +vn 0.859348 0.456618 0.230262 +vn 0.859348 0.456618 0.230262 +vn 0.770470 0.456618 0.444832 +vn 0.770470 0.456618 0.444832 +vn 0.859348 0.456619 0.230262 +vn 0.889663 0.456618 -0.000000 +vn 0.889663 0.456618 0.000000 +vn 0.889663 0.456618 0.000000 +vn 0.859348 0.456618 0.230262 +vn 0.859348 0.456619 0.230262 +vn 0.889663 0.456618 0.000000 +vn 0.859348 0.456618 -0.230262 +vn 0.859348 0.456618 -0.230261 +vn 0.859348 0.456618 -0.230261 +vn 0.889663 0.456618 0.000000 +vn 0.889663 0.456618 0.000000 +vn 0.859348 0.456618 -0.230262 +vn 0.770470 0.456618 -0.444831 +vn 0.770470 0.456618 -0.444832 +vn 0.770470 0.456618 -0.444832 +vn 0.859348 0.456618 -0.230261 +vn 0.859348 0.456618 -0.230262 +vn 0.770470 0.456618 -0.444831 +vn 0.629087 0.456618 -0.629086 +vn 0.629086 0.456618 -0.629087 +vn 0.629086 0.456618 -0.629087 +vn 0.770470 0.456618 -0.444832 +vn 0.770470 0.456618 -0.444831 +vn 0.629087 0.456618 -0.629086 +vn 0.444831 0.456618 -0.770471 +vn 0.444831 0.456618 -0.770471 +vn 0.444831 0.456618 -0.770471 +vn 0.629086 0.456618 -0.629087 +vn 0.629087 0.456618 -0.629086 +vn 0.444831 0.456618 -0.770471 +vn 0.230262 0.456618 -0.859348 +vn 0.230262 0.456618 -0.859348 +vn 0.230262 0.456618 -0.859348 +vn 0.444831 0.456618 -0.770471 +vn 0.444831 0.456618 -0.770471 +vn 0.230262 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn 0.000000 0.456618 -0.889663 +vn 0.000000 0.456618 -0.889663 +vn 0.230262 0.456618 -0.859348 +vn 0.230262 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn -0.230262 0.456618 -0.859348 +vn -0.230261 0.456618 -0.859348 +vn -0.230261 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn 0.000000 0.456618 -0.889663 +vn -0.230262 0.456618 -0.859348 +vn -0.444831 0.456618 -0.770471 +vn -0.444831 0.456618 -0.770471 +vn -0.444831 0.456618 -0.770471 +vn -0.230261 0.456618 -0.859348 +vn -0.230262 0.456618 -0.859348 +vn -0.444831 0.456618 -0.770471 +vn -0.629086 0.456618 -0.629087 +vn -0.629086 0.456618 -0.629087 +vn -0.629086 0.456618 -0.629087 +vn -0.444831 0.456618 -0.770471 +vn -0.444831 0.456618 -0.770471 +vn -0.629086 0.456618 -0.629087 +vn -0.770470 0.456618 -0.444832 +vn -0.770470 0.456618 -0.444832 +vn -0.770470 0.456618 -0.444832 +vn -0.629086 0.456618 -0.629087 +vn -0.629086 0.456618 -0.629087 +vn -0.770470 0.456618 -0.444832 +vn -0.859348 0.456618 -0.230262 +vn -0.859348 0.456618 -0.230262 +vn -0.859348 0.456618 -0.230262 +vn -0.770470 0.456618 -0.444832 +vn -0.770470 0.456618 -0.444832 +vn -0.859348 0.456618 -0.230262 +vn -0.889663 0.456618 -0.000000 +vn -0.889663 0.456618 -0.000000 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 -0.230262 +vn -0.859348 0.456618 -0.230262 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 0.230261 +vn -0.859348 0.456618 0.230261 +vn -0.859348 0.456618 0.230261 +vn -0.889663 0.456618 -0.000000 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 0.230261 +vn -0.770471 0.456618 0.444831 +vn -0.770471 0.456618 0.444831 +vn -0.770471 0.456618 0.444831 +vn -0.859348 0.456618 0.230261 +vn -0.859348 0.456618 0.230261 +vn -0.770471 0.456618 0.444831 +vn -0.629087 0.456618 0.629086 +vn -0.629087 0.456618 0.629086 +vn -0.629087 0.456618 0.629086 +vn -0.770471 0.456618 0.444831 +vn -0.770471 0.456618 0.444831 +vn -0.629087 0.456618 0.629086 +vn -0.444832 0.456618 0.770470 +vn -0.444831 0.456618 0.770471 +vn -0.444831 0.456618 0.770471 +vn -0.629087 0.456618 0.629086 +vn -0.629087 0.456618 0.629086 +vn -0.444832 0.456618 0.770470 +vn -0.230262 0.456618 0.859348 +vn -0.230262 0.456618 0.859348 +vn -0.230262 0.456618 0.859348 +vn -0.444831 0.456618 0.770471 +vn -0.444832 0.456618 0.770470 +vn -0.230262 0.456618 0.859348 +vn -0.000000 0.456618 0.889663 +vn -0.000001 0.456618 0.889663 +vn -0.000001 0.456618 0.889663 +vn -0.230262 0.456618 0.859348 +vn -0.230262 0.456618 0.859348 +vn -0.000000 0.456618 0.889663 +vn 0.230261 0.456618 0.859348 +vn 0.230261 0.456618 0.859348 +vn 0.230261 0.456618 0.859348 +vn -0.000001 0.456618 0.889663 +vn -0.000000 0.456618 0.889663 +vn 0.230261 0.456618 0.859348 +vn 0.444831 0.456618 0.770471 +vn 0.444831 0.456618 0.770471 +vn 0.444831 0.456618 0.770471 +vn 0.230261 0.456618 0.859348 +vn 0.230261 0.456618 0.859348 +vn 0.444831 0.456618 0.770471 +vn 0.629086 0.456618 0.629087 +vn 0.629086 0.456618 0.629087 +vn 0.629086 0.456618 0.629087 +vn 0.444831 0.456618 0.770471 +vn 0.444831 0.456618 0.770471 +vn 0.629086 0.456618 0.629087 +vn 0.770470 0.456618 0.444832 +vn 0.770470 0.456618 0.444832 +vn 0.770470 0.456618 0.444832 +vn 0.629086 0.456618 0.629087 +vn 0.629086 0.456618 0.629087 +vn 0.770470 0.456618 0.444832 +vn 0.859348 0.456618 0.230262 +vn 0.859348 0.456618 0.230262 +vn 0.859348 0.456618 0.230262 +vn 0.770470 0.456618 0.444832 +vn 0.770470 0.456618 0.444832 +vn 0.859348 0.456618 0.230262 +vn 0.889663 0.456618 0.000000 +vn 0.889663 0.456618 0.000000 +vn 0.889663 0.456618 0.000000 +vn 0.859348 0.456618 0.230262 +vn 0.859348 0.456618 0.230262 +vn 0.889663 0.456618 0.000000 +vn 0.859348 0.456618 -0.230261 +vn 0.859348 0.456618 -0.230261 +vn 0.859348 0.456618 -0.230261 +vn 0.889663 0.456618 0.000000 +vn 0.889663 0.456618 0.000000 +vn 0.859348 0.456618 -0.230261 +vn 0.770470 0.456618 -0.444832 +vn 0.770470 0.456619 -0.444831 +vn 0.770470 0.456619 -0.444831 +vn 0.859348 0.456618 -0.230261 +vn 0.859348 0.456618 -0.230261 +vn 0.770470 0.456618 -0.444832 +vn 0.629086 0.456618 -0.629087 +vn 0.629086 0.456618 -0.629087 +vn 0.629086 0.456618 -0.629087 +vn 0.770470 0.456619 -0.444831 +vn 0.770470 0.456618 -0.444832 +vn 0.629086 0.456618 -0.629087 +vn 0.444831 0.456618 -0.770471 +vn 0.444831 0.456618 -0.770470 +vn 0.444831 0.456618 -0.770470 +vn 0.629086 0.456618 -0.629087 +vn 0.629086 0.456618 -0.629087 +vn 0.444831 0.456618 -0.770471 +vn 0.230262 0.456618 -0.859348 +vn 0.230262 0.456618 -0.859348 +vn 0.230262 0.456618 -0.859348 +vn 0.444831 0.456618 -0.770470 +vn 0.444831 0.456618 -0.770471 +vn 0.230262 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn 0.000000 0.456618 -0.889663 +vn 0.000000 0.456618 -0.889663 +vn 0.230262 0.456618 -0.859348 +vn 0.230262 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn -0.230261 0.456618 -0.859348 +vn -0.230261 0.456618 -0.859348 +vn -0.230261 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn 0.000000 0.456618 -0.889663 +vn -0.230261 0.456618 -0.859348 +vn -0.444831 0.456618 -0.770471 +vn -0.444831 0.456618 -0.770470 +vn -0.444831 0.456618 -0.770470 +vn -0.230261 0.456618 -0.859348 +vn -0.230261 0.456618 -0.859348 +vn -0.444831 0.456618 -0.770471 +vn -0.629086 0.456618 -0.629087 +vn -0.629086 0.456618 -0.629087 +vn -0.629086 0.456618 -0.629087 +vn -0.444831 0.456618 -0.770470 +vn -0.444831 0.456618 -0.770471 +vn -0.629086 0.456618 -0.629087 +vn -0.770470 0.456618 -0.444832 +vn -0.770470 0.456618 -0.444831 +vn -0.770470 0.456618 -0.444831 +vn -0.629086 0.456618 -0.629087 +vn -0.629086 0.456618 -0.629087 +vn -0.770470 0.456618 -0.444832 +vn -0.859348 0.456618 -0.230262 +vn -0.859348 0.456618 -0.230262 +vn -0.859348 0.456618 -0.230262 +vn -0.770470 0.456618 -0.444831 +vn -0.770470 0.456618 -0.444832 +vn -0.859348 0.456618 -0.230262 +vn -0.889663 0.456618 -0.000000 +vn -0.889663 0.456618 -0.000000 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 -0.230262 +vn -0.859348 0.456618 -0.230262 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 0.230261 +vn -0.859348 0.456618 0.230261 +vn -0.859348 0.456618 0.230261 +vn -0.889663 0.456618 -0.000000 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 0.230261 +vn -0.770471 0.456618 0.444831 +vn -0.770471 0.456618 0.444831 +vn -0.770471 0.456618 0.444831 +vn -0.859348 0.456618 0.230261 +vn -0.859348 0.456618 0.230261 +vn -0.770471 0.456618 0.444831 +vn -0.629087 0.456618 0.629086 +vn -0.629087 0.456618 0.629086 +vn -0.629087 0.456618 0.629086 +vn -0.770471 0.456618 0.444831 +vn -0.770471 0.456618 0.444831 +vn -0.629087 0.456618 0.629086 +vn -0.444831 0.456618 0.770471 +vn -0.444832 0.456618 0.770470 +vn -0.444832 0.456618 0.770470 +vn -0.629087 0.456618 0.629086 +vn -0.629087 0.456618 0.629086 +vn -0.444831 0.456618 0.770471 +vn -0.230262 0.456618 0.859348 +vn -0.230262 0.456618 0.859348 +vn -0.230262 0.456618 0.859348 +vn -0.444832 0.456618 0.770470 +vn -0.444831 0.456618 0.770471 +vn -0.230262 0.456618 0.859348 +vn -0.000001 0.456618 0.889663 +vn -0.000001 0.456618 0.889663 +vn -0.000001 0.456618 0.889663 +vn -0.230262 0.456618 0.859348 +vn -0.230262 0.456618 0.859348 +vn -0.000001 0.456618 0.889663 +vn 0.230261 0.456618 0.859348 +vn 0.230261 0.456618 0.859348 +vn 0.230261 0.456618 0.859348 +vn -0.000001 0.456618 0.889663 +vn -0.000001 0.456618 0.889663 +vn 0.230261 0.456618 0.859348 +vn 0.444831 0.456618 0.770471 +vn 0.444831 0.456618 0.770471 +vn 0.444831 0.456618 0.770471 +vn 0.230261 0.456618 0.859348 +vn 0.230261 0.456618 0.859348 +vn 0.444831 0.456618 0.770471 +vn 0.629086 0.456618 0.629087 +vn 0.629086 0.456618 0.629087 +vn 0.629086 0.456618 0.629087 +vn 0.444831 0.456618 0.770471 +vn 0.444831 0.456618 0.770471 +vn 0.629086 0.456618 0.629087 +vn 0.770470 0.456618 0.444832 +vn 0.770470 0.456618 0.444831 +vn 0.770470 0.456618 0.444831 +vn 0.629086 0.456618 0.629087 +vn 0.629086 0.456618 0.629087 +vn 0.770470 0.456618 0.444832 +vn 0.859348 0.456618 0.230262 +vn 0.859348 0.456618 0.230262 +vn 0.859348 0.456618 0.230262 +vn 0.770470 0.456618 0.444831 +vn 0.770470 0.456618 0.444832 +vn 0.859348 0.456618 0.230262 +vn 0.889663 0.456618 0.000000 +vn 0.889663 0.456618 0.000000 +vn 0.889663 0.456618 0.000000 +vn 0.859348 0.456618 0.230262 +vn 0.859348 0.456618 0.230262 +vn 0.889663 0.456618 0.000000 +vn 0.859348 0.456618 -0.230261 +vn 0.859348 0.456618 -0.230262 +vn 0.859348 0.456618 -0.230262 +vn 0.889663 0.456618 0.000000 +vn 0.889663 0.456618 0.000000 +vn 0.859348 0.456618 -0.230261 +vn 0.770470 0.456619 -0.444831 +vn 0.770470 0.456618 -0.444831 +vn 0.770470 0.456618 -0.444831 +vn 0.859348 0.456618 -0.230262 +vn 0.859348 0.456618 -0.230261 +vn 0.770470 0.456619 -0.444831 +vn 0.629086 0.456618 -0.629087 +vn 0.629086 0.456618 -0.629087 +vn 0.629086 0.456618 -0.629087 +vn 0.770470 0.456618 -0.444831 +vn 0.770470 0.456619 -0.444831 +vn 0.629086 0.456618 -0.629087 +vn 0.444831 0.456618 -0.770470 +vn 0.444831 0.456618 -0.770470 +vn 0.444831 0.456618 -0.770470 +vn 0.629086 0.456618 -0.629087 +vn 0.629086 0.456618 -0.629087 +vn 0.444831 0.456618 -0.770470 +vn 0.230262 0.456618 -0.859348 +vn 0.230263 0.456618 -0.859348 +vn 0.230263 0.456618 -0.859348 +vn 0.444831 0.456618 -0.770470 +vn 0.444831 0.456618 -0.770470 +vn 0.230262 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn 0.000000 0.456618 -0.889663 +vn 0.000000 0.456618 -0.889663 +vn 0.230263 0.456618 -0.859348 +vn 0.230262 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn -0.230261 0.456618 -0.859348 +vn -0.230262 0.456618 -0.859348 +vn -0.230262 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn 0.000000 0.456618 -0.889663 +vn -0.230261 0.456618 -0.859348 +vn -0.444831 0.456618 -0.770470 +vn -0.444831 0.456618 -0.770471 +vn -0.444831 0.456618 -0.770471 +vn -0.230262 0.456618 -0.859348 +vn -0.230261 0.456618 -0.859348 +vn -0.444831 0.456618 -0.770470 +vn -0.629086 0.456618 -0.629087 +vn -0.629087 0.456619 -0.629086 +vn -0.629087 0.456619 -0.629086 +vn -0.444831 0.456618 -0.770471 +vn -0.444831 0.456618 -0.770470 +vn -0.629086 0.456618 -0.629087 +vn -0.770470 0.456618 -0.444831 +vn -0.770471 0.456618 -0.444831 +vn -0.770471 0.456618 -0.444831 +vn -0.629087 0.456619 -0.629086 +vn -0.629086 0.456618 -0.629087 +vn -0.770470 0.456618 -0.444831 +vn -0.859348 0.456618 -0.230262 +vn -0.859348 0.456618 -0.230262 +vn -0.859348 0.456618 -0.230262 +vn -0.770471 0.456618 -0.444831 +vn -0.770470 0.456618 -0.444831 +vn -0.859348 0.456618 -0.230262 +vn -0.889663 0.456618 -0.000000 +vn -0.889663 0.456618 -0.000000 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 -0.230262 +vn -0.859348 0.456618 -0.230262 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 0.230261 +vn -0.859348 0.456618 0.230261 +vn -0.859348 0.456618 0.230261 +vn -0.889663 0.456618 -0.000000 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 0.230261 +vn -0.770471 0.456618 0.444831 +vn -0.770471 0.456618 0.444831 +vn -0.770471 0.456618 0.444831 +vn -0.859348 0.456618 0.230261 +vn -0.859348 0.456618 0.230261 +vn -0.770471 0.456618 0.444831 +vn -0.629087 0.456618 0.629086 +vn -0.629087 0.456618 0.629086 +vn -0.629087 0.456618 0.629086 +vn -0.770471 0.456618 0.444831 +vn -0.770471 0.456618 0.444831 +vn -0.629087 0.456618 0.629086 +vn -0.444832 0.456618 0.770470 +vn -0.444832 0.456618 0.770470 +vn -0.444832 0.456618 0.770470 +vn -0.629087 0.456618 0.629086 +vn -0.629087 0.456618 0.629086 +vn -0.444832 0.456618 0.770470 +vn -0.230262 0.456618 0.859348 +vn -0.230261 0.456618 0.859348 +vn -0.230261 0.456618 0.859348 +vn -0.444832 0.456618 0.770470 +vn -0.444832 0.456618 0.770470 +vn -0.230262 0.456618 0.859348 +vn -0.000001 0.456618 0.889663 +vn -0.000001 0.456618 0.889663 +vn -0.000001 0.456618 0.889663 +vn -0.230261 0.456618 0.859348 +vn -0.230262 0.456618 0.859348 +vn -0.000001 0.456618 0.889663 +vn 0.230261 0.456618 0.859348 +vn 0.230261 0.456619 0.859348 +vn 0.230261 0.456619 0.859348 +vn -0.000001 0.456618 0.889663 +vn -0.000001 0.456618 0.889663 +vn 0.230261 0.456618 0.859348 +vn 0.444831 0.456618 0.770471 +vn 0.444831 0.456618 0.770471 +vn 0.444831 0.456618 0.770471 +vn 0.230261 0.456619 0.859348 +vn 0.230261 0.456618 0.859348 +vn 0.444831 0.456618 0.770471 +vn 0.629086 0.456618 0.629087 +vn 0.629086 0.456618 0.629086 +vn 0.629086 0.456618 0.629086 +vn 0.444831 0.456618 0.770471 +vn 0.444831 0.456618 0.770471 +vn 0.629086 0.456618 0.629087 +vn 0.770470 0.456618 0.444831 +vn 0.770470 0.456618 0.444832 +vn 0.770470 0.456618 0.444832 +vn 0.629086 0.456618 0.629086 +vn 0.629086 0.456618 0.629087 +vn 0.770470 0.456618 0.444831 +vn 0.859348 0.456618 0.230262 +vn 0.859348 0.456618 0.230263 +vn 0.859348 0.456618 0.230263 +vn 0.770470 0.456618 0.444832 +vn 0.770470 0.456618 0.444831 +vn 0.859348 0.456618 0.230262 +vn 0.889663 0.456618 0.000000 +vn 0.889663 0.456618 0.000000 +vn 0.889663 0.456618 0.000000 +vn 0.859348 0.456618 0.230263 +vn 0.859348 0.456618 0.230262 +vn 0.889663 0.456618 0.000000 +vn 0.859348 0.456618 -0.230262 +vn 0.883622 0.453518 -0.116331 +vn 0.883622 0.453518 -0.116331 +vn 0.883622 0.453518 0.116332 +vn 0.889663 0.456618 0.000000 +vn 0.859348 0.456618 -0.230262 +vn 0.770470 0.456618 -0.444831 +vn 0.823405 0.453518 -0.341066 +vn 0.823405 0.453518 -0.341066 +vn 0.883622 0.453518 -0.116331 +vn 0.859348 0.456618 -0.230262 +vn 0.770470 0.456618 -0.444831 +vn 0.629086 0.456618 -0.629087 +vn 0.707074 0.453518 -0.542557 +vn 0.707074 0.453518 -0.542557 +vn 0.823405 0.453518 -0.341066 +vn 0.770470 0.456618 -0.444831 +vn 0.629086 0.456618 -0.629087 +vn 0.444831 0.456618 -0.770470 +vn 0.542556 0.453518 -0.707074 +vn 0.542556 0.453518 -0.707074 +vn 0.707074 0.453518 -0.542557 +vn 0.629086 0.456618 -0.629087 +vn 0.444831 0.456618 -0.770470 +vn 0.230263 0.456618 -0.859348 +vn 0.341066 0.453518 -0.823405 +vn 0.341066 0.453518 -0.823405 +vn 0.542556 0.453518 -0.707074 +vn 0.444831 0.456618 -0.770470 +vn 0.230263 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn 0.116332 0.453518 -0.883622 +vn 0.116332 0.453518 -0.883622 +vn 0.341066 0.453518 -0.823405 +vn 0.230263 0.456618 -0.859348 +vn 0.000000 0.456618 -0.889663 +vn -0.230262 0.456618 -0.859348 +vn -0.116332 0.453518 -0.883622 +vn -0.116332 0.453518 -0.883622 +vn 0.116332 0.453518 -0.883622 +vn 0.000000 0.456618 -0.889663 +vn -0.230262 0.456618 -0.859348 +vn -0.444831 0.456618 -0.770471 +vn -0.341066 0.453518 -0.823405 +vn -0.341066 0.453518 -0.823405 +vn -0.116332 0.453518 -0.883622 +vn -0.230262 0.456618 -0.859348 +vn -0.444831 0.456618 -0.770471 +vn -0.629087 0.456619 -0.629086 +vn -0.542555 0.453518 -0.707075 +vn -0.542555 0.453518 -0.707075 +vn -0.341066 0.453518 -0.823405 +vn -0.444831 0.456618 -0.770471 +vn -0.629087 0.456619 -0.629086 +vn -0.770471 0.456618 -0.444831 +vn -0.707075 0.453518 -0.542555 +vn -0.707075 0.453518 -0.542555 +vn -0.542555 0.453518 -0.707075 +vn -0.629087 0.456619 -0.629086 +vn -0.770471 0.456618 -0.444831 +vn -0.859348 0.456618 -0.230262 +vn -0.823405 0.453518 -0.341066 +vn -0.823405 0.453518 -0.341066 +vn -0.707075 0.453518 -0.542555 +vn -0.770471 0.456618 -0.444831 +vn -0.859348 0.456618 -0.230262 +vn -0.889663 0.456618 -0.000000 +vn -0.883622 0.453518 -0.116332 +vn -0.883622 0.453518 -0.116332 +vn -0.823405 0.453518 -0.341066 +vn -0.859348 0.456618 -0.230262 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 0.230261 +vn -0.883622 0.453518 0.116331 +vn -0.883622 0.453518 0.116331 +vn -0.883622 0.453518 -0.116332 +vn -0.889663 0.456618 -0.000000 +vn -0.859348 0.456618 0.230261 +vn -0.770471 0.456618 0.444831 +vn -0.823405 0.453518 0.341065 +vn -0.823405 0.453518 0.341065 +vn -0.883622 0.453518 0.116331 +vn -0.859348 0.456618 0.230261 +vn -0.770471 0.456618 0.444831 +vn -0.629087 0.456618 0.629086 +vn -0.707074 0.453518 0.542557 +vn -0.707074 0.453518 0.542557 +vn -0.823405 0.453518 0.341065 +vn -0.770471 0.456618 0.444831 +vn -0.629087 0.456618 0.629086 +vn -0.444832 0.456618 0.770470 +vn -0.542558 0.453518 0.707073 +vn -0.542558 0.453518 0.707073 +vn -0.707074 0.453518 0.542557 +vn -0.629087 0.456618 0.629086 +vn -0.444832 0.456618 0.770470 +vn -0.230261 0.456618 0.859348 +vn -0.341066 0.453518 0.823405 +vn -0.341066 0.453518 0.823405 +vn -0.542558 0.453518 0.707073 +vn -0.444832 0.456618 0.770470 +vn -0.230261 0.456618 0.859348 +vn -0.000001 0.456618 0.889663 +vn -0.116330 0.453518 0.883622 +vn -0.116330 0.453518 0.883622 +vn -0.341066 0.453518 0.823405 +vn -0.230261 0.456618 0.859348 +vn -0.000001 0.456618 0.889663 +vn 0.230261 0.456619 0.859348 +vn 0.116328 0.453518 0.883623 +vn 0.116328 0.453518 0.883623 +vn -0.116330 0.453518 0.883622 +vn -0.000001 0.456618 0.889663 +vn 0.230261 0.456619 0.859348 +vn 0.444831 0.456618 0.770471 +vn 0.341066 0.453518 0.823405 +vn 0.341066 0.453518 0.823405 +vn 0.116328 0.453518 0.883623 +vn 0.230261 0.456619 0.859348 +vn 0.444831 0.456618 0.770471 +vn 0.629086 0.456618 0.629086 +vn 0.542556 0.453518 0.707075 +vn 0.542556 0.453518 0.707075 +vn 0.341066 0.453518 0.823405 +vn 0.444831 0.456618 0.770471 +vn 0.629086 0.456618 0.629086 +vn 0.770470 0.456618 0.444832 +vn 0.707075 0.453518 0.542556 +vn 0.707075 0.453518 0.542556 +vn 0.542556 0.453518 0.707075 +vn 0.629086 0.456618 0.629086 +vn 0.770470 0.456618 0.444832 +vn 0.859348 0.456618 0.230263 +vn 0.823404 0.453518 0.341068 +vn 0.823404 0.453518 0.341068 +vn 0.707075 0.453518 0.542556 +vn 0.770470 0.456618 0.444832 +vn 0.859348 0.456618 0.230263 +vn 0.889663 0.456618 0.000000 +vn 0.883622 0.453518 0.116332 +vn 0.883622 0.453518 0.116332 +vn 0.823404 0.453518 0.341068 +vn 0.859348 0.456618 0.230263 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.000000 -1.000000 -0.000000 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +vn 0.966881 0.000000 -0.255228 +# 3768 vertex normals + +vt 1.000000 0.000000 0.000000 +vt 0.000000 0.000000 0.000000 +vt 1.000000 1.000000 0.000000 +vt 0.000000 1.000000 0.000000 +vt 0.000000 0.000000 0.000000 +vt 1.000000 0.000000 0.000000 +vt 0.000000 1.000000 0.000000 +vt 1.000000 1.000000 0.000000 +vt 0.000000 0.000000 0.000000 +vt 1.000000 0.000000 0.000000 +vt 0.000000 1.000000 0.000000 +vt 1.000000 1.000000 0.000000 +vt 0.000000 0.000000 0.000000 +vt 1.000000 0.000000 0.000000 +vt 0.000000 1.000000 0.000000 +vt 1.000000 1.000000 0.000000 +vt 0.000000 0.000000 0.000000 +vt 1.000000 0.000000 0.000000 +vt 0.000000 1.000000 0.000000 +vt 1.000000 1.000000 0.000000 +vt 0.000000 0.000000 0.000000 +vt 1.000000 0.000000 0.000000 +vt 0.000000 1.000000 0.000000 +vt 1.000000 1.000000 0.000000 +vt 0.000000 1.000000 0.000000 +vt 0.031250 1.000000 0.000000 +vt 0.062500 1.000000 0.000000 +vt 0.093750 1.000000 0.000000 +vt 0.125000 1.000000 0.000000 +vt 0.156250 1.000000 0.000000 +vt 0.187500 1.000000 0.000000 +vt 0.218750 1.000000 0.000000 +vt 0.250000 1.000000 0.000000 +vt 0.281250 1.000000 0.000000 +vt 0.312500 1.000000 0.000000 +vt 0.343750 1.000000 0.000000 +vt 0.375000 1.000000 0.000000 +vt 0.406250 1.000000 0.000000 +vt 0.437500 1.000000 0.000000 +vt 0.468750 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.531250 1.000000 0.000000 +vt 0.562500 1.000000 0.000000 +vt 0.593750 1.000000 0.000000 +vt 0.625000 1.000000 0.000000 +vt 0.656250 1.000000 0.000000 +vt 0.687500 1.000000 0.000000 +vt 0.718750 1.000000 0.000000 +vt 0.750000 1.000000 0.000000 +vt 0.781250 1.000000 0.000000 +vt 0.812500 1.000000 0.000000 +vt 0.843750 1.000000 0.000000 +vt 0.875000 1.000000 0.000000 +vt 0.906250 1.000000 0.000000 +vt 0.937500 1.000000 0.000000 +vt 0.968750 1.000000 0.000000 +vt 0.000000 0.937500 0.000000 +vt 0.031250 0.937500 0.000000 +vt 0.062500 0.937500 0.000000 +vt 0.093750 0.937500 0.000000 +vt 0.125000 0.937500 0.000000 +vt 0.156250 0.937500 0.000000 +vt 0.187500 0.937500 0.000000 +vt 0.218750 0.937500 0.000000 +vt 0.250000 0.937500 0.000000 +vt 0.281250 0.937500 0.000000 +vt 0.312500 0.937500 0.000000 +vt 0.343750 0.937500 0.000000 +vt 0.375000 0.937500 0.000000 +vt 0.406250 0.937500 0.000000 +vt 0.437500 0.937500 0.000000 +vt 0.468750 0.937500 0.000000 +vt 0.500000 0.937500 0.000000 +vt 0.531250 0.937500 0.000000 +vt 0.562500 0.937500 0.000000 +vt 0.593750 0.937500 0.000000 +vt 0.625000 0.937500 0.000000 +vt 0.656250 0.937500 0.000000 +vt 0.687500 0.937500 0.000000 +vt 0.718750 0.937500 0.000000 +vt 0.750000 0.937500 0.000000 +vt 0.781250 0.937500 0.000000 +vt 0.812500 0.937500 0.000000 +vt 0.843750 0.937500 0.000000 +vt 0.875000 0.937500 0.000000 +vt 0.906250 0.937500 0.000000 +vt 0.937500 0.937500 0.000000 +vt 0.968750 0.937500 0.000000 +vt 1.000000 0.937500 0.000000 +vt 0.000000 0.875000 0.000000 +vt 0.031250 0.875000 0.000000 +vt 0.062500 0.875000 0.000000 +vt 0.093750 0.875000 0.000000 +vt 0.125000 0.875000 0.000000 +vt 0.156250 0.875000 0.000000 +vt 0.187500 0.875000 0.000000 +vt 0.218750 0.875000 0.000000 +vt 0.250000 0.875000 0.000000 +vt 0.281250 0.875000 0.000000 +vt 0.312500 0.875000 0.000000 +vt 0.343750 0.875000 0.000000 +vt 0.375000 0.875000 0.000000 +vt 0.406250 0.875000 0.000000 +vt 0.437500 0.875000 0.000000 +vt 0.468750 0.875000 0.000000 +vt 0.500000 0.875000 0.000000 +vt 0.531250 0.875000 0.000000 +vt 0.562500 0.875000 0.000000 +vt 0.593750 0.875000 0.000000 +vt 0.625000 0.875000 0.000000 +vt 0.656250 0.875000 0.000000 +vt 0.687500 0.875000 0.000000 +vt 0.718750 0.875000 0.000000 +vt 0.750000 0.875000 0.000000 +vt 0.781250 0.875000 0.000000 +vt 0.812500 0.875000 0.000000 +vt 0.843750 0.875000 0.000000 +vt 0.875000 0.875000 0.000000 +vt 0.906250 0.875000 0.000000 +vt 0.937500 0.875000 0.000000 +vt 0.968750 0.875000 0.000000 +vt 1.000000 0.875000 0.000000 +vt 0.000000 0.812500 0.000000 +vt 0.031250 0.812500 0.000000 +vt 0.062500 0.812500 0.000000 +vt 0.093750 0.812500 0.000000 +vt 0.125000 0.812500 0.000000 +vt 0.156250 0.812500 0.000000 +vt 0.187500 0.812500 0.000000 +vt 0.218750 0.812500 0.000000 +vt 0.250000 0.812500 0.000000 +vt 0.281250 0.812500 0.000000 +vt 0.312500 0.812500 0.000000 +vt 0.343750 0.812500 0.000000 +vt 0.375000 0.812500 0.000000 +vt 0.406250 0.812500 0.000000 +vt 0.437500 0.812500 0.000000 +vt 0.468750 0.812500 0.000000 +vt 0.500000 0.812500 0.000000 +vt 0.531250 0.812500 0.000000 +vt 0.562500 0.812500 0.000000 +vt 0.593750 0.812500 0.000000 +vt 0.625000 0.812500 0.000000 +vt 0.656250 0.812500 0.000000 +vt 0.687500 0.812500 0.000000 +vt 0.718750 0.812500 0.000000 +vt 0.750000 0.812500 0.000000 +vt 0.781250 0.812500 0.000000 +vt 0.812500 0.812500 0.000000 +vt 0.843750 0.812500 0.000000 +vt 0.875000 0.812500 0.000000 +vt 0.906250 0.812500 0.000000 +vt 0.937500 0.812500 0.000000 +vt 0.968750 0.812500 0.000000 +vt 1.000000 0.812500 0.000000 +vt 0.000000 0.750000 0.000000 +vt 0.031250 0.750000 0.000000 +vt 0.062500 0.750000 0.000000 +vt 0.093750 0.750000 0.000000 +vt 0.125000 0.750000 0.000000 +vt 0.156250 0.750000 0.000000 +vt 0.187500 0.750000 0.000000 +vt 0.218750 0.750000 0.000000 +vt 0.250000 0.750000 0.000000 +vt 0.281250 0.750000 0.000000 +vt 0.312500 0.750000 0.000000 +vt 0.343750 0.750000 0.000000 +vt 0.375000 0.750000 0.000000 +vt 0.406250 0.750000 0.000000 +vt 0.437500 0.750000 0.000000 +vt 0.468750 0.750000 0.000000 +vt 0.500000 0.750000 0.000000 +vt 0.531250 0.750000 0.000000 +vt 0.562500 0.750000 0.000000 +vt 0.593750 0.750000 0.000000 +vt 0.625000 0.750000 0.000000 +vt 0.656250 0.750000 0.000000 +vt 0.687500 0.750000 0.000000 +vt 0.718750 0.750000 0.000000 +vt 0.750000 0.750000 0.000000 +vt 0.781250 0.750000 0.000000 +vt 0.812500 0.750000 0.000000 +vt 0.843750 0.750000 0.000000 +vt 0.875000 0.750000 0.000000 +vt 0.906250 0.750000 0.000000 +vt 0.937500 0.750000 0.000000 +vt 0.968750 0.750000 0.000000 +vt 1.000000 0.750000 0.000000 +vt 0.000000 0.687500 0.000000 +vt 0.031250 0.687500 0.000000 +vt 0.062500 0.687500 0.000000 +vt 0.093750 0.687500 0.000000 +vt 0.125000 0.687500 0.000000 +vt 0.156250 0.687500 0.000000 +vt 0.187500 0.687500 0.000000 +vt 0.218750 0.687500 0.000000 +vt 0.250000 0.687500 0.000000 +vt 0.281250 0.687500 0.000000 +vt 0.312500 0.687500 0.000000 +vt 0.343750 0.687500 0.000000 +vt 0.375000 0.687500 0.000000 +vt 0.406250 0.687500 0.000000 +vt 0.437500 0.687500 0.000000 +vt 0.468750 0.687500 0.000000 +vt 0.500000 0.687500 0.000000 +vt 0.531250 0.687500 0.000000 +vt 0.562500 0.687500 0.000000 +vt 0.593750 0.687500 0.000000 +vt 0.625000 0.687500 0.000000 +vt 0.656250 0.687500 0.000000 +vt 0.687500 0.687500 0.000000 +vt 0.718750 0.687500 0.000000 +vt 0.750000 0.687500 0.000000 +vt 0.781250 0.687500 0.000000 +vt 0.812500 0.687500 0.000000 +vt 0.843750 0.687500 0.000000 +vt 0.875000 0.687500 0.000000 +vt 0.906250 0.687500 0.000000 +vt 0.937500 0.687500 0.000000 +vt 0.968750 0.687500 0.000000 +vt 1.000000 0.687500 0.000000 +vt 0.000000 0.625000 0.000000 +vt 0.031250 0.625000 0.000000 +vt 0.062500 0.625000 0.000000 +vt 0.093750 0.625000 0.000000 +vt 0.125000 0.625000 0.000000 +vt 0.156250 0.625000 0.000000 +vt 0.187500 0.625000 0.000000 +vt 0.218750 0.625000 0.000000 +vt 0.250000 0.625000 0.000000 +vt 0.281250 0.625000 0.000000 +vt 0.312500 0.625000 0.000000 +vt 0.343750 0.625000 0.000000 +vt 0.375000 0.625000 0.000000 +vt 0.406250 0.625000 0.000000 +vt 0.437500 0.625000 0.000000 +vt 0.468750 0.625000 0.000000 +vt 0.500000 0.625000 0.000000 +vt 0.531250 0.625000 0.000000 +vt 0.562500 0.625000 0.000000 +vt 0.593750 0.625000 0.000000 +vt 0.625000 0.625000 0.000000 +vt 0.656250 0.625000 0.000000 +vt 0.687500 0.625000 0.000000 +vt 0.718750 0.625000 0.000000 +vt 0.750000 0.625000 0.000000 +vt 0.781250 0.625000 0.000000 +vt 0.812500 0.625000 0.000000 +vt 0.843750 0.625000 0.000000 +vt 0.875000 0.625000 0.000000 +vt 0.906250 0.625000 0.000000 +vt 0.937500 0.625000 0.000000 +vt 0.968750 0.625000 0.000000 +vt 1.000000 0.625000 0.000000 +vt 0.000000 0.562500 0.000000 +vt 0.031250 0.562500 0.000000 +vt 0.062500 0.562500 0.000000 +vt 0.093750 0.562500 0.000000 +vt 0.125000 0.562500 0.000000 +vt 0.156250 0.562500 0.000000 +vt 0.187500 0.562500 0.000000 +vt 0.218750 0.562500 0.000000 +vt 0.250000 0.562500 0.000000 +vt 0.281250 0.562500 0.000000 +vt 0.312500 0.562500 0.000000 +vt 0.343750 0.562500 0.000000 +vt 0.375000 0.562500 0.000000 +vt 0.406250 0.562500 0.000000 +vt 0.437500 0.562500 0.000000 +vt 0.468750 0.562500 0.000000 +vt 0.500000 0.562500 0.000000 +vt 0.531250 0.562500 0.000000 +vt 0.562500 0.562500 0.000000 +vt 0.593750 0.562500 0.000000 +vt 0.625000 0.562500 0.000000 +vt 0.656250 0.562500 0.000000 +vt 0.687500 0.562500 0.000000 +vt 0.718750 0.562500 0.000000 +vt 0.750000 0.562500 0.000000 +vt 0.781250 0.562500 0.000000 +vt 0.812500 0.562500 0.000000 +vt 0.843750 0.562500 0.000000 +vt 0.875000 0.562500 0.000000 +vt 0.906250 0.562500 0.000000 +vt 0.937500 0.562500 0.000000 +vt 0.968750 0.562500 0.000000 +vt 1.000000 0.562500 0.000000 +vt 0.000000 0.500000 0.000000 +vt 0.031250 0.500000 0.000000 +vt 0.062500 0.500000 0.000000 +vt 0.093750 0.500000 0.000000 +vt 0.125000 0.500000 0.000000 +vt 0.156250 0.500000 0.000000 +vt 0.187500 0.500000 0.000000 +vt 0.218750 0.500000 0.000000 +vt 0.250000 0.500000 0.000000 +vt 0.281250 0.500000 0.000000 +vt 0.312500 0.500000 0.000000 +vt 0.343750 0.500000 0.000000 +vt 0.375000 0.500000 0.000000 +vt 0.406250 0.500000 0.000000 +vt 0.437500 0.500000 0.000000 +vt 0.468750 0.500000 0.000000 +vt 0.500000 0.500000 0.000000 +vt 0.531250 0.500000 0.000000 +vt 0.562500 0.500000 0.000000 +vt 0.593750 0.500000 0.000000 +vt 0.625000 0.500000 0.000000 +vt 0.656250 0.500000 0.000000 +vt 0.687500 0.500000 0.000000 +vt 0.718750 0.500000 0.000000 +vt 0.750000 0.500000 0.000000 +vt 0.781250 0.500000 0.000000 +vt 0.812500 0.500000 0.000000 +vt 0.843750 0.500000 0.000000 +vt 0.875000 0.500000 0.000000 +vt 0.906250 0.500000 0.000000 +vt 0.937500 0.500000 0.000000 +vt 0.968750 0.500000 0.000000 +vt 1.000000 0.500000 0.000000 +vt 0.000000 0.437500 0.000000 +vt 0.031250 0.437500 0.000000 +vt 0.062500 0.437500 0.000000 +vt 0.093750 0.437500 0.000000 +vt 0.125000 0.437500 0.000000 +vt 0.156250 0.437500 0.000000 +vt 0.187500 0.437500 0.000000 +vt 0.218750 0.437500 0.000000 +vt 0.250000 0.437500 0.000000 +vt 0.281250 0.437500 0.000000 +vt 0.312500 0.437500 0.000000 +vt 0.343750 0.437500 0.000000 +vt 0.375000 0.437500 0.000000 +vt 0.406250 0.437500 0.000000 +vt 0.437500 0.437500 0.000000 +vt 0.468750 0.437500 0.000000 +vt 0.500000 0.437500 0.000000 +vt 0.531250 0.437500 0.000000 +vt 0.562500 0.437500 0.000000 +vt 0.593750 0.437500 0.000000 +vt 0.625000 0.437500 0.000000 +vt 0.656250 0.437500 0.000000 +vt 0.687500 0.437500 0.000000 +vt 0.718750 0.437500 0.000000 +vt 0.750000 0.437500 0.000000 +vt 0.781250 0.437500 0.000000 +vt 0.812500 0.437500 0.000000 +vt 0.843750 0.437500 0.000000 +vt 0.875000 0.437500 0.000000 +vt 0.906250 0.437500 0.000000 +vt 0.937500 0.437500 0.000000 +vt 0.968750 0.437500 0.000000 +vt 1.000000 0.437500 0.000000 +vt 0.000000 0.375000 0.000000 +vt 0.031250 0.375000 0.000000 +vt 0.062500 0.375000 0.000000 +vt 0.093750 0.375000 0.000000 +vt 0.125000 0.375000 0.000000 +vt 0.156250 0.375000 0.000000 +vt 0.187500 0.375000 0.000000 +vt 0.218750 0.375000 0.000000 +vt 0.250000 0.375000 0.000000 +vt 0.281250 0.375000 0.000000 +vt 0.312500 0.375000 0.000000 +vt 0.343750 0.375000 0.000000 +vt 0.375000 0.375000 0.000000 +vt 0.406250 0.375000 0.000000 +vt 0.437500 0.375000 0.000000 +vt 0.468750 0.375000 0.000000 +vt 0.500000 0.375000 0.000000 +vt 0.531250 0.375000 0.000000 +vt 0.562500 0.375000 0.000000 +vt 0.593750 0.375000 0.000000 +vt 0.625000 0.375000 0.000000 +vt 0.656250 0.375000 0.000000 +vt 0.687500 0.375000 0.000000 +vt 0.718750 0.375000 0.000000 +vt 0.750000 0.375000 0.000000 +vt 0.781250 0.375000 0.000000 +vt 0.812500 0.375000 0.000000 +vt 0.843750 0.375000 0.000000 +vt 0.875000 0.375000 0.000000 +vt 0.906250 0.375000 0.000000 +vt 0.937500 0.375000 0.000000 +vt 0.968750 0.375000 0.000000 +vt 1.000000 0.375000 0.000000 +vt 0.000000 0.312500 0.000000 +vt 0.031250 0.312500 0.000000 +vt 0.062500 0.312500 0.000000 +vt 0.093750 0.312500 0.000000 +vt 0.125000 0.312500 0.000000 +vt 0.156250 0.312500 0.000000 +vt 0.187500 0.312500 0.000000 +vt 0.218750 0.312500 0.000000 +vt 0.250000 0.312500 0.000000 +vt 0.281250 0.312500 0.000000 +vt 0.312500 0.312500 0.000000 +vt 0.343750 0.312500 0.000000 +vt 0.375000 0.312500 0.000000 +vt 0.406250 0.312500 0.000000 +vt 0.437500 0.312500 0.000000 +vt 0.468750 0.312500 0.000000 +vt 0.500000 0.312500 0.000000 +vt 0.531250 0.312500 0.000000 +vt 0.562500 0.312500 0.000000 +vt 0.593750 0.312500 0.000000 +vt 0.625000 0.312500 0.000000 +vt 0.656250 0.312500 0.000000 +vt 0.687500 0.312500 0.000000 +vt 0.718750 0.312500 0.000000 +vt 0.750000 0.312500 0.000000 +vt 0.781250 0.312500 0.000000 +vt 0.812500 0.312500 0.000000 +vt 0.843750 0.312500 0.000000 +vt 0.875000 0.312500 0.000000 +vt 0.906250 0.312500 0.000000 +vt 0.937500 0.312500 0.000000 +vt 0.968750 0.312500 0.000000 +vt 1.000000 0.312500 0.000000 +vt 0.000000 0.250000 0.000000 +vt 0.031250 0.250000 0.000000 +vt 0.062500 0.250000 0.000000 +vt 0.093750 0.250000 0.000000 +vt 0.125000 0.250000 0.000000 +vt 0.156250 0.250000 0.000000 +vt 0.187500 0.250000 0.000000 +vt 0.218750 0.250000 0.000000 +vt 0.250000 0.250000 0.000000 +vt 0.281250 0.250000 0.000000 +vt 0.312500 0.250000 0.000000 +vt 0.343750 0.250000 0.000000 +vt 0.375000 0.250000 0.000000 +vt 0.406250 0.250000 0.000000 +vt 0.437500 0.250000 0.000000 +vt 0.468750 0.250000 0.000000 +vt 0.500000 0.250000 0.000000 +vt 0.531250 0.250000 0.000000 +vt 0.562500 0.250000 0.000000 +vt 0.593750 0.250000 0.000000 +vt 0.625000 0.250000 0.000000 +vt 0.656250 0.250000 0.000000 +vt 0.687500 0.250000 0.000000 +vt 0.718750 0.250000 0.000000 +vt 0.750000 0.250000 0.000000 +vt 0.781250 0.250000 0.000000 +vt 0.812500 0.250000 0.000000 +vt 0.843750 0.250000 0.000000 +vt 0.875000 0.250000 0.000000 +vt 0.906250 0.250000 0.000000 +vt 0.937500 0.250000 0.000000 +vt 0.968750 0.250000 0.000000 +vt 1.000000 0.250000 0.000000 +vt 0.000000 0.187500 0.000000 +vt 0.031250 0.187500 0.000000 +vt 0.062500 0.187500 0.000000 +vt 0.093750 0.187500 0.000000 +vt 0.125000 0.187500 0.000000 +vt 0.156250 0.187500 0.000000 +vt 0.187500 0.187500 0.000000 +vt 0.218750 0.187500 0.000000 +vt 0.250000 0.187500 0.000000 +vt 0.281250 0.187500 0.000000 +vt 0.312500 0.187500 0.000000 +vt 0.343750 0.187500 0.000000 +vt 0.375000 0.187500 0.000000 +vt 0.406250 0.187500 0.000000 +vt 0.437500 0.187500 0.000000 +vt 0.468750 0.187500 0.000000 +vt 0.500000 0.187500 0.000000 +vt 0.531250 0.187500 0.000000 +vt 0.562500 0.187500 0.000000 +vt 0.593750 0.187500 0.000000 +vt 0.625000 0.187500 0.000000 +vt 0.656250 0.187500 0.000000 +vt 0.687500 0.187500 0.000000 +vt 0.718750 0.187500 0.000000 +vt 0.750000 0.187500 0.000000 +vt 0.781250 0.187500 0.000000 +vt 0.812500 0.187500 0.000000 +vt 0.843750 0.187500 0.000000 +vt 0.875000 0.187500 0.000000 +vt 0.906250 0.187500 0.000000 +vt 0.937500 0.187500 0.000000 +vt 0.968750 0.187500 0.000000 +vt 1.000000 0.187500 0.000000 +vt 0.000000 0.125000 0.000000 +vt 0.031250 0.125000 0.000000 +vt 0.062500 0.125000 0.000000 +vt 0.093750 0.125000 0.000000 +vt 0.125000 0.125000 0.000000 +vt 0.156250 0.125000 0.000000 +vt 0.187500 0.125000 0.000000 +vt 0.218750 0.125000 0.000000 +vt 0.250000 0.125000 0.000000 +vt 0.281250 0.125000 0.000000 +vt 0.312500 0.125000 0.000000 +vt 0.343750 0.125000 0.000000 +vt 0.375000 0.125000 0.000000 +vt 0.406250 0.125000 0.000000 +vt 0.437500 0.125000 0.000000 +vt 0.468750 0.125000 0.000000 +vt 0.500000 0.125000 0.000000 +vt 0.531250 0.125000 0.000000 +vt 0.562500 0.125000 0.000000 +vt 0.593750 0.125000 0.000000 +vt 0.625000 0.125000 0.000000 +vt 0.656250 0.125000 0.000000 +vt 0.687500 0.125000 0.000000 +vt 0.718750 0.125000 0.000000 +vt 0.750000 0.125000 0.000000 +vt 0.781250 0.125000 0.000000 +vt 0.812500 0.125000 0.000000 +vt 0.843750 0.125000 0.000000 +vt 0.875000 0.125000 0.000000 +vt 0.906250 0.125000 0.000000 +vt 0.937500 0.125000 0.000000 +vt 0.968750 0.125000 0.000000 +vt 1.000000 0.125000 0.000000 +vt 0.000000 0.062500 0.000000 +vt 0.031250 0.062500 0.000000 +vt 0.062500 0.062500 0.000000 +vt 0.093750 0.062500 0.000000 +vt 0.125000 0.062500 0.000000 +vt 0.156250 0.062500 0.000000 +vt 0.187500 0.062500 0.000000 +vt 0.218750 0.062500 0.000000 +vt 0.250000 0.062500 0.000000 +vt 0.281250 0.062500 0.000000 +vt 0.312500 0.062500 0.000000 +vt 0.343750 0.062500 0.000000 +vt 0.375000 0.062500 0.000000 +vt 0.406250 0.062500 0.000000 +vt 0.437500 0.062500 0.000000 +vt 0.468750 0.062500 0.000000 +vt 0.500000 0.062500 0.000000 +vt 0.531250 0.062500 0.000000 +vt 0.562500 0.062500 0.000000 +vt 0.593750 0.062500 0.000000 +vt 0.625000 0.062500 0.000000 +vt 0.656250 0.062500 0.000000 +vt 0.687500 0.062500 0.000000 +vt 0.718750 0.062500 0.000000 +vt 0.750000 0.062500 0.000000 +vt 0.781250 0.062500 0.000000 +vt 0.812500 0.062500 0.000000 +vt 0.843750 0.062500 0.000000 +vt 0.875000 0.062500 0.000000 +vt 0.906250 0.062500 0.000000 +vt 0.937500 0.062500 0.000000 +vt 0.968750 0.062500 0.000000 +vt 1.000000 0.062500 0.000000 +vt 0.000000 -0.000000 0.000000 +vt 0.031250 -0.000000 0.000000 +vt 0.062500 -0.000000 0.000000 +vt 0.093750 -0.000000 0.000000 +vt 0.125000 -0.000000 0.000000 +vt 0.156250 -0.000000 0.000000 +vt 0.187500 -0.000000 0.000000 +vt 0.218750 -0.000000 0.000000 +vt 0.250000 -0.000000 0.000000 +vt 0.281250 -0.000000 0.000000 +vt 0.312500 -0.000000 0.000000 +vt 0.343750 -0.000000 0.000000 +vt 0.375000 -0.000000 0.000000 +vt 0.406250 -0.000000 0.000000 +vt 0.437500 -0.000000 0.000000 +vt 0.468750 -0.000000 0.000000 +vt 0.500000 -0.000000 0.000000 +vt 0.531250 -0.000000 0.000000 +vt 0.562500 -0.000000 0.000000 +vt 0.593750 -0.000000 0.000000 +vt 0.625000 -0.000000 0.000000 +vt 0.656250 -0.000000 0.000000 +vt 0.687500 -0.000000 0.000000 +vt 0.718750 -0.000000 0.000000 +vt 0.750000 -0.000000 0.000000 +vt 0.781250 -0.000000 0.000000 +vt 0.812500 -0.000000 0.000000 +vt 0.843750 -0.000000 0.000000 +vt 0.875000 -0.000000 0.000000 +vt 0.906250 -0.000000 0.000000 +vt 0.937500 -0.000000 0.000000 +vt 0.968750 -0.000000 0.000000 +vt 0.750000 0.000000 1.000000 +vt 0.791667 0.000000 1.000000 +vt 0.833333 0.000000 1.000000 +vt 0.875000 0.000000 1.000000 +vt 0.916667 0.000000 1.000000 +vt 0.958333 0.000000 1.000000 +vt 1.000000 0.000000 1.000000 +vt 0.041667 0.000000 1.000000 +vt 0.083333 0.000000 1.000000 +vt 0.125000 0.000000 1.000000 +vt 0.166667 0.000000 1.000000 +vt 0.208333 0.000000 1.000000 +vt 0.250000 0.000000 1.000000 +vt 0.291667 0.000000 1.000000 +vt 0.333333 0.000000 1.000000 +vt 0.375000 0.000000 1.000000 +vt 0.416667 0.000000 1.000000 +vt 0.458333 0.000000 1.000000 +vt 0.500000 0.000000 1.000000 +vt 0.541667 0.000000 1.000000 +vt 0.583333 0.000000 1.000000 +vt 0.625000 0.000000 1.000000 +vt 0.666667 0.000000 1.000000 +vt 0.708333 0.000000 1.000000 +vt 0.750000 0.200000 0.800000 +vt 0.791667 0.200000 0.800000 +vt 0.833333 0.200000 0.800000 +vt 0.875000 0.200000 0.800000 +vt 0.916667 0.200000 0.800000 +vt 0.958333 0.200000 0.800000 +vt 1.000000 0.200000 0.800000 +vt 0.041667 0.200000 0.800000 +vt 0.083333 0.200000 0.800000 +vt 0.125000 0.200000 0.800000 +vt 0.166667 0.200000 0.800000 +vt 0.208333 0.200000 0.800000 +vt 0.250000 0.200000 0.800000 +vt 0.291667 0.200000 0.800000 +vt 0.333333 0.200000 0.800000 +vt 0.375000 0.200000 0.800000 +vt 0.416667 0.200000 0.800000 +vt 0.458333 0.200000 0.800000 +vt 0.500000 0.200000 0.800000 +vt 0.541667 0.200000 0.800000 +vt 0.583333 0.200000 0.800000 +vt 0.625000 0.200000 0.800000 +vt 0.666667 0.200000 0.800000 +vt 0.708333 0.200000 0.800000 +vt 0.750000 0.400000 0.600000 +vt 0.791667 0.400000 0.600000 +vt 0.833333 0.400000 0.600000 +vt 0.875000 0.400000 0.600000 +vt 0.916667 0.400000 0.600000 +vt 0.958333 0.400000 0.600000 +vt 1.000000 0.400000 0.600000 +vt 0.041667 0.400000 0.600000 +vt 0.083333 0.400000 0.600000 +vt 0.125000 0.400000 0.600000 +vt 0.166667 0.400000 0.600000 +vt 0.208333 0.400000 0.600000 +vt 0.250000 0.400000 0.600000 +vt 0.291667 0.400000 0.600000 +vt 0.333333 0.400000 0.600000 +vt 0.375000 0.400000 0.600000 +vt 0.416667 0.400000 0.600000 +vt 0.458333 0.400000 0.600000 +vt 0.500000 0.400000 0.600000 +vt 0.541667 0.400000 0.600000 +vt 0.583333 0.400000 0.600000 +vt 0.625000 0.400000 0.600000 +vt 0.666667 0.400000 0.600000 +vt 0.708333 0.400000 0.600000 +vt 0.750000 0.600000 0.400000 +vt 0.791667 0.600000 0.400000 +vt 0.833333 0.600000 0.400000 +vt 0.875000 0.600000 0.400000 +vt 0.916667 0.600000 0.400000 +vt 0.958333 0.600000 0.400000 +vt 1.000000 0.600000 0.400000 +vt 0.041667 0.600000 0.400000 +vt 0.083333 0.600000 0.400000 +vt 0.125000 0.600000 0.400000 +vt 0.166667 0.600000 0.400000 +vt 0.208333 0.600000 0.400000 +vt 0.250000 0.600000 0.400000 +vt 0.291667 0.600000 0.400000 +vt 0.333333 0.600000 0.400000 +vt 0.375000 0.600000 0.400000 +vt 0.416667 0.600000 0.400000 +vt 0.458333 0.600000 0.400000 +vt 0.500000 0.600000 0.400000 +vt 0.541667 0.600000 0.400000 +vt 0.583333 0.600000 0.400000 +vt 0.625000 0.600000 0.400000 +vt 0.666667 0.600000 0.400000 +vt 0.708333 0.600000 0.400000 +vt 0.750000 0.800000 0.200000 +vt 0.791667 0.800000 0.200000 +vt 0.833333 0.800000 0.200000 +vt 0.875000 0.800000 0.200000 +vt 0.916667 0.800000 0.200000 +vt 0.958333 0.800000 0.200000 +vt 1.000000 0.800000 0.200000 +vt 0.041667 0.800000 0.200000 +vt 0.083333 0.800000 0.200000 +vt 0.125000 0.800000 0.200000 +vt 0.166667 0.800000 0.200000 +vt 0.208333 0.800000 0.200000 +vt 0.250000 0.800000 0.200000 +vt 0.291667 0.800000 0.200000 +vt 0.333333 0.800000 0.200000 +vt 0.375000 0.800000 0.200000 +vt 0.416667 0.800000 0.200000 +vt 0.458333 0.800000 0.200000 +vt 0.500000 0.800000 0.200000 +vt 0.541667 0.800000 0.200000 +vt 0.583333 0.800000 0.200000 +vt 0.625000 0.800000 0.200000 +vt 0.666667 0.800000 0.200000 +vt 0.708333 0.800000 0.200000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 0.500000 1.000000 0.000000 +vt 1.041667 0.000000 1.000000 +vt 1.041667 0.200000 0.800000 +vt 1.041667 0.400000 0.600000 +vt 1.041667 0.600000 0.400000 +vt 1.041667 0.800000 0.200000 +vt 1.500000 1.000000 0.000000 +vt 1.500000 1.000000 0.000000 +vt 2.000000 0.800000 0.200000 +vt 0.629410 0.982963 -0.250000 +vt 0.750000 0.933013 -0.250000 +vt 0.853554 0.853553 -0.250000 +vt 0.933013 0.750000 -0.250000 +vt 0.982963 0.629409 -0.250000 +vt 1.000000 0.500000 -0.250000 +vt 0.982963 0.370590 -0.250000 +vt 0.933013 0.250000 -0.250000 +vt 0.853553 0.146446 -0.250000 +vt 0.750000 0.066987 -0.250000 +vt 0.629409 0.017037 -0.250000 +vt 0.500000 0.000000 -0.250000 +vt 0.370590 0.017037 -0.250000 +vt 0.250000 0.066987 -0.250000 +vt 0.146447 0.146447 -0.250000 +vt 0.066987 0.250000 -0.250000 +vt 0.017037 0.370591 -0.250000 +vt 0.000000 0.500000 -0.250000 +vt 0.017037 0.629410 -0.250000 +vt 0.066987 0.750000 -0.250000 +vt 0.146447 0.853553 -0.250000 +vt 0.250000 0.933013 -0.250000 +vt 0.370590 0.982963 -0.250000 +vt 0.500000 1.000000 -0.250000 +# 759 texture coords + +g Box001 +f 1/1/1 3/3/2 4/4/3 +f 4/4/4 2/2/5 1/1/6 +f 5/5/7 6/6/8 8/8/9 +f 8/8/10 7/7/11 5/5/12 +f 1/9/13 2/10/14 6/12/15 +f 6/12/16 5/11/17 1/9/18 +f 2/13/19 4/14/20 8/16/21 +f 8/16/22 6/15/23 2/13/24 +f 4/17/25 3/18/26 7/20/27 +f 7/20/28 8/19/29 4/17/30 +f 3/21/31 1/22/32 5/24/33 +f 5/24/34 7/23/35 3/21/36 +f 9/25/37 10/57/38 11/58/39 +f 9/26/40 11/58/41 12/59/42 +f 9/27/43 12/59/44 13/60/45 +f 9/28/46 13/60/47 14/61/48 +f 9/29/49 14/61/50 15/62/51 +f 9/30/52 15/62/53 16/63/54 +f 9/31/55 16/63/56 17/64/57 +f 9/32/58 17/64/59 18/65/60 +f 9/33/61 18/65/62 19/66/63 +f 9/34/64 19/66/65 20/67/66 +f 9/35/67 20/67/68 21/68/69 +f 9/36/70 21/68/71 22/69/72 +f 9/37/73 22/69/74 23/70/75 +f 9/38/76 23/70/77 24/71/78 +f 9/39/79 24/71/80 25/72/81 +f 9/40/82 25/72/83 26/73/84 +f 9/41/85 26/73/86 27/74/87 +f 9/42/88 27/74/89 28/75/90 +f 9/43/91 28/75/92 29/76/93 +f 9/44/94 29/76/95 30/77/96 +f 9/45/97 30/77/98 31/78/99 +f 9/46/100 31/78/101 32/79/102 +f 9/47/103 32/79/104 33/80/105 +f 9/48/106 33/80/107 34/81/108 +f 9/49/109 34/81/110 35/82/111 +f 9/50/112 35/82/113 36/83/114 +f 9/51/115 36/83/116 37/84/117 +f 9/52/118 37/84/119 38/85/120 +f 9/53/121 38/85/122 39/86/123 +f 9/54/124 39/86/125 40/87/126 +f 9/55/127 40/87/128 41/88/129 +f 9/56/130 41/88/131 10/89/132 +f 43/91/133 11/58/134 10/57/135 +f 10/57/136 42/90/137 43/91/138 +f 44/92/139 12/59/140 11/58/141 +f 11/58/142 43/91/143 44/92/144 +f 45/93/145 13/60/146 12/59/147 +f 12/59/148 44/92/149 45/93/150 +f 46/94/151 14/61/152 13/60/153 +f 13/60/154 45/93/155 46/94/156 +f 47/95/157 15/62/158 14/61/159 +f 14/61/160 46/94/161 47/95/162 +f 48/96/163 16/63/164 15/62/165 +f 15/62/166 47/95/167 48/96/168 +f 49/97/169 17/64/170 16/63/171 +f 16/63/172 48/96/173 49/97/174 +f 50/98/175 18/65/176 17/64/177 +f 17/64/178 49/97/179 50/98/180 +f 51/99/181 19/66/182 18/65/183 +f 18/65/184 50/98/185 51/99/186 +f 52/100/187 20/67/188 19/66/189 +f 19/66/190 51/99/191 52/100/192 +f 53/101/193 21/68/194 20/67/195 +f 20/67/196 52/100/197 53/101/198 +f 54/102/199 22/69/200 21/68/201 +f 21/68/202 53/101/203 54/102/204 +f 55/103/205 23/70/206 22/69/207 +f 22/69/208 54/102/209 55/103/210 +f 56/104/211 24/71/212 23/70/213 +f 23/70/214 55/103/215 56/104/216 +f 57/105/217 25/72/218 24/71/219 +f 24/71/220 56/104/221 57/105/222 +f 58/106/223 26/73/224 25/72/225 +f 25/72/226 57/105/227 58/106/228 +f 59/107/229 27/74/230 26/73/231 +f 26/73/232 58/106/233 59/107/234 +f 60/108/235 28/75/236 27/74/237 +f 27/74/238 59/107/239 60/108/240 +f 61/109/241 29/76/242 28/75/243 +f 28/75/244 60/108/245 61/109/246 +f 62/110/247 30/77/248 29/76/249 +f 29/76/250 61/109/251 62/110/252 +f 63/111/253 31/78/254 30/77/255 +f 30/77/256 62/110/257 63/111/258 +f 64/112/259 32/79/260 31/78/261 +f 31/78/262 63/111/263 64/112/264 +f 65/113/265 33/80/266 32/79/267 +f 32/79/268 64/112/269 65/113/270 +f 66/114/271 34/81/272 33/80/273 +f 33/80/274 65/113/275 66/114/276 +f 67/115/277 35/82/278 34/81/279 +f 34/81/280 66/114/281 67/115/282 +f 68/116/283 36/83/284 35/82/285 +f 35/82/286 67/115/287 68/116/288 +f 69/117/289 37/84/290 36/83/291 +f 36/83/292 68/116/293 69/117/294 +f 70/118/295 38/85/296 37/84/297 +f 37/84/298 69/117/299 70/118/300 +f 71/119/301 39/86/302 38/85/303 +f 38/85/304 70/118/305 71/119/306 +f 72/120/307 40/87/308 39/86/309 +f 39/86/310 71/119/311 72/120/312 +f 73/121/313 41/88/314 40/87/315 +f 40/87/316 72/120/317 73/121/318 +f 42/122/319 10/89/320 41/88/321 +f 41/88/322 73/121/323 42/122/324 +f 75/124/325 43/91/326 42/90/327 +f 42/90/328 74/123/329 75/124/330 +f 76/125/331 44/92/332 43/91/333 +f 43/91/334 75/124/335 76/125/336 +f 77/126/337 45/93/338 44/92/339 +f 44/92/340 76/125/341 77/126/342 +f 78/127/343 46/94/344 45/93/345 +f 45/93/346 77/126/347 78/127/348 +f 79/128/349 47/95/350 46/94/351 +f 46/94/352 78/127/353 79/128/354 +f 80/129/355 48/96/356 47/95/357 +f 47/95/358 79/128/359 80/129/360 +f 81/130/361 49/97/362 48/96/363 +f 48/96/364 80/129/365 81/130/366 +f 82/131/367 50/98/368 49/97/369 +f 49/97/370 81/130/371 82/131/372 +f 83/132/373 51/99/374 50/98/375 +f 50/98/376 82/131/377 83/132/378 +f 84/133/379 52/100/380 51/99/381 +f 51/99/382 83/132/383 84/133/384 +f 85/134/385 53/101/386 52/100/387 +f 52/100/388 84/133/389 85/134/390 +f 86/135/391 54/102/392 53/101/393 +f 53/101/394 85/134/395 86/135/396 +f 87/136/397 55/103/398 54/102/399 +f 54/102/400 86/135/401 87/136/402 +f 88/137/403 56/104/404 55/103/405 +f 55/103/406 87/136/407 88/137/408 +f 89/138/409 57/105/410 56/104/411 +f 56/104/412 88/137/413 89/138/414 +f 90/139/415 58/106/416 57/105/417 +f 57/105/418 89/138/419 90/139/420 +f 91/140/421 59/107/422 58/106/423 +f 58/106/424 90/139/425 91/140/426 +f 92/141/427 60/108/428 59/107/429 +f 59/107/430 91/140/431 92/141/432 +f 93/142/433 61/109/434 60/108/435 +f 60/108/436 92/141/437 93/142/438 +f 94/143/439 62/110/440 61/109/441 +f 61/109/442 93/142/443 94/143/444 +f 95/144/445 63/111/446 62/110/447 +f 62/110/448 94/143/449 95/144/450 +f 96/145/451 64/112/452 63/111/453 +f 63/111/454 95/144/455 96/145/456 +f 97/146/457 65/113/458 64/112/459 +f 64/112/460 96/145/461 97/146/462 +f 98/147/463 66/114/464 65/113/465 +f 65/113/466 97/146/467 98/147/468 +f 99/148/469 67/115/470 66/114/471 +f 66/114/472 98/147/473 99/148/474 +f 100/149/475 68/116/476 67/115/477 +f 67/115/478 99/148/479 100/149/480 +f 101/150/481 69/117/482 68/116/483 +f 68/116/484 100/149/485 101/150/486 +f 102/151/487 70/118/488 69/117/489 +f 69/117/490 101/150/491 102/151/492 +f 103/152/493 71/119/494 70/118/495 +f 70/118/496 102/151/497 103/152/498 +f 104/153/499 72/120/500 71/119/501 +f 71/119/502 103/152/503 104/153/504 +f 105/154/505 73/121/506 72/120/507 +f 72/120/508 104/153/509 105/154/510 +f 74/155/511 42/122/512 73/121/513 +f 73/121/514 105/154/515 74/155/516 +f 107/157/517 75/124/518 74/123/519 +f 74/123/520 106/156/521 107/157/522 +f 108/158/523 76/125/524 75/124/525 +f 75/124/526 107/157/527 108/158/528 +f 109/159/529 77/126/530 76/125/531 +f 76/125/532 108/158/533 109/159/534 +f 110/160/535 78/127/536 77/126/537 +f 77/126/538 109/159/539 110/160/540 +f 111/161/541 79/128/542 78/127/543 +f 78/127/544 110/160/545 111/161/546 +f 112/162/547 80/129/548 79/128/549 +f 79/128/550 111/161/551 112/162/552 +f 113/163/553 81/130/554 80/129/555 +f 80/129/556 112/162/557 113/163/558 +f 114/164/559 82/131/560 81/130/561 +f 81/130/562 113/163/563 114/164/564 +f 115/165/565 83/132/566 82/131/567 +f 82/131/568 114/164/569 115/165/570 +f 116/166/571 84/133/572 83/132/573 +f 83/132/574 115/165/575 116/166/576 +f 117/167/577 85/134/578 84/133/579 +f 84/133/580 116/166/581 117/167/582 +f 118/168/583 86/135/584 85/134/585 +f 85/134/586 117/167/587 118/168/588 +f 119/169/589 87/136/590 86/135/591 +f 86/135/592 118/168/593 119/169/594 +f 120/170/595 88/137/596 87/136/597 +f 87/136/598 119/169/599 120/170/600 +f 121/171/601 89/138/602 88/137/603 +f 88/137/604 120/170/605 121/171/606 +f 122/172/607 90/139/608 89/138/609 +f 89/138/610 121/171/611 122/172/612 +f 123/173/613 91/140/614 90/139/615 +f 90/139/616 122/172/617 123/173/618 +f 124/174/619 92/141/620 91/140/621 +f 91/140/622 123/173/623 124/174/624 +f 125/175/625 93/142/626 92/141/627 +f 92/141/628 124/174/629 125/175/630 +f 126/176/631 94/143/632 93/142/633 +f 93/142/634 125/175/635 126/176/636 +f 127/177/637 95/144/638 94/143/639 +f 94/143/640 126/176/641 127/177/642 +f 128/178/643 96/145/644 95/144/645 +f 95/144/646 127/177/647 128/178/648 +f 129/179/649 97/146/650 96/145/651 +f 96/145/652 128/178/653 129/179/654 +f 130/180/655 98/147/656 97/146/657 +f 97/146/658 129/179/659 130/180/660 +f 131/181/661 99/148/662 98/147/663 +f 98/147/664 130/180/665 131/181/666 +f 132/182/667 100/149/668 99/148/669 +f 99/148/670 131/181/671 132/182/672 +f 133/183/673 101/150/674 100/149/675 +f 100/149/676 132/182/677 133/183/678 +f 134/184/679 102/151/680 101/150/681 +f 101/150/682 133/183/683 134/184/684 +f 135/185/685 103/152/686 102/151/687 +f 102/151/688 134/184/689 135/185/690 +f 136/186/691 104/153/692 103/152/693 +f 103/152/694 135/185/695 136/186/696 +f 137/187/697 105/154/698 104/153/699 +f 104/153/700 136/186/701 137/187/702 +f 106/188/703 74/155/704 105/154/705 +f 105/154/706 137/187/707 106/188/708 +f 139/190/709 107/157/710 106/156/711 +f 106/156/712 138/189/713 139/190/714 +f 140/191/715 108/158/716 107/157/717 +f 107/157/718 139/190/719 140/191/720 +f 141/192/721 109/159/722 108/158/723 +f 108/158/724 140/191/725 141/192/726 +f 142/193/727 110/160/728 109/159/729 +f 109/159/730 141/192/731 142/193/732 +f 143/194/733 111/161/734 110/160/735 +f 110/160/736 142/193/737 143/194/738 +f 144/195/739 112/162/740 111/161/741 +f 111/161/742 143/194/743 144/195/744 +f 145/196/745 113/163/746 112/162/747 +f 112/162/748 144/195/749 145/196/750 +f 146/197/751 114/164/752 113/163/753 +f 113/163/754 145/196/755 146/197/756 +f 147/198/757 115/165/758 114/164/759 +f 114/164/760 146/197/761 147/198/762 +f 148/199/763 116/166/764 115/165/765 +f 115/165/766 147/198/767 148/199/768 +f 149/200/769 117/167/770 116/166/771 +f 116/166/772 148/199/773 149/200/774 +f 150/201/775 118/168/776 117/167/777 +f 117/167/778 149/200/779 150/201/780 +f 151/202/781 119/169/782 118/168/783 +f 118/168/784 150/201/785 151/202/786 +f 152/203/787 120/170/788 119/169/789 +f 119/169/790 151/202/791 152/203/792 +f 153/204/793 121/171/794 120/170/795 +f 120/170/796 152/203/797 153/204/798 +f 154/205/799 122/172/800 121/171/801 +f 121/171/802 153/204/803 154/205/804 +f 155/206/805 123/173/806 122/172/807 +f 122/172/808 154/205/809 155/206/810 +f 156/207/811 124/174/812 123/173/813 +f 123/173/814 155/206/815 156/207/816 +f 157/208/817 125/175/818 124/174/819 +f 124/174/820 156/207/821 157/208/822 +f 158/209/823 126/176/824 125/175/825 +f 125/175/826 157/208/827 158/209/828 +f 159/210/829 127/177/830 126/176/831 +f 126/176/832 158/209/833 159/210/834 +f 160/211/835 128/178/836 127/177/837 +f 127/177/838 159/210/839 160/211/840 +f 161/212/841 129/179/842 128/178/843 +f 128/178/844 160/211/845 161/212/846 +f 162/213/847 130/180/848 129/179/849 +f 129/179/850 161/212/851 162/213/852 +f 163/214/853 131/181/854 130/180/855 +f 130/180/856 162/213/857 163/214/858 +f 164/215/859 132/182/860 131/181/861 +f 131/181/862 163/214/863 164/215/864 +f 165/216/865 133/183/866 132/182/867 +f 132/182/868 164/215/869 165/216/870 +f 166/217/871 134/184/872 133/183/873 +f 133/183/874 165/216/875 166/217/876 +f 167/218/877 135/185/878 134/184/879 +f 134/184/880 166/217/881 167/218/882 +f 168/219/883 136/186/884 135/185/885 +f 135/185/886 167/218/887 168/219/888 +f 169/220/889 137/187/890 136/186/891 +f 136/186/892 168/219/893 169/220/894 +f 138/221/895 106/188/896 137/187/897 +f 137/187/898 169/220/899 138/221/900 +f 171/223/901 139/190/902 138/189/903 +f 138/189/904 170/222/905 171/223/906 +f 172/224/907 140/191/908 139/190/909 +f 139/190/910 171/223/911 172/224/912 +f 173/225/913 141/192/914 140/191/915 +f 140/191/916 172/224/917 173/225/918 +f 174/226/919 142/193/920 141/192/921 +f 141/192/922 173/225/923 174/226/924 +f 175/227/925 143/194/926 142/193/927 +f 142/193/928 174/226/929 175/227/930 +f 176/228/931 144/195/932 143/194/933 +f 143/194/934 175/227/935 176/228/936 +f 177/229/937 145/196/938 144/195/939 +f 144/195/940 176/228/941 177/229/942 +f 178/230/943 146/197/944 145/196/945 +f 145/196/946 177/229/947 178/230/948 +f 179/231/949 147/198/950 146/197/951 +f 146/197/952 178/230/953 179/231/954 +f 180/232/955 148/199/956 147/198/957 +f 147/198/958 179/231/959 180/232/960 +f 181/233/961 149/200/962 148/199/963 +f 148/199/964 180/232/965 181/233/966 +f 182/234/967 150/201/968 149/200/969 +f 149/200/970 181/233/971 182/234/972 +f 183/235/973 151/202/974 150/201/975 +f 150/201/976 182/234/977 183/235/978 +f 184/236/979 152/203/980 151/202/981 +f 151/202/982 183/235/983 184/236/984 +f 185/237/985 153/204/986 152/203/987 +f 152/203/988 184/236/989 185/237/990 +f 186/238/991 154/205/992 153/204/993 +f 153/204/994 185/237/995 186/238/996 +f 187/239/997 155/206/998 154/205/999 +f 154/205/1000 186/238/1001 187/239/1002 +f 188/240/1003 156/207/1004 155/206/1005 +f 155/206/1006 187/239/1007 188/240/1008 +f 189/241/1009 157/208/1010 156/207/1011 +f 156/207/1012 188/240/1013 189/241/1014 +f 190/242/1015 158/209/1016 157/208/1017 +f 157/208/1018 189/241/1019 190/242/1020 +f 191/243/1021 159/210/1022 158/209/1023 +f 158/209/1024 190/242/1025 191/243/1026 +f 192/244/1027 160/211/1028 159/210/1029 +f 159/210/1030 191/243/1031 192/244/1032 +f 193/245/1033 161/212/1034 160/211/1035 +f 160/211/1036 192/244/1037 193/245/1038 +f 194/246/1039 162/213/1040 161/212/1041 +f 161/212/1042 193/245/1043 194/246/1044 +f 195/247/1045 163/214/1046 162/213/1047 +f 162/213/1048 194/246/1049 195/247/1050 +f 196/248/1051 164/215/1052 163/214/1053 +f 163/214/1054 195/247/1055 196/248/1056 +f 197/249/1057 165/216/1058 164/215/1059 +f 164/215/1060 196/248/1061 197/249/1062 +f 198/250/1063 166/217/1064 165/216/1065 +f 165/216/1066 197/249/1067 198/250/1068 +f 199/251/1069 167/218/1070 166/217/1071 +f 166/217/1072 198/250/1073 199/251/1074 +f 200/252/1075 168/219/1076 167/218/1077 +f 167/218/1078 199/251/1079 200/252/1080 +f 201/253/1081 169/220/1082 168/219/1083 +f 168/219/1084 200/252/1085 201/253/1086 +f 170/254/1087 138/221/1088 169/220/1089 +f 169/220/1090 201/253/1091 170/254/1092 +f 203/256/1093 171/223/1094 170/222/1095 +f 170/222/1096 202/255/1097 203/256/1098 +f 204/257/1099 172/224/1100 171/223/1101 +f 171/223/1102 203/256/1103 204/257/1104 +f 205/258/1105 173/225/1106 172/224/1107 +f 172/224/1108 204/257/1109 205/258/1110 +f 206/259/1111 174/226/1112 173/225/1113 +f 173/225/1114 205/258/1115 206/259/1116 +f 207/260/1117 175/227/1118 174/226/1119 +f 174/226/1120 206/259/1121 207/260/1122 +f 208/261/1123 176/228/1124 175/227/1125 +f 175/227/1126 207/260/1127 208/261/1128 +f 209/262/1129 177/229/1130 176/228/1131 +f 176/228/1132 208/261/1133 209/262/1134 +f 210/263/1135 178/230/1136 177/229/1137 +f 177/229/1138 209/262/1139 210/263/1140 +f 211/264/1141 179/231/1142 178/230/1143 +f 178/230/1144 210/263/1145 211/264/1146 +f 212/265/1147 180/232/1148 179/231/1149 +f 179/231/1150 211/264/1151 212/265/1152 +f 213/266/1153 181/233/1154 180/232/1155 +f 180/232/1156 212/265/1157 213/266/1158 +f 214/267/1159 182/234/1160 181/233/1161 +f 181/233/1162 213/266/1163 214/267/1164 +f 215/268/1165 183/235/1166 182/234/1167 +f 182/234/1168 214/267/1169 215/268/1170 +f 216/269/1171 184/236/1172 183/235/1173 +f 183/235/1174 215/268/1175 216/269/1176 +f 217/270/1177 185/237/1178 184/236/1179 +f 184/236/1180 216/269/1181 217/270/1182 +f 218/271/1183 186/238/1184 185/237/1185 +f 185/237/1186 217/270/1187 218/271/1188 +f 219/272/1189 187/239/1190 186/238/1191 +f 186/238/1192 218/271/1193 219/272/1194 +f 220/273/1195 188/240/1196 187/239/1197 +f 187/239/1198 219/272/1199 220/273/1200 +f 221/274/1201 189/241/1202 188/240/1203 +f 188/240/1204 220/273/1205 221/274/1206 +f 222/275/1207 190/242/1208 189/241/1209 +f 189/241/1210 221/274/1211 222/275/1212 +f 223/276/1213 191/243/1214 190/242/1215 +f 190/242/1216 222/275/1217 223/276/1218 +f 224/277/1219 192/244/1220 191/243/1221 +f 191/243/1222 223/276/1223 224/277/1224 +f 225/278/1225 193/245/1226 192/244/1227 +f 192/244/1228 224/277/1229 225/278/1230 +f 226/279/1231 194/246/1232 193/245/1233 +f 193/245/1234 225/278/1235 226/279/1236 +f 227/280/1237 195/247/1238 194/246/1239 +f 194/246/1240 226/279/1241 227/280/1242 +f 228/281/1243 196/248/1244 195/247/1245 +f 195/247/1246 227/280/1247 228/281/1248 +f 229/282/1249 197/249/1250 196/248/1251 +f 196/248/1252 228/281/1253 229/282/1254 +f 230/283/1255 198/250/1256 197/249/1257 +f 197/249/1258 229/282/1259 230/283/1260 +f 231/284/1261 199/251/1262 198/250/1263 +f 198/250/1264 230/283/1265 231/284/1266 +f 232/285/1267 200/252/1268 199/251/1269 +f 199/251/1270 231/284/1271 232/285/1272 +f 233/286/1273 201/253/1274 200/252/1275 +f 200/252/1276 232/285/1277 233/286/1278 +f 202/287/1279 170/254/1280 201/253/1281 +f 201/253/1282 233/286/1283 202/287/1284 +f 235/289/1285 203/256/1286 202/255/1287 +f 202/255/1288 234/288/1289 235/289/1290 +f 236/290/1291 204/257/1292 203/256/1293 +f 203/256/1294 235/289/1295 236/290/1296 +f 237/291/1297 205/258/1298 204/257/1299 +f 204/257/1300 236/290/1301 237/291/1302 +f 238/292/1303 206/259/1304 205/258/1305 +f 205/258/1306 237/291/1307 238/292/1308 +f 239/293/1309 207/260/1310 206/259/1311 +f 206/259/1312 238/292/1313 239/293/1314 +f 240/294/1315 208/261/1316 207/260/1317 +f 207/260/1318 239/293/1319 240/294/1320 +f 241/295/1321 209/262/1322 208/261/1323 +f 208/261/1324 240/294/1325 241/295/1326 +f 242/296/1327 210/263/1328 209/262/1329 +f 209/262/1330 241/295/1331 242/296/1332 +f 243/297/1333 211/264/1334 210/263/1335 +f 210/263/1336 242/296/1337 243/297/1338 +f 244/298/1339 212/265/1340 211/264/1341 +f 211/264/1342 243/297/1343 244/298/1344 +f 245/299/1345 213/266/1346 212/265/1347 +f 212/265/1348 244/298/1349 245/299/1350 +f 246/300/1351 214/267/1352 213/266/1353 +f 213/266/1354 245/299/1355 246/300/1356 +f 247/301/1357 215/268/1358 214/267/1359 +f 214/267/1360 246/300/1361 247/301/1362 +f 248/302/1363 216/269/1364 215/268/1365 +f 215/268/1366 247/301/1367 248/302/1368 +f 249/303/1369 217/270/1370 216/269/1371 +f 216/269/1372 248/302/1373 249/303/1374 +f 250/304/1375 218/271/1376 217/270/1377 +f 217/270/1378 249/303/1379 250/304/1380 +f 251/305/1381 219/272/1382 218/271/1383 +f 218/271/1384 250/304/1385 251/305/1386 +f 252/306/1387 220/273/1388 219/272/1389 +f 219/272/1390 251/305/1391 252/306/1392 +f 253/307/1393 221/274/1394 220/273/1395 +f 220/273/1396 252/306/1397 253/307/1398 +f 254/308/1399 222/275/1400 221/274/1401 +f 221/274/1402 253/307/1403 254/308/1404 +f 255/309/1405 223/276/1406 222/275/1407 +f 222/275/1408 254/308/1409 255/309/1410 +f 256/310/1411 224/277/1412 223/276/1413 +f 223/276/1414 255/309/1415 256/310/1416 +f 257/311/1417 225/278/1418 224/277/1419 +f 224/277/1420 256/310/1421 257/311/1422 +f 258/312/1423 226/279/1424 225/278/1425 +f 225/278/1426 257/311/1427 258/312/1428 +f 259/313/1429 227/280/1430 226/279/1431 +f 226/279/1432 258/312/1433 259/313/1434 +f 260/314/1435 228/281/1436 227/280/1437 +f 227/280/1438 259/313/1439 260/314/1440 +f 261/315/1441 229/282/1442 228/281/1443 +f 228/281/1444 260/314/1445 261/315/1446 +f 262/316/1447 230/283/1448 229/282/1449 +f 229/282/1450 261/315/1451 262/316/1452 +f 263/317/1453 231/284/1454 230/283/1455 +f 230/283/1456 262/316/1457 263/317/1458 +f 264/318/1459 232/285/1460 231/284/1461 +f 231/284/1462 263/317/1463 264/318/1464 +f 265/319/1465 233/286/1466 232/285/1467 +f 232/285/1468 264/318/1469 265/319/1470 +f 234/320/1471 202/287/1472 233/286/1473 +f 233/286/1474 265/319/1475 234/320/1476 +f 267/322/1477 235/289/1478 234/288/1479 +f 234/288/1480 266/321/1481 267/322/1482 +f 268/323/1483 236/290/1484 235/289/1485 +f 235/289/1486 267/322/1487 268/323/1488 +f 269/324/1489 237/291/1490 236/290/1491 +f 236/290/1492 268/323/1493 269/324/1494 +f 270/325/1495 238/292/1496 237/291/1497 +f 237/291/1498 269/324/1499 270/325/1500 +f 271/326/1501 239/293/1502 238/292/1503 +f 238/292/1504 270/325/1505 271/326/1506 +f 272/327/1507 240/294/1508 239/293/1509 +f 239/293/1510 271/326/1511 272/327/1512 +f 273/328/1513 241/295/1514 240/294/1515 +f 240/294/1516 272/327/1517 273/328/1518 +f 274/329/1519 242/296/1520 241/295/1521 +f 241/295/1522 273/328/1523 274/329/1524 +f 275/330/1525 243/297/1526 242/296/1527 +f 242/296/1528 274/329/1529 275/330/1530 +f 276/331/1531 244/298/1532 243/297/1533 +f 243/297/1534 275/330/1535 276/331/1536 +f 277/332/1537 245/299/1538 244/298/1539 +f 244/298/1540 276/331/1541 277/332/1542 +f 278/333/1543 246/300/1544 245/299/1545 +f 245/299/1546 277/332/1547 278/333/1548 +f 279/334/1549 247/301/1550 246/300/1551 +f 246/300/1552 278/333/1553 279/334/1554 +f 280/335/1555 248/302/1556 247/301/1557 +f 247/301/1558 279/334/1559 280/335/1560 +f 281/336/1561 249/303/1562 248/302/1563 +f 248/302/1564 280/335/1565 281/336/1566 +f 282/337/1567 250/304/1568 249/303/1569 +f 249/303/1570 281/336/1571 282/337/1572 +f 283/338/1573 251/305/1574 250/304/1575 +f 250/304/1576 282/337/1577 283/338/1578 +f 284/339/1579 252/306/1580 251/305/1581 +f 251/305/1582 283/338/1583 284/339/1584 +f 285/340/1585 253/307/1586 252/306/1587 +f 252/306/1588 284/339/1589 285/340/1590 +f 286/341/1591 254/308/1592 253/307/1593 +f 253/307/1594 285/340/1595 286/341/1596 +f 287/342/1597 255/309/1598 254/308/1599 +f 254/308/1600 286/341/1601 287/342/1602 +f 288/343/1603 256/310/1604 255/309/1605 +f 255/309/1606 287/342/1607 288/343/1608 +f 289/344/1609 257/311/1610 256/310/1611 +f 256/310/1612 288/343/1613 289/344/1614 +f 290/345/1615 258/312/1616 257/311/1617 +f 257/311/1618 289/344/1619 290/345/1620 +f 291/346/1621 259/313/1622 258/312/1623 +f 258/312/1624 290/345/1625 291/346/1626 +f 292/347/1627 260/314/1628 259/313/1629 +f 259/313/1630 291/346/1631 292/347/1632 +f 293/348/1633 261/315/1634 260/314/1635 +f 260/314/1636 292/347/1637 293/348/1638 +f 294/349/1639 262/316/1640 261/315/1641 +f 261/315/1642 293/348/1643 294/349/1644 +f 295/350/1645 263/317/1646 262/316/1647 +f 262/316/1648 294/349/1649 295/350/1650 +f 296/351/1651 264/318/1652 263/317/1653 +f 263/317/1654 295/350/1655 296/351/1656 +f 297/352/1657 265/319/1658 264/318/1659 +f 264/318/1660 296/351/1661 297/352/1662 +f 266/353/1663 234/320/1664 265/319/1665 +f 265/319/1666 297/352/1667 266/353/1668 +f 299/355/1669 267/322/1670 266/321/1671 +f 266/321/1672 298/354/1673 299/355/1674 +f 300/356/1675 268/323/1676 267/322/1677 +f 267/322/1678 299/355/1679 300/356/1680 +f 301/357/1681 269/324/1682 268/323/1683 +f 268/323/1684 300/356/1685 301/357/1686 +f 302/358/1687 270/325/1688 269/324/1689 +f 269/324/1690 301/357/1691 302/358/1692 +f 303/359/1693 271/326/1694 270/325/1695 +f 270/325/1696 302/358/1697 303/359/1698 +f 304/360/1699 272/327/1700 271/326/1701 +f 271/326/1702 303/359/1703 304/360/1704 +f 305/361/1705 273/328/1706 272/327/1707 +f 272/327/1708 304/360/1709 305/361/1710 +f 306/362/1711 274/329/1712 273/328/1713 +f 273/328/1714 305/361/1715 306/362/1716 +f 307/363/1717 275/330/1718 274/329/1719 +f 274/329/1720 306/362/1721 307/363/1722 +f 308/364/1723 276/331/1724 275/330/1725 +f 275/330/1726 307/363/1727 308/364/1728 +f 309/365/1729 277/332/1730 276/331/1731 +f 276/331/1732 308/364/1733 309/365/1734 +f 310/366/1735 278/333/1736 277/332/1737 +f 277/332/1738 309/365/1739 310/366/1740 +f 311/367/1741 279/334/1742 278/333/1743 +f 278/333/1744 310/366/1745 311/367/1746 +f 312/368/1747 280/335/1748 279/334/1749 +f 279/334/1750 311/367/1751 312/368/1752 +f 313/369/1753 281/336/1754 280/335/1755 +f 280/335/1756 312/368/1757 313/369/1758 +f 314/370/1759 282/337/1760 281/336/1761 +f 281/336/1762 313/369/1763 314/370/1764 +f 315/371/1765 283/338/1766 282/337/1767 +f 282/337/1768 314/370/1769 315/371/1770 +f 316/372/1771 284/339/1772 283/338/1773 +f 283/338/1774 315/371/1775 316/372/1776 +f 317/373/1777 285/340/1778 284/339/1779 +f 284/339/1780 316/372/1781 317/373/1782 +f 318/374/1783 286/341/1784 285/340/1785 +f 285/340/1786 317/373/1787 318/374/1788 +f 319/375/1789 287/342/1790 286/341/1791 +f 286/341/1792 318/374/1793 319/375/1794 +f 320/376/1795 288/343/1796 287/342/1797 +f 287/342/1798 319/375/1799 320/376/1800 +f 321/377/1801 289/344/1802 288/343/1803 +f 288/343/1804 320/376/1805 321/377/1806 +f 322/378/1807 290/345/1808 289/344/1809 +f 289/344/1810 321/377/1811 322/378/1812 +f 323/379/1813 291/346/1814 290/345/1815 +f 290/345/1816 322/378/1817 323/379/1818 +f 324/380/1819 292/347/1820 291/346/1821 +f 291/346/1822 323/379/1823 324/380/1824 +f 325/381/1825 293/348/1826 292/347/1827 +f 292/347/1828 324/380/1829 325/381/1830 +f 326/382/1831 294/349/1832 293/348/1833 +f 293/348/1834 325/381/1835 326/382/1836 +f 327/383/1837 295/350/1838 294/349/1839 +f 294/349/1840 326/382/1841 327/383/1842 +f 328/384/1843 296/351/1844 295/350/1845 +f 295/350/1846 327/383/1847 328/384/1848 +f 329/385/1849 297/352/1850 296/351/1851 +f 296/351/1852 328/384/1853 329/385/1854 +f 298/386/1855 266/353/1856 297/352/1857 +f 297/352/1858 329/385/1859 298/386/1860 +f 331/388/1861 299/355/1862 298/354/1863 +f 298/354/1864 330/387/1865 331/388/1866 +f 332/389/1867 300/356/1868 299/355/1869 +f 299/355/1870 331/388/1871 332/389/1872 +f 333/390/1873 301/357/1874 300/356/1875 +f 300/356/1876 332/389/1877 333/390/1878 +f 334/391/1879 302/358/1880 301/357/1881 +f 301/357/1882 333/390/1883 334/391/1884 +f 335/392/1885 303/359/1886 302/358/1887 +f 302/358/1888 334/391/1889 335/392/1890 +f 336/393/1891 304/360/1892 303/359/1893 +f 303/359/1894 335/392/1895 336/393/1896 +f 337/394/1897 305/361/1898 304/360/1899 +f 304/360/1900 336/393/1901 337/394/1902 +f 338/395/1903 306/362/1904 305/361/1905 +f 305/361/1906 337/394/1907 338/395/1908 +f 339/396/1909 307/363/1910 306/362/1911 +f 306/362/1912 338/395/1913 339/396/1914 +f 340/397/1915 308/364/1916 307/363/1917 +f 307/363/1918 339/396/1919 340/397/1920 +f 341/398/1921 309/365/1922 308/364/1923 +f 308/364/1924 340/397/1925 341/398/1926 +f 342/399/1927 310/366/1928 309/365/1929 +f 309/365/1930 341/398/1931 342/399/1932 +f 343/400/1933 311/367/1934 310/366/1935 +f 310/366/1936 342/399/1937 343/400/1938 +f 344/401/1939 312/368/1940 311/367/1941 +f 311/367/1942 343/400/1943 344/401/1944 +f 345/402/1945 313/369/1946 312/368/1947 +f 312/368/1948 344/401/1949 345/402/1950 +f 346/403/1951 314/370/1952 313/369/1953 +f 313/369/1954 345/402/1955 346/403/1956 +f 347/404/1957 315/371/1958 314/370/1959 +f 314/370/1960 346/403/1961 347/404/1962 +f 348/405/1963 316/372/1964 315/371/1965 +f 315/371/1966 347/404/1967 348/405/1968 +f 349/406/1969 317/373/1970 316/372/1971 +f 316/372/1972 348/405/1973 349/406/1974 +f 350/407/1975 318/374/1976 317/373/1977 +f 317/373/1978 349/406/1979 350/407/1980 +f 351/408/1981 319/375/1982 318/374/1983 +f 318/374/1984 350/407/1985 351/408/1986 +f 352/409/1987 320/376/1988 319/375/1989 +f 319/375/1990 351/408/1991 352/409/1992 +f 353/410/1993 321/377/1994 320/376/1995 +f 320/376/1996 352/409/1997 353/410/1998 +f 354/411/1999 322/378/2000 321/377/2001 +f 321/377/2002 353/410/2003 354/411/2004 +f 355/412/2005 323/379/2006 322/378/2007 +f 322/378/2008 354/411/2009 355/412/2010 +f 356/413/2011 324/380/2012 323/379/2013 +f 323/379/2014 355/412/2015 356/413/2016 +f 357/414/2017 325/381/2018 324/380/2019 +f 324/380/2020 356/413/2021 357/414/2022 +f 358/415/2023 326/382/2024 325/381/2025 +f 325/381/2026 357/414/2027 358/415/2028 +f 359/416/2029 327/383/2030 326/382/2031 +f 326/382/2032 358/415/2033 359/416/2034 +f 360/417/2035 328/384/2036 327/383/2037 +f 327/383/2038 359/416/2039 360/417/2040 +f 361/418/2041 329/385/2042 328/384/2043 +f 328/384/2044 360/417/2045 361/418/2046 +f 330/419/2047 298/386/2048 329/385/2049 +f 329/385/2050 361/418/2051 330/419/2052 +f 363/421/2053 331/388/2054 330/387/2055 +f 330/387/2056 362/420/2057 363/421/2058 +f 364/422/2059 332/389/2060 331/388/2061 +f 331/388/2062 363/421/2063 364/422/2064 +f 365/423/2065 333/390/2066 332/389/2067 +f 332/389/2068 364/422/2069 365/423/2070 +f 366/424/2071 334/391/2072 333/390/2073 +f 333/390/2074 365/423/2075 366/424/2076 +f 367/425/2077 335/392/2078 334/391/2079 +f 334/391/2080 366/424/2081 367/425/2082 +f 368/426/2083 336/393/2084 335/392/2085 +f 335/392/2086 367/425/2087 368/426/2088 +f 369/427/2089 337/394/2090 336/393/2091 +f 336/393/2092 368/426/2093 369/427/2094 +f 370/428/2095 338/395/2096 337/394/2097 +f 337/394/2098 369/427/2099 370/428/2100 +f 371/429/2101 339/396/2102 338/395/2103 +f 338/395/2104 370/428/2105 371/429/2106 +f 372/430/2107 340/397/2108 339/396/2109 +f 339/396/2110 371/429/2111 372/430/2112 +f 373/431/2113 341/398/2114 340/397/2115 +f 340/397/2116 372/430/2117 373/431/2118 +f 374/432/2119 342/399/2120 341/398/2121 +f 341/398/2122 373/431/2123 374/432/2124 +f 375/433/2125 343/400/2126 342/399/2127 +f 342/399/2128 374/432/2129 375/433/2130 +f 376/434/2131 344/401/2132 343/400/2133 +f 343/400/2134 375/433/2135 376/434/2136 +f 377/435/2137 345/402/2138 344/401/2139 +f 344/401/2140 376/434/2141 377/435/2142 +f 378/436/2143 346/403/2144 345/402/2145 +f 345/402/2146 377/435/2147 378/436/2148 +f 379/437/2149 347/404/2150 346/403/2151 +f 346/403/2152 378/436/2153 379/437/2154 +f 380/438/2155 348/405/2156 347/404/2157 +f 347/404/2158 379/437/2159 380/438/2160 +f 381/439/2161 349/406/2162 348/405/2163 +f 348/405/2164 380/438/2165 381/439/2166 +f 382/440/2167 350/407/2168 349/406/2169 +f 349/406/2170 381/439/2171 382/440/2172 +f 383/441/2173 351/408/2174 350/407/2175 +f 350/407/2176 382/440/2177 383/441/2178 +f 384/442/2179 352/409/2180 351/408/2181 +f 351/408/2182 383/441/2183 384/442/2184 +f 385/443/2185 353/410/2186 352/409/2187 +f 352/409/2188 384/442/2189 385/443/2190 +f 386/444/2191 354/411/2192 353/410/2193 +f 353/410/2194 385/443/2195 386/444/2196 +f 387/445/2197 355/412/2198 354/411/2199 +f 354/411/2200 386/444/2201 387/445/2202 +f 388/446/2203 356/413/2204 355/412/2205 +f 355/412/2206 387/445/2207 388/446/2208 +f 389/447/2209 357/414/2210 356/413/2211 +f 356/413/2212 388/446/2213 389/447/2214 +f 390/448/2215 358/415/2216 357/414/2217 +f 357/414/2218 389/447/2219 390/448/2220 +f 391/449/2221 359/416/2222 358/415/2223 +f 358/415/2224 390/448/2225 391/449/2226 +f 392/450/2227 360/417/2228 359/416/2229 +f 359/416/2230 391/449/2231 392/450/2232 +f 393/451/2233 361/418/2234 360/417/2235 +f 360/417/2236 392/450/2237 393/451/2238 +f 362/452/2239 330/419/2240 361/418/2241 +f 361/418/2242 393/451/2243 362/452/2244 +f 395/454/2245 363/421/2246 362/420/2247 +f 362/420/2248 394/453/2249 395/454/2250 +f 396/455/2251 364/422/2252 363/421/2253 +f 363/421/2254 395/454/2255 396/455/2256 +f 397/456/2257 365/423/2258 364/422/2259 +f 364/422/2260 396/455/2261 397/456/2262 +f 398/457/2263 366/424/2264 365/423/2265 +f 365/423/2266 397/456/2267 398/457/2268 +f 399/458/2269 367/425/2270 366/424/2271 +f 366/424/2272 398/457/2273 399/458/2274 +f 400/459/2275 368/426/2276 367/425/2277 +f 367/425/2278 399/458/2279 400/459/2280 +f 401/460/2281 369/427/2282 368/426/2283 +f 368/426/2284 400/459/2285 401/460/2286 +f 402/461/2287 370/428/2288 369/427/2289 +f 369/427/2290 401/460/2291 402/461/2292 +f 403/462/2293 371/429/2294 370/428/2295 +f 370/428/2296 402/461/2297 403/462/2298 +f 404/463/2299 372/430/2300 371/429/2301 +f 371/429/2302 403/462/2303 404/463/2304 +f 405/464/2305 373/431/2306 372/430/2307 +f 372/430/2308 404/463/2309 405/464/2310 +f 406/465/2311 374/432/2312 373/431/2313 +f 373/431/2314 405/464/2315 406/465/2316 +f 407/466/2317 375/433/2318 374/432/2319 +f 374/432/2320 406/465/2321 407/466/2322 +f 408/467/2323 376/434/2324 375/433/2325 +f 375/433/2326 407/466/2327 408/467/2328 +f 409/468/2329 377/435/2330 376/434/2331 +f 376/434/2332 408/467/2333 409/468/2334 +f 410/469/2335 378/436/2336 377/435/2337 +f 377/435/2338 409/468/2339 410/469/2340 +f 411/470/2341 379/437/2342 378/436/2343 +f 378/436/2344 410/469/2345 411/470/2346 +f 412/471/2347 380/438/2348 379/437/2349 +f 379/437/2350 411/470/2351 412/471/2352 +f 413/472/2353 381/439/2354 380/438/2355 +f 380/438/2356 412/471/2357 413/472/2358 +f 414/473/2359 382/440/2360 381/439/2361 +f 381/439/2362 413/472/2363 414/473/2364 +f 415/474/2365 383/441/2366 382/440/2367 +f 382/440/2368 414/473/2369 415/474/2370 +f 416/475/2371 384/442/2372 383/441/2373 +f 383/441/2374 415/474/2375 416/475/2376 +f 417/476/2377 385/443/2378 384/442/2379 +f 384/442/2380 416/475/2381 417/476/2382 +f 418/477/2383 386/444/2384 385/443/2385 +f 385/443/2386 417/476/2387 418/477/2388 +f 419/478/2389 387/445/2390 386/444/2391 +f 386/444/2392 418/477/2393 419/478/2394 +f 420/479/2395 388/446/2396 387/445/2397 +f 387/445/2398 419/478/2399 420/479/2400 +f 421/480/2401 389/447/2402 388/446/2403 +f 388/446/2404 420/479/2405 421/480/2406 +f 422/481/2407 390/448/2408 389/447/2409 +f 389/447/2410 421/480/2411 422/481/2412 +f 423/482/2413 391/449/2414 390/448/2415 +f 390/448/2416 422/481/2417 423/482/2418 +f 424/483/2419 392/450/2420 391/449/2421 +f 391/449/2422 423/482/2423 424/483/2424 +f 425/484/2425 393/451/2426 392/450/2427 +f 392/450/2428 424/483/2429 425/484/2430 +f 394/485/2431 362/452/2432 393/451/2433 +f 393/451/2434 425/484/2435 394/485/2436 +f 427/487/2437 395/454/2438 394/453/2439 +f 394/453/2440 426/486/2441 427/487/2442 +f 428/488/2443 396/455/2444 395/454/2445 +f 395/454/2446 427/487/2447 428/488/2448 +f 429/489/2449 397/456/2450 396/455/2451 +f 396/455/2452 428/488/2453 429/489/2454 +f 430/490/2455 398/457/2456 397/456/2457 +f 397/456/2458 429/489/2459 430/490/2460 +f 431/491/2461 399/458/2462 398/457/2463 +f 398/457/2464 430/490/2465 431/491/2466 +f 432/492/2467 400/459/2468 399/458/2469 +f 399/458/2470 431/491/2471 432/492/2472 +f 433/493/2473 401/460/2474 400/459/2475 +f 400/459/2476 432/492/2477 433/493/2478 +f 434/494/2479 402/461/2480 401/460/2481 +f 401/460/2482 433/493/2483 434/494/2484 +f 435/495/2485 403/462/2486 402/461/2487 +f 402/461/2488 434/494/2489 435/495/2490 +f 436/496/2491 404/463/2492 403/462/2493 +f 403/462/2494 435/495/2495 436/496/2496 +f 437/497/2497 405/464/2498 404/463/2499 +f 404/463/2500 436/496/2501 437/497/2502 +f 438/498/2503 406/465/2504 405/464/2505 +f 405/464/2506 437/497/2507 438/498/2508 +f 439/499/2509 407/466/2510 406/465/2511 +f 406/465/2512 438/498/2513 439/499/2514 +f 440/500/2515 408/467/2516 407/466/2517 +f 407/466/2518 439/499/2519 440/500/2520 +f 441/501/2521 409/468/2522 408/467/2523 +f 408/467/2524 440/500/2525 441/501/2526 +f 442/502/2527 410/469/2528 409/468/2529 +f 409/468/2530 441/501/2531 442/502/2532 +f 443/503/2533 411/470/2534 410/469/2535 +f 410/469/2536 442/502/2537 443/503/2538 +f 444/504/2539 412/471/2540 411/470/2541 +f 411/470/2542 443/503/2543 444/504/2544 +f 445/505/2545 413/472/2546 412/471/2547 +f 412/471/2548 444/504/2549 445/505/2550 +f 446/506/2551 414/473/2552 413/472/2553 +f 413/472/2554 445/505/2555 446/506/2556 +f 447/507/2557 415/474/2558 414/473/2559 +f 414/473/2560 446/506/2561 447/507/2562 +f 448/508/2563 416/475/2564 415/474/2565 +f 415/474/2566 447/507/2567 448/508/2568 +f 449/509/2569 417/476/2570 416/475/2571 +f 416/475/2572 448/508/2573 449/509/2574 +f 450/510/2575 418/477/2576 417/476/2577 +f 417/476/2578 449/509/2579 450/510/2580 +f 451/511/2581 419/478/2582 418/477/2583 +f 418/477/2584 450/510/2585 451/511/2586 +f 452/512/2587 420/479/2588 419/478/2589 +f 419/478/2590 451/511/2591 452/512/2592 +f 453/513/2593 421/480/2594 420/479/2595 +f 420/479/2596 452/512/2597 453/513/2598 +f 454/514/2599 422/481/2600 421/480/2601 +f 421/480/2602 453/513/2603 454/514/2604 +f 455/515/2605 423/482/2606 422/481/2607 +f 422/481/2608 454/514/2609 455/515/2610 +f 456/516/2611 424/483/2612 423/482/2613 +f 423/482/2614 455/515/2615 456/516/2616 +f 457/517/2617 425/484/2618 424/483/2619 +f 424/483/2620 456/516/2621 457/517/2622 +f 426/518/2623 394/485/2624 425/484/2625 +f 425/484/2626 457/517/2627 426/518/2628 +f 459/520/2629 427/487/2630 426/486/2631 +f 426/486/2632 458/519/2633 459/520/2634 +f 460/521/2635 428/488/2636 427/487/2637 +f 427/487/2638 459/520/2639 460/521/2640 +f 461/522/2641 429/489/2642 428/488/2643 +f 428/488/2644 460/521/2645 461/522/2646 +f 462/523/2647 430/490/2648 429/489/2649 +f 429/489/2650 461/522/2651 462/523/2652 +f 463/524/2653 431/491/2654 430/490/2655 +f 430/490/2656 462/523/2657 463/524/2658 +f 464/525/2659 432/492/2660 431/491/2661 +f 431/491/2662 463/524/2663 464/525/2664 +f 465/526/2665 433/493/2666 432/492/2667 +f 432/492/2668 464/525/2669 465/526/2670 +f 466/527/2671 434/494/2672 433/493/2673 +f 433/493/2674 465/526/2675 466/527/2676 +f 467/528/2677 435/495/2678 434/494/2679 +f 434/494/2680 466/527/2681 467/528/2682 +f 468/529/2683 436/496/2684 435/495/2685 +f 435/495/2686 467/528/2687 468/529/2688 +f 469/530/2689 437/497/2690 436/496/2691 +f 436/496/2692 468/529/2693 469/530/2694 +f 470/531/2695 438/498/2696 437/497/2697 +f 437/497/2698 469/530/2699 470/531/2700 +f 471/532/2701 439/499/2702 438/498/2703 +f 438/498/2704 470/531/2705 471/532/2706 +f 472/533/2707 440/500/2708 439/499/2709 +f 439/499/2710 471/532/2711 472/533/2712 +f 473/534/2713 441/501/2714 440/500/2715 +f 440/500/2716 472/533/2717 473/534/2718 +f 474/535/2719 442/502/2720 441/501/2721 +f 441/501/2722 473/534/2723 474/535/2724 +f 475/536/2725 443/503/2726 442/502/2727 +f 442/502/2728 474/535/2729 475/536/2730 +f 476/537/2731 444/504/2732 443/503/2733 +f 443/503/2734 475/536/2735 476/537/2736 +f 477/538/2737 445/505/2738 444/504/2739 +f 444/504/2740 476/537/2741 477/538/2742 +f 478/539/2743 446/506/2744 445/505/2745 +f 445/505/2746 477/538/2747 478/539/2748 +f 479/540/2749 447/507/2750 446/506/2751 +f 446/506/2752 478/539/2753 479/540/2754 +f 480/541/2755 448/508/2756 447/507/2757 +f 447/507/2758 479/540/2759 480/541/2760 +f 481/542/2761 449/509/2762 448/508/2763 +f 448/508/2764 480/541/2765 481/542/2766 +f 482/543/2767 450/510/2768 449/509/2769 +f 449/509/2770 481/542/2771 482/543/2772 +f 483/544/2773 451/511/2774 450/510/2775 +f 450/510/2776 482/543/2777 483/544/2778 +f 484/545/2779 452/512/2780 451/511/2781 +f 451/511/2782 483/544/2783 484/545/2784 +f 485/546/2785 453/513/2786 452/512/2787 +f 452/512/2788 484/545/2789 485/546/2790 +f 486/547/2791 454/514/2792 453/513/2793 +f 453/513/2794 485/546/2795 486/547/2796 +f 487/548/2797 455/515/2798 454/514/2799 +f 454/514/2800 486/547/2801 487/548/2802 +f 488/549/2803 456/516/2804 455/515/2805 +f 455/515/2806 487/548/2807 488/549/2808 +f 489/550/2809 457/517/2810 456/516/2811 +f 456/516/2812 488/549/2813 489/550/2814 +f 458/551/2815 426/518/2816 457/517/2817 +f 457/517/2818 489/550/2819 458/551/2820 +f 490/552/2821 459/520/2822 458/519/2823 +f 490/553/2824 460/521/2825 459/520/2826 +f 490/554/2827 461/522/2828 460/521/2829 +f 490/555/2830 462/523/2831 461/522/2832 +f 490/556/2833 463/524/2834 462/523/2835 +f 490/557/2836 464/525/2837 463/524/2838 +f 490/558/2839 465/526/2840 464/525/2841 +f 490/559/2842 466/527/2843 465/526/2844 +f 490/560/2845 467/528/2846 466/527/2847 +f 490/561/2848 468/529/2849 467/528/2850 +f 490/562/2851 469/530/2852 468/529/2853 +f 490/563/2854 470/531/2855 469/530/2856 +f 490/564/2857 471/532/2858 470/531/2859 +f 490/565/2860 472/533/2861 471/532/2862 +f 490/566/2863 473/534/2864 472/533/2865 +f 490/567/2866 474/535/2867 473/534/2868 +f 490/568/2869 475/536/2870 474/535/2871 +f 490/569/2872 476/537/2873 475/536/2874 +f 490/570/2875 477/538/2876 476/537/2877 +f 490/571/2878 478/539/2879 477/538/2880 +f 490/572/2881 479/540/2882 478/539/2883 +f 490/573/2884 480/541/2885 479/540/2886 +f 490/574/2887 481/542/2888 480/541/2889 +f 490/575/2890 482/543/2891 481/542/2892 +f 490/576/2893 483/544/2894 482/543/2895 +f 490/577/2896 484/545/2897 483/544/2898 +f 490/578/2899 485/546/2900 484/545/2901 +f 490/579/2902 486/547/2903 485/546/2904 +f 490/580/2905 487/548/2906 486/547/2907 +f 490/581/2908 488/549/2909 487/548/2910 +f 490/582/2911 489/550/2912 488/549/2913 +f 490/583/2914 458/551/2915 489/550/2916 +f 491/584/2917 492/585/2918 516/609/2919 +f 516/609/2920 515/608/2921 491/584/2922 +f 492/585/2923 493/586/2924 517/610/2925 +f 517/610/2926 516/609/2927 492/585/2928 +f 493/586/2929 494/587/2930 518/611/2931 +f 518/611/2932 517/610/2933 493/586/2934 +f 494/587/2935 495/588/2936 519/612/2937 +f 519/612/2938 518/611/2939 494/587/2940 +f 495/588/2941 496/589/2942 520/613/2943 +f 520/613/2944 519/612/2945 495/588/2946 +f 496/589/2947 497/590/2948 521/614/2949 +f 521/614/2950 520/613/2951 496/589/2952 +f 497/590/2953 498/728/2954 522/729/2955 +f 522/729/2956 521/614/2957 497/590/2958 +f 498/591/2959 499/592/2960 523/616/2961 +f 523/616/2962 522/615/2963 498/591/2964 +f 499/592/2965 500/593/2966 524/617/2967 +f 524/617/2968 523/616/2969 499/592/2970 +f 500/593/2971 501/594/2972 525/618/2973 +f 525/618/2974 524/617/2975 500/593/2976 +f 501/594/2977 502/595/2978 526/619/2979 +f 526/619/2980 525/618/2981 501/594/2982 +f 502/595/2983 503/596/2984 527/620/2985 +f 527/620/2986 526/619/2987 502/595/2988 +f 503/596/2989 504/597/2990 528/621/2991 +f 528/621/2992 527/620/2993 503/596/2994 +f 504/597/2995 505/598/2996 529/622/2997 +f 529/622/2998 528/621/2999 504/597/3000 +f 505/598/3001 506/599/3002 530/623/3003 +f 530/623/3004 529/622/3005 505/598/3006 +f 506/599/3007 507/600/3008 531/624/3009 +f 531/624/3010 530/623/3011 506/599/3012 +f 507/600/3013 508/601/3014 532/625/3015 +f 532/625/3016 531/624/3017 507/600/3018 +f 508/601/3019 509/602/3020 533/626/3021 +f 533/626/3022 532/625/3023 508/601/3024 +f 509/602/3025 510/603/3026 534/627/3027 +f 534/627/3028 533/626/3029 509/602/3030 +f 510/603/3031 511/604/3032 535/628/3033 +f 535/628/3034 534/627/3035 510/603/3036 +f 511/604/3037 512/605/3038 536/629/3039 +f 536/629/3040 535/628/3041 511/604/3042 +f 512/605/3043 513/606/3044 537/630/3045 +f 537/630/3046 536/629/3047 512/605/3048 +f 513/606/3049 514/607/3050 538/631/3051 +f 538/631/3052 537/630/3053 513/606/3054 +f 514/607/3055 491/584/3056 515/608/3057 +f 515/608/3058 538/631/3059 514/607/3060 +f 515/608/3061 516/609/3062 540/633/3063 +f 540/633/3064 539/632/3065 515/608/3066 +f 516/609/3067 517/610/3068 541/634/3069 +f 541/634/3070 540/633/3071 516/609/3072 +f 517/610/3073 518/611/3074 542/635/3075 +f 542/635/3076 541/634/3077 517/610/3078 +f 518/611/3079 519/612/3080 543/636/3081 +f 543/636/3082 542/635/3083 518/611/3084 +f 519/612/3085 520/613/3086 544/637/3087 +f 544/637/3088 543/636/3089 519/612/3090 +f 520/613/3091 521/614/3092 545/638/3093 +f 545/638/3094 544/637/3095 520/613/3096 +f 521/614/3097 522/729/3098 546/730/3099 +f 546/730/3100 545/638/3101 521/614/3102 +f 522/615/3103 523/616/3104 547/640/3105 +f 547/640/3106 546/639/3107 522/615/3108 +f 523/616/3109 524/617/3110 548/641/3111 +f 548/641/3112 547/640/3113 523/616/3114 +f 524/617/3115 525/618/3116 549/642/3117 +f 549/642/3118 548/641/3119 524/617/3120 +f 525/618/3121 526/619/3122 550/643/3123 +f 550/643/3124 549/642/3125 525/618/3126 +f 526/619/3127 527/620/3128 551/644/3129 +f 551/644/3130 550/643/3131 526/619/3132 +f 527/620/3133 528/621/3134 552/645/3135 +f 552/645/3136 551/644/3137 527/620/3138 +f 528/621/3139 529/622/3140 553/646/3141 +f 553/646/3142 552/645/3143 528/621/3144 +f 529/622/3145 530/623/3146 554/647/3147 +f 554/647/3148 553/646/3149 529/622/3150 +f 530/623/3151 531/624/3152 555/648/3153 +f 555/648/3154 554/647/3155 530/623/3156 +f 531/624/3157 532/625/3158 556/649/3159 +f 556/649/3160 555/648/3161 531/624/3162 +f 532/625/3163 533/626/3164 557/650/3165 +f 557/650/3166 556/649/3167 532/625/3168 +f 533/626/3169 534/627/3170 558/651/3171 +f 558/651/3172 557/650/3173 533/626/3174 +f 534/627/3175 535/628/3176 559/652/3177 +f 559/652/3178 558/651/3179 534/627/3180 +f 535/628/3181 536/629/3182 560/653/3183 +f 560/653/3184 559/652/3185 535/628/3186 +f 536/629/3187 537/630/3188 561/654/3189 +f 561/654/3190 560/653/3191 536/629/3192 +f 537/630/3193 538/631/3194 562/655/3195 +f 562/655/3196 561/654/3197 537/630/3198 +f 538/631/3199 515/608/3200 539/632/3201 +f 539/632/3202 562/655/3203 538/631/3204 +f 539/632/3205 540/633/3206 564/657/3207 +f 564/657/3208 563/656/3209 539/632/3210 +f 540/633/3211 541/634/3212 565/658/3213 +f 565/658/3214 564/657/3215 540/633/3216 +f 541/634/3217 542/635/3218 566/659/3219 +f 566/659/3220 565/658/3221 541/634/3222 +f 542/635/3223 543/636/3224 567/660/3225 +f 567/660/3226 566/659/3227 542/635/3228 +f 543/636/3229 544/637/3230 568/661/3231 +f 568/661/3232 567/660/3233 543/636/3234 +f 544/637/3235 545/638/3236 569/662/3237 +f 569/662/3238 568/661/3239 544/637/3240 +f 545/638/3241 546/730/3242 570/731/3243 +f 570/731/3244 569/662/3245 545/638/3246 +f 546/639/3247 547/640/3248 571/664/3249 +f 571/664/3250 570/663/3251 546/639/3252 +f 547/640/3253 548/641/3254 572/665/3255 +f 572/665/3256 571/664/3257 547/640/3258 +f 548/641/3259 549/642/3260 573/666/3261 +f 573/666/3262 572/665/3263 548/641/3264 +f 549/642/3265 550/643/3266 574/667/3267 +f 574/667/3268 573/666/3269 549/642/3270 +f 550/643/3271 551/644/3272 575/668/3273 +f 575/668/3274 574/667/3275 550/643/3276 +f 551/644/3277 552/645/3278 576/669/3279 +f 576/669/3280 575/668/3281 551/644/3282 +f 552/645/3283 553/646/3284 577/670/3285 +f 577/670/3286 576/669/3287 552/645/3288 +f 553/646/3289 554/647/3290 578/671/3291 +f 578/671/3292 577/670/3293 553/646/3294 +f 554/647/3295 555/648/3296 579/672/3297 +f 579/672/3298 578/671/3299 554/647/3300 +f 555/648/3301 556/649/3302 580/673/3303 +f 580/673/3304 579/672/3305 555/648/3306 +f 556/649/3307 557/650/3308 581/674/3309 +f 581/674/3310 580/673/3311 556/649/3312 +f 557/650/3313 558/651/3314 582/675/3315 +f 582/675/3316 581/674/3317 557/650/3318 +f 558/651/3319 559/652/3320 583/676/3321 +f 583/676/3322 582/675/3323 558/651/3324 +f 559/652/3325 560/653/3326 584/677/3327 +f 584/677/3328 583/676/3329 559/652/3330 +f 560/653/3331 561/654/3332 585/678/3333 +f 585/678/3334 584/677/3335 560/653/3336 +f 561/654/3337 562/655/3338 586/679/3339 +f 586/679/3340 585/678/3341 561/654/3342 +f 562/655/3343 539/632/3344 563/656/3345 +f 563/656/3346 586/679/3347 562/655/3348 +f 563/656/3349 564/657/3350 588/681/3351 +f 588/681/3352 587/680/3353 563/656/3354 +f 564/657/3355 565/658/3356 589/682/3357 +f 589/682/3358 588/681/3359 564/657/3360 +f 565/658/3361 566/659/3362 590/683/3363 +f 590/683/3364 589/682/3365 565/658/3366 +f 566/659/3367 567/660/3368 591/684/3369 +f 591/684/3370 590/683/3371 566/659/3372 +f 567/660/3373 568/661/3374 592/685/3375 +f 592/685/3376 591/684/3377 567/660/3378 +f 568/661/3379 569/662/3380 593/686/3381 +f 593/686/3382 592/685/3383 568/661/3384 +f 569/662/3385 570/731/3386 594/732/3387 +f 594/732/3388 593/686/3389 569/662/3390 +f 570/663/3391 571/664/3392 595/688/3393 +f 595/688/3394 594/687/3395 570/663/3396 +f 571/664/3397 572/665/3398 596/689/3399 +f 596/689/3400 595/688/3401 571/664/3402 +f 572/665/3403 573/666/3404 597/690/3405 +f 597/690/3406 596/689/3407 572/665/3408 +f 573/666/3409 574/667/3410 598/691/3411 +f 598/691/3412 597/690/3413 573/666/3414 +f 574/667/3415 575/668/3416 599/692/3417 +f 599/692/3418 598/691/3419 574/667/3420 +f 575/668/3421 576/669/3422 600/693/3423 +f 600/693/3424 599/692/3425 575/668/3426 +f 576/669/3427 577/670/3428 601/694/3429 +f 601/694/3430 600/693/3431 576/669/3432 +f 577/670/3433 578/671/3434 602/695/3435 +f 602/695/3436 601/694/3437 577/670/3438 +f 578/671/3439 579/672/3440 603/696/3441 +f 603/696/3442 602/695/3443 578/671/3444 +f 579/672/3445 580/673/3446 604/697/3447 +f 604/697/3448 603/696/3449 579/672/3450 +f 580/673/3451 581/674/3452 605/698/3453 +f 605/698/3454 604/697/3455 580/673/3456 +f 581/674/3457 582/675/3458 606/699/3459 +f 606/699/3460 605/698/3461 581/674/3462 +f 582/675/3463 583/676/3464 607/700/3465 +f 607/700/3466 606/699/3467 582/675/3468 +f 583/676/3469 584/677/3470 608/701/3471 +f 608/701/3472 607/700/3473 583/676/3474 +f 584/677/3475 585/678/3476 609/702/3477 +f 609/702/3478 608/701/3479 584/677/3480 +f 585/678/3481 586/679/3482 610/703/3483 +f 610/703/3484 609/702/3485 585/678/3486 +f 586/679/3487 563/656/3488 587/680/3489 +f 587/680/3490 610/703/3491 586/679/3492 +f 587/680/3493 588/681/3494 612/705/3495 +f 612/705/3496 611/704/3497 587/680/3498 +f 588/681/3499 589/682/3500 613/706/3501 +f 613/706/3502 612/705/3503 588/681/3504 +f 589/682/3505 590/683/3506 614/707/3507 +f 614/707/3508 613/706/3509 589/682/3510 +f 590/683/3511 591/684/3512 615/708/3513 +f 615/708/3514 614/707/3515 590/683/3516 +f 591/684/3517 592/685/3518 616/709/3519 +f 616/709/3520 615/708/3521 591/684/3522 +f 592/685/3523 593/686/3524 617/710/3525 +f 617/710/3526 616/709/3527 592/685/3528 +f 593/735/3529 594/732/3530 618/733/3531 +f 618/733/3532 617/734/3533 593/735/3534 +f 594/687/3535 595/688/3536 619/712/3537 +f 619/712/3538 618/711/3539 594/687/3540 +f 595/688/3541 596/689/3542 620/713/3543 +f 620/713/3544 619/712/3545 595/688/3546 +f 596/689/3547 597/690/3548 621/714/3549 +f 621/714/3550 620/713/3551 596/689/3552 +f 597/690/3553 598/691/3554 622/715/3555 +f 622/715/3556 621/714/3557 597/690/3558 +f 598/691/3559 599/692/3560 623/716/3561 +f 623/716/3562 622/715/3563 598/691/3564 +f 599/692/3565 600/693/3566 624/717/3567 +f 624/717/3568 623/716/3569 599/692/3570 +f 600/693/3571 601/694/3572 625/718/3573 +f 625/718/3574 624/717/3575 600/693/3576 +f 601/694/3577 602/695/3578 626/719/3579 +f 626/719/3580 625/718/3581 601/694/3582 +f 602/695/3583 603/696/3584 627/720/3585 +f 627/720/3586 626/719/3587 602/695/3588 +f 603/696/3589 604/697/3590 628/721/3591 +f 628/721/3592 627/720/3593 603/696/3594 +f 604/697/3595 605/698/3596 629/722/3597 +f 629/722/3598 628/721/3599 604/697/3600 +f 605/698/3601 606/699/3602 630/723/3603 +f 630/723/3604 629/722/3605 605/698/3606 +f 606/699/3607 607/700/3608 631/724/3609 +f 631/724/3610 630/723/3611 606/699/3612 +f 607/700/3613 608/701/3614 632/725/3615 +f 632/725/3616 631/724/3617 607/700/3618 +f 608/701/3619 609/702/3620 633/726/3621 +f 633/726/3622 632/725/3623 608/701/3624 +f 609/702/3625 610/703/3626 634/727/3627 +f 634/727/3628 633/726/3629 609/702/3630 +f 610/703/3631 587/680/3632 611/704/3633 +f 611/704/3634 634/727/3635 610/703/3636 +f 513/737/3637 512/738/3638 511/739/3639 +f 511/739/3640 510/740/3641 509/741/3642 +f 509/741/3643 508/742/3644 507/743/3645 +f 511/739/3646 509/741/3647 507/743/3648 +f 507/743/3649 506/744/3650 505/745/3651 +f 505/745/3652 504/746/3653 503/747/3654 +f 507/743/3655 505/745/3656 503/747/3657 +f 503/747/3658 502/748/3659 501/749/3660 +f 501/749/3661 500/750/3662 499/751/3663 +f 503/747/3664 501/749/3665 499/751/3666 +f 507/743/3667 503/747/3668 499/751/3669 +f 499/751/3670 498/752/3671 497/753/3672 +f 497/753/3673 496/754/3674 495/755/3675 +f 499/751/3676 497/753/3677 495/755/3678 +f 495/755/3679 494/756/3680 493/757/3681 +f 493/757/3682 492/758/3683 491/759/3684 +f 495/755/3685 493/757/3686 491/759/3687 +f 499/751/3688 495/755/3689 491/759/3690 +f 507/743/3691 499/751/3692 491/759/3693 +f 511/739/3694 507/743/3695 491/759/3696 +f 513/737/3697 511/739/3698 491/759/3699 +f 514/736/3700 513/737/3701 491/759/3702 +f 612/705/3703 613/706/3704 614/707/3705 +f 614/707/3706 615/708/3707 616/709/3708 +f 616/709/3709 617/710/3710 618/711/3711 +f 614/707/3712 616/709/3713 618/711/3714 +f 618/711/3715 619/712/3716 620/713/3717 +f 620/713/3718 621/714/3719 622/715/3720 +f 618/711/3721 620/713/3722 622/715/3723 +f 622/715/3724 623/716/3725 624/717/3726 +f 624/717/3727 625/718/3728 626/719/3729 +f 622/715/3730 624/717/3731 626/719/3732 +f 618/711/3733 622/715/3734 626/719/3735 +f 626/719/3736 627/720/3737 628/721/3738 +f 628/721/3739 629/722/3740 630/723/3741 +f 626/719/3742 628/721/3743 630/723/3744 +f 630/723/3745 631/724/3746 632/725/3747 +f 632/725/3748 633/726/3749 634/727/3750 +f 630/723/3751 632/725/3752 634/727/3753 +f 626/719/3754 630/723/3755 634/727/3756 +f 618/711/3757 626/719/3758 634/727/3759 +f 614/707/3760 618/711/3761 634/727/3762 +f 612/705/3763 614/707/3764 634/727/3765 +f 611/704/3766 612/705/3767 634/727/3768 +# 1256 faces + diff --git a/examples/resources/shaders/base.vs b/examples/resources/shaders/base.vs index 59eae0a00..b0f930b70 100644 --- a/examples/resources/shaders/base.vs +++ b/examples/resources/shaders/base.vs @@ -6,8 +6,7 @@ in vec3 vertexNormal; out vec2 fragTexCoord; -uniform mat4 projectionMatrix; -uniform mat4 modelviewMatrix; +uniform mat4 mvpMatrix; // NOTE: Add here your custom variables @@ -15,5 +14,5 @@ void main() { fragTexCoord = vertexTexCoord; - gl_Position = projectionMatrix*modelviewMatrix*vec4(vertexPosition, 1.0); + gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); } \ No newline at end of file diff --git a/examples/resources/shaders/bloom.fs b/examples/resources/shaders/bloom.fs index f9cebe18a..2833ce330 100644 --- a/examples/resources/shaders/bloom.fs +++ b/examples/resources/shaders/bloom.fs @@ -5,7 +5,7 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables diff --git a/examples/resources/shaders/grayscale.fs b/examples/resources/shaders/grayscale.fs index 38337e007..af50b8c1b 100644 --- a/examples/resources/shaders/grayscale.fs +++ b/examples/resources/shaders/grayscale.fs @@ -5,16 +5,16 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables void main() { - vec4 base = texture2D(texture0, fragTexCoord)*tintColor; + vec4 base = texture2D(texture0, fragTexCoord)*fragTintColor; // Convert to grayscale using NTSC conversion weights float gray = dot(base.rgb, vec3(0.299, 0.587, 0.114)); - fragColor = vec4(gray, gray, gray, tintColor.a); + fragColor = vec4(gray, gray, gray, fragTintColor.a); } \ No newline at end of file diff --git a/examples/resources/shaders/phong.fs b/examples/resources/shaders/phong.fs new file mode 100644 index 000000000..f79413d98 --- /dev/null +++ b/examples/resources/shaders/phong.fs @@ -0,0 +1,76 @@ +#version 330 + +// Vertex shader input data +in vec2 fragTexCoord; +in vec3 fragNormal; + +// Diffuse data +uniform sampler2D texture0; +uniform vec4 fragTintColor; + +// Light attributes +uniform vec3 light_ambientColor = vec3(0.6, 0.3, 0.0); +uniform vec3 light_diffuseColor = vec3(1.0, 0.5, 0.0); +uniform vec3 light_specularColor = vec3(0.0, 1.0, 0.0); +uniform float light_intensity = 1.0; +uniform float light_specIntensity = 1.0; + +// Material attributes +uniform vec3 mat_ambientColor = vec3(1.0, 1.0, 1.0); +uniform vec3 mat_specularColor = vec3(1.0, 1.0, 1.0); +uniform float mat_glossiness = 50.0; + +// World attributes +uniform vec3 lightPos; +uniform vec3 cameraPos; + +// Fragment shader output data +out vec4 fragColor; + +vec3 AmbientLighting() +{ + return (mat_ambientColor*light_ambientColor); +} + +vec3 DiffuseLighting(in vec3 N, in vec3 L) +{ + // Lambertian reflection calculation + float diffuse = clamp(dot(N, L), 0, 1); + + return (fragTintColor.xyz*light_diffuseColor*light_intensity*diffuse); +} + +vec3 SpecularLighting(in vec3 N, in vec3 L, in vec3 V) +{ + float specular = 0.0; + + // Calculate specular reflection only if the surface is oriented to the light source + if (dot(N, L) > 0) + { + // Calculate half vector + vec3 H = normalize(L + V); + + // Calculate specular intensity + specular = pow(dot(N, H), 3 + mat_glossiness); + } + + return (mat_specularColor*light_specularColor*light_specIntensity*specular); +} + +void main() +{ + // Normalize input vectors + vec3 L = normalize(lightPos); + vec3 V = normalize(cameraPos); + vec3 N = normalize(fragNormal); + + vec3 ambient = AmbientLighting(); + vec3 diffuse = DiffuseLighting(N, L); + vec3 specular = SpecularLighting(N, L, V); + + // Get base color from texture + vec4 textureColor = texture(texture0, fragTexCoord); + vec3 finalColor = textureColor.rgb; + + fragColor = vec4(finalColor * (ambient + diffuse + specular), textureColor.a); +} \ No newline at end of file diff --git a/examples/resources/shaders/phong.vs b/examples/resources/shaders/phong.vs new file mode 100644 index 000000000..ee6d34bfa --- /dev/null +++ b/examples/resources/shaders/phong.vs @@ -0,0 +1,27 @@ +#version 330 + +// Vertex input data +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; + +// Projection and model data +uniform mat4 mvpMatrix; +uniform mat4 modelMatrix; + +// Attributes to fragment shader +out vec2 fragTexCoord; +out vec3 fragNormal; + +void main() +{ + // Send texture coord to fragment shader + fragTexCoord = vertexTexCoord; + + // Calculate view vector normal from model + mat3 normalMatrix = transpose(inverse(mat3(modelMatrix))); + fragNormal = normalize(normalMatrix*vertexNormal); + + // Calculate final vertex position + gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); +} \ No newline at end of file diff --git a/examples/resources/shaders/shapes_base.vs b/examples/resources/shaders/shapes_base.vs index 78e543b71..1fd686beb 100644 --- a/examples/resources/shaders/shapes_base.vs +++ b/examples/resources/shaders/shapes_base.vs @@ -4,16 +4,15 @@ attribute vec3 vertexPosition; attribute vec2 vertexTexCoord; attribute vec4 vertexColor; -uniform mat4 projectionMatrix; -uniform mat4 modelviewMatrix; +uniform mat4 mvpMatrix; varying vec2 fragTexCoord; -varying vec4 fragColor; +varying vec4 fragTintColor; void main() { fragTexCoord = vertexTexCoord; - fragColor = vertexColor; + fragTintColor = vertexColor; - gl_Position = projectionMatrix*modelviewMatrix*vec4(vertexPosition, 1.0); + gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); } \ No newline at end of file diff --git a/examples/resources/shaders/shapes_grayscale.fs b/examples/resources/shaders/shapes_grayscale.fs index 1b7788717..23ba91539 100644 --- a/examples/resources/shaders/shapes_grayscale.fs +++ b/examples/resources/shaders/shapes_grayscale.fs @@ -2,11 +2,11 @@ uniform sampler2D texture0; varying vec2 fragTexCoord; -varying vec4 fragColor; +varying vec4 fragTintColor; void main() { - vec4 base = texture2D(texture0, fragTexCoord)*fragColor; + vec4 base = texture2D(texture0, fragTexCoord)*fragTintColor; // Convert to grayscale using NTSC conversion weights float gray = dot(base.rgb, vec3(0.299, 0.587, 0.114)); diff --git a/examples/resources/shaders/swirl.fs b/examples/resources/shaders/swirl.fs index ba26cc05a..f89ef4061 100644 --- a/examples/resources/shaders/swirl.fs +++ b/examples/resources/shaders/swirl.fs @@ -5,17 +5,17 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables -const float renderWidth = 800; // HARDCODED for example! -const float renderHeight = 480; // Use uniforms instead... +const float renderWidth = 800.0; // HARDCODED for example! +const float renderHeight = 480.0; // Use uniforms instead... float radius = 250.0; float angle = 0.8; -uniform vec2 center = vec2(200, 200); +uniform vec2 center = vec2(200.0, 200.0); void main (void) { diff --git a/examples/shaders_basic_lighting.c b/examples/shaders_basic_lighting.c new file mode 100644 index 000000000..ba779b94f --- /dev/null +++ b/examples/shaders_basic_lighting.c @@ -0,0 +1,152 @@ +/******************************************************************************************* +* +* raylib [shaders] example - Basic lighting: Blinn-Phong +* +* This example has been created using raylib 1.3 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2014 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#define SHININESS_SPEED 1.0f +#define LIGHT_SPEED 0.25f + +int main() +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic lighting"); + + // Camera initialization + Camera camera = {{ 8.0f, 8.0f, 8.0f }, { 0.0f, 3.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + + // Model initialization + Vector3 position = { 0.0f, 0.0f, 0.0f }; + Model model = LoadModel("resources/model/dwarf.obj"); + Shader shader = LoadShader("resources/shaders/phong.vs", "resources/shaders/phong.fs"); + SetModelShader(&model, shader); + + // Shader locations initialization + int lIntensityLoc = GetShaderLocation(shader, "light_intensity"); + int lAmbientLoc = GetShaderLocation(shader, "light_ambientColor"); + int lDiffuseLoc = GetShaderLocation(shader, "light_diffuseColor"); + int lSpecularLoc = GetShaderLocation(shader, "light_specularColor"); + int lSpecIntensityLoc = GetShaderLocation(shader, "light_specIntensity"); + + int mAmbientLoc = GetShaderLocation(shader, "mat_ambientColor"); + int mSpecularLoc = GetShaderLocation(shader, "mat_specularColor"); + int mGlossLoc = GetShaderLocation(shader, "mat_glossiness"); + + // Camera and light vectors shader locations + int cameraLoc = GetShaderLocation(shader, "cameraPos"); + int lightLoc = GetShaderLocation(shader, "lightPos"); + + // Light and material definitions + Light light; + Material matBlinn; + + // Light initialization + light.position = (Vector3){ 4.0f, 2.0f, 0.0f }; + light.direction = (Vector3){ 5.0f, 1.0f, 1.0f }; + light.intensity = 1.0f; + light.diffuse = WHITE; + light.ambient = (Color){ 150, 75, 0, 255 }; + light.specular = WHITE; + light.specIntensity = 1.0f; + + // Material initialization + matBlinn.diffuse = WHITE; + matBlinn.ambient = (Color){ 50, 50, 50, 255 }; + matBlinn.specular = WHITE; + matBlinn.glossiness = 50.0f; + + // Setup camera + SetCameraMode(CAMERA_FREE); // Set camera mode + SetCameraPosition(camera.position); // Set internal camera position to match our camera position + SetCameraTarget(camera.target); // Set internal camera target to match our camera target + + SetTargetFPS(60); + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + UpdateCamera(&camera); // Update camera position + + // Glossiness input control + if(IsKeyDown(KEY_UP)) matBlinn.glossiness += SHININESS_SPEED; + else if(IsKeyDown(KEY_DOWN)) + { + matBlinn.glossiness -= SHININESS_SPEED; + if( matBlinn.glossiness < 0) matBlinn.glossiness = 0.0f; + } + + // Light X movement + if (IsKeyDown(KEY_D)) light.position.x += LIGHT_SPEED; + else if(IsKeyDown(KEY_A)) light.position.x -= LIGHT_SPEED; + + // Light Y movement + if (IsKeyDown(KEY_LEFT_SHIFT)) light.position.y += LIGHT_SPEED; + else if (IsKeyDown(KEY_LEFT_CONTROL)) light.position.y -= LIGHT_SPEED; + + // Light Z movement + if (IsKeyDown(KEY_S)) light.position.z += LIGHT_SPEED; + else if (IsKeyDown(KEY_W)) light.position.z -= LIGHT_SPEED; + + // Send light values to shader + SetShaderValue(shader, lIntensityLoc, &light.intensity, 1); + SetShaderValue(shader, lAmbientLoc, ColorToFloat(light.ambient), 3); + SetShaderValue(shader, lDiffuseLoc, ColorToFloat(light.diffuse), 3); + SetShaderValue(shader, lSpecularLoc, ColorToFloat(light.specular), 3); + SetShaderValue(shader, lSpecIntensityLoc, &light.specIntensity, 1); + + // Send material values to shader + SetShaderValue(shader, mAmbientLoc, ColorToFloat(matBlinn.ambient), 3); + SetShaderValue(shader, mSpecularLoc, ColorToFloat(matBlinn.specular), 3); + SetShaderValue(shader, mGlossLoc, &matBlinn.glossiness, 1); + + // Send camera and light transform values to shader + SetShaderValue(shader, cameraLoc, VectorToFloat(camera.position), 3); + SetShaderValue(shader, lightLoc, VectorToFloat(light.position), 3); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + Begin3dMode(camera); + + DrawModel(model, position, 4.0f, matBlinn.diffuse); + DrawSphere(light.position, 0.5f, GOLD); + + DrawGrid(20, 1.0f); + + End3dMode(); + + DrawFPS(10, 10); // Draw FPS + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + UnloadShader(shader); + UnloadModel(model); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} diff --git a/examples/shaders_custom_uniform.c b/examples/shaders_custom_uniform.c index 59350d353..0377cfff2 100644 --- a/examples/shaders_custom_uniform.c +++ b/examples/shaders_custom_uniform.c @@ -30,13 +30,13 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [shaders] example - custom uniform variable"); // Define the camera to look into our 3d world - Camera camera = {{ 3.0, 3.0, 3.0 }, { 0.0, 1.5, 0.0 }, { 0.0, 1.0, 0.0 }}; + Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture SetModelTexture(&dwarf, texture); // Bind texture to model - Vector3 position = { 0.0, 0.0, 0.0 }; // Set model position + Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position Shader shader = LoadShader("resources/shaders/base.vs", "resources/shaders/swirl.fs"); // Load postpro shader @@ -45,7 +45,7 @@ int main() // NOTE: If uniform variable could not be found in the shader, function returns -1 int swirlCenterLoc = GetShaderLocation(shader, "center"); - float swirlCenter[2] = { screenWidth/2, screenHeight/2 }; + float swirlCenter[2] = { (float)screenWidth/2, (float)screenHeight/2 }; SetPostproShader(shader); // Set fullscreen postprocessing shader @@ -83,7 +83,7 @@ int main() DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture - DrawGrid(10.0, 1.0); // Draw a grid + DrawGrid(10, 1.0f); // Draw a grid End3dMode(); diff --git a/examples/shaders_model_shader.c b/examples/shaders_model_shader.c index 8ea390e5b..5d8c3711e 100644 --- a/examples/shaders_model_shader.c +++ b/examples/shaders_model_shader.c @@ -30,7 +30,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [shaders] example - model shader"); // Define the camera to look into our 3d world - Camera camera = {{ 3.0, 3.0, 3.0 }, { 0.0, 1.5, 0.0 }, { 0.0, 1.0, 0.0 }}; + Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture @@ -40,7 +40,7 @@ int main() SetModelShader(&dwarf, shader); // Set shader effect to 3d model SetModelTexture(&dwarf, texture); // Bind texture to model - Vector3 position = { 0.0, 0.0, 0.0 }; // Set model position + Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position // Setup orbital camera SetCameraMode(CAMERA_ORBITAL); // Set an orbital camera mode @@ -68,7 +68,7 @@ int main() DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture - DrawGrid(10.0, 1.0); // Draw a grid + DrawGrid(10, 1.0f); // Draw a grid End3dMode(); diff --git a/examples/shaders_postprocessing.c b/examples/shaders_postprocessing.c index 5d7c1f617..0f851658f 100644 --- a/examples/shaders_postprocessing.c +++ b/examples/shaders_postprocessing.c @@ -30,13 +30,13 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [shaders] example - postprocessing shader"); // Define the camera to look into our 3d world - Camera camera = {{ 3.0, 3.0, 3.0 }, { 0.0, 1.5, 0.0 }, { 0.0, 1.0, 0.0 }}; + Camera camera = {{ 3.0f, 3.0f, 3.0f }, { 0.0f, 1.5f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; Model dwarf = LoadModel("resources/model/dwarf.obj"); // Load OBJ model Texture2D texture = LoadTexture("resources/model/dwarf_diffuse.png"); // Load model texture SetModelTexture(&dwarf, texture); // Bind texture to model - Vector3 position = { 0.0, 0.0, 0.0 }; // Set model position + Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position Shader shader = LoadShader("resources/shaders/base.vs", "resources/shaders/bloom.fs"); // Load postpro shader @@ -69,7 +69,7 @@ int main() DrawModel(dwarf, position, 2.0f, WHITE); // Draw 3d model with texture - DrawGrid(10.0, 1.0); // Draw a grid + DrawGrid(10, 1.0f); // Draw a grid End3dMode(); diff --git a/examples/shapes_basic_shapes.c b/examples/shapes_basic_shapes.c index 4b14af89d..6b2719fc9 100644 --- a/examples/shapes_basic_shapes.c +++ b/examples/shapes_basic_shapes.c @@ -19,6 +19,8 @@ int main() int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - basic shapes drawing"); + + SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/shapes_colors_palette.c b/examples/shapes_colors_palette.c index 3e1611145..dcab862e2 100644 --- a/examples/shapes_colors_palette.c +++ b/examples/shapes_colors_palette.c @@ -19,6 +19,8 @@ int main() int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - raylib color palette"); + + SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/shapes_logo_raylib.c b/examples/shapes_logo_raylib.c index 3dd8fbf39..be94988c9 100644 --- a/examples/shapes_logo_raylib.c +++ b/examples/shapes_logo_raylib.c @@ -19,6 +19,8 @@ int main() int screenHeight = 450; InitWindow(screenWidth, screenHeight, "raylib [shapes] example - raylib logo using shapes"); + + SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop diff --git a/examples/shapes_logo_raylib_anim.c b/examples/shapes_logo_raylib_anim.c index d08313782..b1bdc3a8c 100644 --- a/examples/shapes_logo_raylib_anim.c +++ b/examples/shapes_logo_raylib_anim.c @@ -35,9 +35,7 @@ int main() char raylib[8] = " \0"; // raylib text array, max 8 letters int state = 0; // Tracking animation states (State Machine) - - float alpha = 1.0; // Useful for fading - + float alpha = 1.0f; // Useful for fading SetTargetFPS(60); //-------------------------------------------------------------------------------------- diff --git a/examples/textures_logo_raylib.c b/examples/textures_logo_raylib.c index 2ebf08672..f2f931281 100644 --- a/examples/textures_logo_raylib.c +++ b/examples/textures_logo_raylib.c @@ -38,8 +38,7 @@ int main() ClearBackground(RAYWHITE); - DrawTexture(texture, screenWidth/2 - texture.width/2, - screenHeight/2 - texture.height/2, WHITE); + DrawTexture(texture, screenWidth/2 - texture.width/2, screenHeight/2 - texture.height/2, WHITE); DrawText("this IS a texture!", 360, 370, 10, GRAY); diff --git a/examples/textures_particles_trail_blending.c b/examples/textures_particles_trail_blending.c index da01f8632..76cd04234 100644 --- a/examples/textures_particles_trail_blending.c +++ b/examples/textures_particles_trail_blending.c @@ -41,12 +41,12 @@ int main() mouseTail[i].position = (Vector2){ 0, 0 }; mouseTail[i].color = (Color){ GetRandomValue(0, 255), GetRandomValue(0, 255), GetRandomValue(0, 255), 255 }; mouseTail[i].alpha = 1.0f; - mouseTail[i].size = (float)GetRandomValue(1, 30)/20; + mouseTail[i].size = (float)GetRandomValue(1, 30)/20.0f; mouseTail[i].rotation = GetRandomValue(0, 360); mouseTail[i].active = false; } - float gravity = 3; + float gravity = 3.0f; Texture2D smoke = LoadTexture("resources/smoke.png"); @@ -85,7 +85,7 @@ int main() if (mouseTail[i].alpha <= 0.0f) mouseTail[i].active = false; - mouseTail[i].rotation += 5; + mouseTail[i].rotation += 5.0f; } } diff --git a/examples/textures_rectangle.c b/examples/textures_rectangle.c index bf52bb187..cca5b2169 100644 --- a/examples/textures_rectangle.c +++ b/examples/textures_rectangle.c @@ -23,7 +23,7 @@ int main() // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) Texture2D guybrush = LoadTexture("resources/guybrush.png"); // Texture loading - Vector2 position = { 350, 240 }; + Vector2 position = { 350.0f, 240.0f }; Rectangle frameRec = { 0, 0, guybrush.width/7, guybrush.height }; int currentFrame = 0; //-------------------------------------------------------------------------------------- diff --git a/games/floppy/floppy.c b/games/floppy/floppy.c index 0617797e0..0c0cb5f2e 100644 --- a/games/floppy/floppy.c +++ b/games/floppy/floppy.c @@ -2,16 +2,6 @@ * * raylib game - Floppy Bird * -* Welcome to raylib! -* -* To test examples, just press F6 and execute raylib_compile_execute script -* Note that compiled executable is placed in the same folder as .c file -* -* You can find all basic examples on C:\raylib\raylib\examples folder or -* raylib official webpage: www.raylib.com -* -* Enjoy using raylib. :) -* * This game has been created using raylib 1.1 (www.raylib.com) * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) * @@ -86,10 +76,21 @@ int main() { // Update //---------------------------------------------------------------------------------- - backScroll--; + // Background scroll logic + backScroll--; if (backScroll <= -800) backScroll = 0; + // Player movement logic + if (!gameover) + { + if (IsKeyDown(KEY_SPACE)) floppyPos.y -= 3; + else floppyPos.y += 1; + + if (IsKeyPressed(KEY_SPACE)) PlaySound(jump); + } + + // Tubes moving logic for (int i = 0; i < MAX_TUBES; i++) tubesPos[i].x -= tubesSpeedX; for (int i = 0; i < MAX_TUBES*2; i += 2) @@ -98,12 +99,7 @@ int main() tubesRecs[i+1].x = tubesPos[i/2].x; } - if (IsKeyDown(KEY_SPACE) && !gameover) floppyPos.y -= 3; - else floppyPos.y += 1; - - if (IsKeyPressed(KEY_SPACE) && !gameover) PlaySound(jump); - - // Check Collisions + // Check collisions player-tubes for (int i = 0; i < MAX_TUBES*2; i++) { if (CheckCollisionCircleRec((Vector2){ floppyPos.x + floppy.width/2, floppyPos.y + floppy.height/2 }, floppy.width/2, tubesRecs[i])) @@ -122,6 +118,7 @@ int main() } } + // Gameover logic for reset if (gameover && IsKeyPressed(KEY_ENTER)) { for (int i = 0; i < MAX_TUBES; i++) @@ -147,7 +144,6 @@ int main() gameover = false; score = 0; } - //---------------------------------------------------------------------------------- // Draw @@ -156,32 +152,39 @@ int main() ClearBackground(RAYWHITE); + // Draw scrolling background DrawTexture(background, backScroll, 0, WHITE); DrawTexture(background, screenWidth + backScroll, 0, WHITE); - if (!gameover) - { - DrawTextureEx(floppy, floppyPos, 0, 1.0, WHITE); - //DrawCircleLines(floppyPos.x + floppy.width/2, floppyPos.y + floppy.height/2, floppy.width/2, RED); - } - + // Draw moving tubes for (int i = 0; i < MAX_TUBES; i++) { if (tubesPos[i].x <= 800) DrawTextureEx(tubes, tubesPos[i], 0, 1.0, WHITE); + // Draw collision recs //DrawRectangleLines(tubesRecs[i*2].x, tubesRecs[i*2].y, tubesRecs[i*2].width, tubesRecs[i*2].height, RED); //DrawRectangleLines(tubesRecs[i*2 + 1].x, tubesRecs[i*2 + 1].y, tubesRecs[i*2 + 1].width, tubesRecs[i*2 + 1].height, RED); } + // Draw scores DrawText(FormatText("%04i", score), 20, 20, 40, PINK); DrawText(FormatText("HI-SCORE: %04i", hiscore), 20, 70, 20, VIOLET); - if (gameover) + // Draw player or game over messages + if (!gameover) + { + DrawTextureEx(floppy, floppyPos, 0, 1.0, WHITE); + + // Draw collision circle + //DrawCircleLines(floppyPos.x + floppy.width/2, floppyPos.y + floppy.height/2, floppy.width/2, RED); + } + else { DrawText("GAME OVER", 100, 180, 100, MAROON); DrawText("PRESS ENTER to RETRY!", 280, 280, 20, RED); } + // Draw screen light flash when passing through a tube if (superfx) { DrawRectangle(0, 0, screenWidth, screenHeight, GOLD); diff --git a/games/just_do/just_do.c b/games/just_do/just_do.c new file mode 100644 index 000000000..beac9e149 --- /dev/null +++ b/games/just_do/just_do.c @@ -0,0 +1,358 @@ +/******************************************************************************************* +* +* JUST DO - Global Game Jam 2015 Videogame +* Experimental puzzle game that lets the user try to find a logic solution to +* different shape-color-based situations. +* +* Developed by: Ramon Santamaria (Ray San) +* +* This game has been created using raylib (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* raylib - Copyright (c) 2015 Ramon Santamaria (Ray San - raysan@raysanweb.com) +* +********************************************************************************************/ + +#include "raylib.h" +#include "screens/screens.h" // NOTE: Defines currentScreen + +#if defined(PLATFORM_WEB) + #include +#endif + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- +const int screenWidth = 1280; // Moved to screens.h +const int screenHeight = 720; // Moved to screens.h + +// Required variables to manage screen transitions (fade-in, fade-out) +float transAlpha = 0; +bool onTransition = false; +bool transFadeOut = false; +int transFromScreen = -1; +int transToScreen = -1; +int framesCounter = 0; + +//static Sound levelWin; + +//---------------------------------------------------------------------------------- +// Local Functions Declaration +//---------------------------------------------------------------------------------- +void TransitionToScreen(int screen); +void UpdateTransition(void); +void DrawTransition(void); + +void UpdateDrawFrame(void); // Update and Draw one frame + +//---------------------------------------------------------------------------------- +// Main entry point +//---------------------------------------------------------------------------------- +int main(void) +{ + // Initialization + //--------------------------------------------------------- + const char windowTitle[30] = "JUST DO"; + + //SetupFlags(FLAG_FULLSCREEN_MODE); + InitWindow(screenWidth, screenHeight, windowTitle); + + // TODO: Load global data here (assets that must be available in all screens, i.e. fonts) + InitAudioDevice(); + + levelWin = LoadSound("resources/win.wav"); + + // Setup and Init first screen + currentScreen = LOGO; + InitLogoScreen(); + +#if defined(PLATFORM_WEB) + emscripten_set_main_loop(UpdateDrawFrame, 0, 1); +#else + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + + if (IsKeyPressed(KEY_SPACE)) PlaySound(levelWin); + + UpdateDrawFrame(); + } +#endif + + // De-Initialization + //-------------------------------------------------------------------------------------- + + // TODO: Unload all global loaded data (i.e. fonts) here! + UnloadSound(levelWin); + + CloseAudioDevice(); + + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +} + +//---------------------------------------------------------------------------------- +// Local Functions Definition +//---------------------------------------------------------------------------------- +void TransitionToScreen(int screen) +{ + onTransition = true; + transFromScreen = currentScreen; + transToScreen = screen; +} + +void UpdateTransition(void) +{ + if (!transFadeOut) + { + transAlpha += 0.02f; + + if (transAlpha >= 1.0) + { + transAlpha = 1.0; + currentScreen = transToScreen; + transFadeOut = true; + framesCounter = 0; + } + } + else // Transition fade out logic + { + transAlpha -= 0.02f; + + if (transAlpha <= 0) + { + transAlpha = 0; + transFadeOut = false; + onTransition = false; + transFromScreen = -1; + transToScreen = -1; + } + } +} + +void DrawTransition(void) +{ + DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(RAYWHITE, transAlpha)); +} + +void UpdateDrawFrame(void) +{ + // Update + //---------------------------------------------------------------------------------- + if (!onTransition) + { + if (IsKeyPressed('0')) + { + TransitionToScreen(LEVEL00); + InitLevel00Screen(); + } + else if (IsKeyPressed('1')) + { + TransitionToScreen(LEVEL01); + InitLevel01Screen(); + } + else if (IsKeyPressed('2')) + { + TransitionToScreen(LEVEL02); + InitLevel02Screen(); + } + else if (IsKeyPressed('3')) + { + TransitionToScreen(LEVEL03); + InitLevel03Screen(); + } + else if (IsKeyPressed('4')) + { + TransitionToScreen(LEVEL04); + InitLevel04Screen(); + } + else if (IsKeyPressed('5')) + { + TransitionToScreen(LEVEL05); + InitLevel05Screen(); + } + else if (IsKeyPressed('6')) + { + TransitionToScreen(LEVEL06); + InitLevel06Screen(); + } + else if (IsKeyPressed('7')) + { + TransitionToScreen(LEVEL07); + InitLevel07Screen(); + } + else if (IsKeyPressed('8')) + { + TransitionToScreen(LEVEL08); + InitLevel08Screen(); + } + else if (IsKeyPressed('9')) + { + TransitionToScreen(LEVEL09); + InitLevel08Screen(); + } + + switch(currentScreen) + { + case LOGO: + { + UpdateLogoScreen(); + + if (FinishLogoScreen()) + { + UnloadLogoScreen(); + TransitionToScreen(LEVEL00); + InitLevel00Screen(); + + PlayMusicStream("resources/ambient.ogg"); + SetMusicVolume(0.6f); + } + } break; + case LEVEL00: + { + UpdateLevel00Screen(); + + if (FinishLevel00Screen()) + { + UnloadLevel00Screen(); + TransitionToScreen(LEVEL01); + InitLevel01Screen(); + } + } break; + case LEVEL01: + { + UpdateLevel01Screen(); + + if (FinishLevel01Screen()) + { + UnloadLevel01Screen(); + TransitionToScreen(LEVEL02); + InitLevel02Screen(); + } + } break; + case LEVEL02: + { + UpdateLevel02Screen(); + + if (FinishLevel02Screen()) + { + UnloadLevel02Screen(); + TransitionToScreen(LEVEL03); + InitLevel03Screen(); + } + } break; + case LEVEL03: + { + UpdateLevel03Screen(); + + if (FinishLevel03Screen()) + { + UnloadLevel03Screen(); + TransitionToScreen(LEVEL04); + InitLevel04Screen(); + } + } break; + case LEVEL04: + { + UpdateLevel04Screen(); + + if (FinishLevel04Screen()) + { + UnloadLevel04Screen(); + TransitionToScreen(LEVEL05); + InitLevel05Screen(); + } + } break; + case LEVEL05: + { + UpdateLevel05Screen(); + + if (FinishLevel05Screen()) + { + UnloadLevel05Screen(); + TransitionToScreen(LEVEL06); + InitLevel06Screen(); + } + } break; + case LEVEL06: + { + UpdateLevel06Screen(); + + if (FinishLevel06Screen()) + { + UnloadLevel06Screen(); + TransitionToScreen(LEVEL07); + InitLevel07Screen(); + } + } break; + case LEVEL07: + { + UpdateLevel07Screen(); + + if (FinishLevel07Screen()) + { + UnloadLevel07Screen(); + TransitionToScreen(LEVEL08); + InitLevel08Screen(); + } + } break; + case LEVEL08: + { + UpdateLevel08Screen(); + + if (FinishLevel08Screen()) + { + UnloadLevel08Screen(); + TransitionToScreen(LEVEL09); + InitLevel09Screen(); + } + } break; + case LEVEL09: + { + UpdateLevel09Screen(); + + if (FinishLevel09Screen()) + { + UnloadLevel09Screen(); + TransitionToScreen(LEVEL00); + InitLevel00Screen(); + } + } break; + default: break; + } + } + else UpdateTransition(); // Update transition (fade-in, fade-out) + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + switch(currentScreen) + { + case LOGO: DrawLogoScreen(); break; + case LEVEL00: DrawLevel00Screen(); break; + case LEVEL01: DrawLevel01Screen(); break; + case LEVEL02: DrawLevel02Screen(); break; + case LEVEL03: DrawLevel03Screen(); break; + case LEVEL04: DrawLevel04Screen(); break; + case LEVEL05: DrawLevel05Screen(); break; + case LEVEL06: DrawLevel06Screen(); break; + case LEVEL07: DrawLevel07Screen(); break; + case LEVEL08: DrawLevel08Screen(); break; + case LEVEL09: DrawLevel09Screen(); break; + default: break; + } + + if (onTransition) DrawTransition(); + + EndDrawing(); + //---------------------------------------------------------------------------------- +} \ No newline at end of file diff --git a/games/just_do/makefile b/games/just_do/makefile new file mode 100644 index 000000000..4c36b154f --- /dev/null +++ b/games/just_do/makefile @@ -0,0 +1,246 @@ +#************************************************************************************************** +# +# raylib - Advance Game +# +# makefile to compile advance game for desktop platforms, Raspberry Pi and HTML5 (emscripten) +# +# Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 raylib platform to compile for +# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB +# WARNING: To compile to HTML5, code must be redesigned to use emscripten.h and emscripten_set_main_loop() +PLATFORM ?= PLATFORM_DESKTOP + +# determine PLATFORM_OS in case PLATFORM_DESKTOP selected +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + # No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows + ifeq ($(OS),Windows_NT) + PLATFORM_OS=WINDOWS + LIBPATH=win32 + else + UNAMEOS:=$(shell uname) + ifeq ($(UNAMEOS),Linux) + PLATFORM_OS=LINUX + LIBPATH=linux + else + ifeq ($(UNAMEOS),Darwin) + PLATFORM_OS=OSX + LIBPATH=osx + endif + endif + endif +endif + +# define compiler: gcc for C program, define as g++ for C++ +ifeq ($(PLATFORM),PLATFORM_WEB) + # define emscripten compiler + CC = emcc +else +ifeq ($(PLATFORM_OS),OSX) + # define llvm compiler for mac + CC = clang +else + # define default gcc compiler + CC = gcc +endif +endif + +# define compiler flags: +# -O2 defines optimization level +# -Wall turns on most, but not all, compiler warnings +# -std=c99 use standard C from 1999 revision +ifeq ($(PLATFORM),PLATFORM_RPI) + CFLAGS = -O2 -Wall -std=gnu99 -fgnu89-inline +else + CFLAGS = -O2 -Wall -std=c99 +endif +ifeq ($(PLATFORM),PLATFORM_WEB) + CFLAGS = -O1 -Wall -std=c99 -s USE_GLFW=3 + #-s ASSERTIONS=1 --preload-file resources + #-s ALLOW_MEMORY_GROWTH=1 # to allow memory resizing + #-s TOTAL_MEMORY=16777216 # to specify heap memory size (default = 16MB) +endif + +#CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes + +# define any directories containing required header files +ifeq ($(PLATFORM),PLATFORM_RPI) + INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads +else + INCLUDES = -I. -I../../src -I../../../src +# external libraries headers +# GLFW3 + INCLUDES += -I../../external/glfw3/include +# GLEW + INCLUDES += -I../../external/glew/include +# OpenAL Soft + INCLUDES += -I../../external/openal_soft/include +endif + +# define library paths containing required libs +ifeq ($(PLATFORM),PLATFORM_RPI) + LFLAGS = -L. -L../../src -L/opt/vc/lib +else + LFLAGS = -L. -L../../src -L../../../src + # external libraries to link with + # GLFW3 + LFLAGS += -L../../external/glfw3/lib/$(LIBPATH) + ifneq ($(PLATFORM_OS),OSX) + # OpenAL Soft + LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH) + # GLEW + LFLAGS += -L../../external/glew/lib/$(LIBPATH) + endif +endif + +# define any libraries to link into executable +# if you want to link libraries (libname.so or libname.a), use the -lname +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),LINUX) + # libraries for Debian GNU/Linux desktop compiling + # requires the following packages: + # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev + LIBS = -lraylib -lglfw -lGLEW -lGL -lopenal + endif + ifeq ($(PLATFORM_OS),OSX) + # libraries for OS X 10.9 desktop compiling + # requires the following packages: + # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev + LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa + else + # libraries for Windows desktop compiling + # NOTE: GLFW3 and OpenAL Soft libraries should be installed + LIBS = -lraylib -lglfw3 -lglew32 -lopengl32 -lopenal32 -lgdi32 + endif +endif +ifeq ($(PLATFORM),PLATFORM_RPI) + # libraries for Raspberry Pi compiling + # NOTE: OpenAL Soft library should be installed (libopenal1 package) + LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal +endif +ifeq ($(PLATFORM),PLATFORM_WEB) + LIBS = ../../src/libraylib.bc +endif + +# define additional parameters and flags for windows +ifeq ($(PLATFORM_OS),WINDOWS) + # resources file contains windows exe icon + # -Wl,--subsystem,windows hides the console window + WINFLAGS = ../../src/resources -Wl,--subsystem,windows +endif + +ifeq ($(PLATFORM),PLATFORM_WEB) + EXT = .html +endif + +# define all screen object files required +SCREENS = \ + screens/screen_logo.o \ + screens/screen_level00.o \ + screens/screen_level01.o \ + screens/screen_level02.o \ + screens/screen_level03.o \ + screens/screen_level04.o \ + screens/screen_level05.o \ + screens/screen_level06.o \ + screens/screen_level07.o \ + screens/screen_level08.o \ + screens/screen_level09.o \ + +# typing 'make' will invoke the first target entry in the file, +# in this case, the 'default' target entry is just_do +default: just_do + +# compile just_do +just_do: just_do.c $(SCREENS) + $(CC) -o $@$(EXT) $< $(SCREENS) $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) + +# compile screen LOGO +screens/screen_logo.o: screens/screen_logo.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen LEVEL00 +screens/screen_level00.o: screens/screen_level00.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen LEVEL01 +screens/screen_level01.o: screens/screen_level01.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen LEVEL02 +screens/screen_level02.o: screens/screen_level02.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen LEVEL03 +screens/screen_level03.o: screens/screen_level03.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen LEVEL04 +screens/screen_level04.o: screens/screen_level04.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen LEVEL05 +screens/screen_level05.o: screens/screen_level05.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen LEVEL06 +screens/screen_level06.o: screens/screen_level06.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen LEVEL07 +screens/screen_level07.o: screens/screen_level07.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen LEVEL08 +screens/screen_level08.o: screens/screen_level08.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile screen LEVEL09 +screens/screen_level09.o: screens/screen_level09.c + $(CC) -c $< -o $@ $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# clean everything +clean: +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),OSX) + find . -type f -perm +ugo+x -delete + rm -f *.o + else + ifeq ($(PLATFORM_OS),LINUX) + find . -type f -executable -delete + rm -f *.o + else + del *.o *.exe + endif + endif +endif +ifeq ($(PLATFORM),PLATFORM_RPI) + find . -type f -executable -delete + rm -f *.o +endif +ifeq ($(PLATFORM),PLATFORM_WEB) + del *.o *.html *.js +endif + @echo Cleaning done + +# instead of defining every module one by one, we can define a pattern +# this pattern below will automatically compile every module defined on $(OBJS) +#%.exe : %.c +# $(CC) -o $@ $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) diff --git a/games/just_do/resources/ambient.ogg b/games/just_do/resources/ambient.ogg new file mode 100644 index 000000000..af7f836ed Binary files /dev/null and b/games/just_do/resources/ambient.ogg differ diff --git a/games/just_do/resources/win.wav b/games/just_do/resources/win.wav new file mode 100644 index 000000000..72520f993 Binary files /dev/null and b/games/just_do/resources/win.wav differ diff --git a/games/just_do/screens/screen_level00.c b/games/just_do/screens/screen_level00.c new file mode 100644 index 000000000..99f298492 --- /dev/null +++ b/games/just_do/screens/screen_level00.c @@ -0,0 +1,167 @@ +/********************************************************************************************** +* +* raylib - Standard Game template +* +* Level00 Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 "raylib.h" +#include "screens.h" + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Level00 screen global variables +static int framesCounter; +static int finishScreen; + +static Rectangle boundsU, boundsO; + +static bool mouseOverU = false; +static bool mouseOverO = false; +static bool placedU = false; +static bool placedO = false; + +static bool done = false; +static int levelTimeSec = 0; +static bool levelFinished = false; + +//---------------------------------------------------------------------------------- +// Level00 Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Level00 Screen Initialization logic +void InitLevel00Screen(void) +{ + // Initialize Level00 screen variables here! + framesCounter = 0; + finishScreen = 0; + + boundsU = (Rectangle){GetScreenWidth()/2 - 265, -200, MeasureText("U", 160) + 40, 160 }; + boundsO = (Rectangle){GetScreenWidth() - 370, -30, MeasureText("O", 160) + 40, 160 }; +} + +// Level00 Screen Update logic +void UpdateLevel00Screen(void) +{ + // Update Level00 screen variables here! + if (!done) framesCounter++; + + if (!done) + { + if (!placedU) boundsU.y += 2; + + if (boundsU.y >= GetScreenHeight()) boundsU.y = -boundsU.height; + + Vector2 mousePos = GetMousePosition(); + + if (CheckCollisionPointRec(mousePos, boundsU)) + { + mouseOverU = true; + + if (!placedU && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + if ((boundsU.y > GetScreenHeight()/2 - 110) && ((boundsU.y + boundsU.height) < (GetScreenHeight()/2 + 100))) + { + placedU = true; + } + } + } + else mouseOverU = false; + + if (CheckCollisionPointRec(mousePos, boundsO)) + { + mouseOverO = true; + + if (!placedO && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) boundsO.y += 100; + + if (boundsO.y >= (GetScreenHeight()/2 - 130)) placedO = true; + } + else mouseOverO = false; + + if (placedO && placedU) + { + done = true; + PlaySound(levelWin); + } + } + + if (done && !levelFinished) + { + levelTimeSec = framesCounter/60; + levelFinished = true; + framesCounter = 0; + } + + if (levelFinished) + { + framesCounter++; + + if ((framesCounter > 30) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true; + } +} + +// Level00 Screen Draw logic +void DrawLevel00Screen(void) +{ + // Draw Level00 screen + DrawText("U", boundsU.x, boundsU.y + 10, 160, GRAY); + DrawText("J", GetScreenWidth()/2 - MeasureText("JUST DO", 160)/2, GetScreenHeight()/2 - 80, 160, GRAY); + DrawText("ST D", GetScreenWidth()/2 - MeasureText("JUST DO", 160)/2 + 210, GetScreenHeight()/2 - 80, 160, GRAY); + DrawText("O", boundsO.x, boundsO.y + 10, 160, GRAY); + + DrawText("by RAMON SANTAMARIA (@raysan5)", 370, GetScreenHeight()/2 + 100, 30, Fade(LIGHTGRAY, 0.4f)); + + if (mouseOverU && !placedU) DrawRectangleLines(boundsU.x - 20, boundsU.y, boundsU.width, boundsU.height, Fade(LIGHTGRAY, 0.8f)); + //DrawRectangleBordersRec(boundsU, -20, 0, 20, Fade(RED, 0.3f)); + + if (mouseOverO && !placedO) DrawRectangleLines(boundsO.x - 20, boundsO.y, boundsO.width, boundsO.height, Fade(LIGHTGRAY, 0.8f)); + //DrawRectangleBordersRec(boundsO, -20, 0, 20, Fade(RED, 0.3f)); + + if (levelFinished) + { + DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f)); + DrawText("LEVEL 00", GetScreenWidth()/2 - MeasureText("LEVEL 00", 30)/2, 20, 30, GRAY); + DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY); + } + else DrawText("LEVEL 00", GetScreenWidth()/2 - MeasureText("LEVEL 00", 30)/2, 20, 30, LIGHTGRAY); +} + +// Level00 Screen Unload logic +void UnloadLevel00Screen(void) +{ + // TODO: Unload Level00 screen variables here! +} + +// Level00 Screen should finish? +int FinishLevel00Screen(void) +{ + return finishScreen; +} + +void DrawRectangleBordersRec(Rectangle rec, int offsetX, int offsetY, int borderSize, Color col) +{ + DrawRectangle(rec.x + offsetX, rec.y + offsetY, rec.width, borderSize, col); + DrawRectangle(rec.x + offsetX, rec.y + borderSize + offsetY, borderSize, rec.height - borderSize*2, col); + DrawRectangle(rec.x + rec.width - borderSize + offsetX, rec.y + borderSize + offsetY, borderSize, rec.height - borderSize*2, col); + DrawRectangle(rec.x + offsetX, rec.y + rec.height - borderSize + offsetY, rec.width, borderSize, col); +} \ No newline at end of file diff --git a/games/just_do/screens/screen_level01.c b/games/just_do/screens/screen_level01.c new file mode 100644 index 000000000..cedcb2e0c --- /dev/null +++ b/games/just_do/screens/screen_level01.c @@ -0,0 +1,163 @@ +/********************************************************************************************** +* +* raylib - Standard Game template +* +* Level01 Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 "raylib.h" +#include "screens.h" + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Level01 screen global variables +static int framesCounter; +static int finishScreen; + +static Rectangle innerLeftRec, outerLeftRec; +static Rectangle innerRightRec, outerRightRec; + +static bool done = false; +static int levelTimeSec = 0; +static bool levelFinished = false; + +//---------------------------------------------------------------------------------- +// Level01 Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Level01 Screen Initialization logic +void InitLevel01Screen(void) +{ + // Initialize Level01 screen variables here! + framesCounter = 0; + finishScreen = 0; + + outerLeftRec = (Rectangle){ 0, 0, GetScreenWidth()/2, GetScreenHeight() }; + outerRightRec = (Rectangle){ GetScreenWidth()/2, 0, GetScreenWidth()/2, GetScreenHeight() }; + + innerLeftRec = (Rectangle){ GetScreenWidth()/4 - 200, GetScreenHeight()/2 - 200, 400, 400}; + innerRightRec = (Rectangle){ GetScreenWidth()/2 + GetScreenWidth()/4 - 200, GetScreenHeight()/2 - 200, 400, 400}; +} + +// Level01 Screen Update logic +void UpdateLevel01Screen(void) +{ + // Update Level01 screen + framesCounter++; + + if (!done) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + if (CheckCollisionPointRec(GetMousePosition(), innerLeftRec)) + { + if (innerRightRec.width > 0) + { + innerRightRec.x += 20; + innerRightRec.y += 20; + innerRightRec.width -= 40; + innerRightRec.height -= 40; + } + } + else if (CheckCollisionPointRec(GetMousePosition(), innerRightRec)) + { + if (innerLeftRec.width > 0) + { + innerLeftRec.x += 20; + innerLeftRec.y += 20; + innerLeftRec.width -= 40; + innerLeftRec.height -= 40; + } + } + else if (CheckCollisionPointRec(GetMousePosition(), outerLeftRec)) + { + innerLeftRec.x -= 20; + innerLeftRec.y -= 20; + innerLeftRec.width += 40; + innerLeftRec.height += 40; + } + else if (CheckCollisionPointRec(GetMousePosition(), outerRightRec)) + { + innerRightRec.x -= 20; + innerRightRec.y -= 20; + innerRightRec.width += 40; + innerRightRec.height += 40; + } + } + + + if (((innerRightRec.width == 0) && (innerLeftRec.height >= GetScreenHeight())) || + ((innerLeftRec.width == 0) && (innerRightRec.height >= GetScreenHeight()))) + { + done = true; + PlaySound(levelWin); + } + } + + if (done && !levelFinished) + { + levelTimeSec = framesCounter/60; + levelFinished = true; + framesCounter = 0; + } + + if (levelFinished) + { + framesCounter++; + + if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true; + } +} + +// Level01 Screen Draw logic +void DrawLevel01Screen(void) +{ + // Draw Level01 screen + if (!levelFinished) DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), LIGHTGRAY); + else DrawRectangle(60, 60, GetScreenWidth() - 120, GetScreenHeight() - 120, LIGHTGRAY); + + DrawRectangleRec(outerLeftRec, GRAY); + DrawRectangleRec(innerLeftRec, RAYWHITE); + DrawRectangleRec(outerRightRec, RAYWHITE); + DrawRectangleRec(innerRightRec, GRAY); + + if (levelFinished) + { + DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f)); + DrawText("LEVEL 01", GetScreenWidth()/2 - MeasureText("LEVEL 01", 30)/2, 20, 30, GRAY); + DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY); + } + else DrawText("LEVEL 01", GetScreenWidth()/2 - MeasureText("LEVEL 01", 30)/2, 20, 30, LIGHTGRAY); +} + +// Level01 Screen Unload logic +void UnloadLevel01Screen(void) +{ + // TODO: Unload Level01 screen variables here! +} + +// Level01 Screen should finish? +int FinishLevel01Screen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/just_do/screens/screen_level02.c b/games/just_do/screens/screen_level02.c new file mode 100644 index 000000000..ccfa355e8 --- /dev/null +++ b/games/just_do/screens/screen_level02.c @@ -0,0 +1,170 @@ +/********************************************************************************************** +* +* raylib - Standard Game template +* +* Level02 Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 "raylib.h" +#include "screens.h" + +#include + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Level02 screen global variables +static int framesCounter; +static int finishScreen; + +static Vector2 bouncingBallPos; +static float bouncingBallRadius = 40; +static Vector2 bouncingBallSpeed; + +static Vector2 holeCirclePos; +static float holeCircleRadius = 50; + +static bool ballOnHole = false; + +static int levelTimeSec = 0; +static bool levelFinished = false; + +//---------------------------------------------------------------------------------- +// Level02 Screen Functions Definition +//---------------------------------------------------------------------------------- +float Vector2Distance(Vector2 v1, Vector2 v2); + +// Level02 Screen Initialization logic +void InitLevel02Screen(void) +{ + // TODO: Initialize Level02 screen variables here! + framesCounter = 0; + finishScreen = 0; + + bouncingBallPos = (Vector2){ 120, 80 }; + bouncingBallSpeed = (Vector2){ 6, 8 }; + holeCirclePos = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 }; +} + +// Level02 Screen Update logic +void UpdateLevel02Screen(void) +{ + // Update Level02 screen + framesCounter++; + + if (!ballOnHole) + { + bouncingBallPos.x += bouncingBallSpeed.x; + bouncingBallPos.y += bouncingBallSpeed.y; + + if (((bouncingBallPos.x - bouncingBallRadius) <= 0) || ((bouncingBallPos.x + bouncingBallRadius) >= GetScreenWidth())) bouncingBallSpeed.x *= -1; + if (((bouncingBallPos.y - bouncingBallRadius) <= 0) || ((bouncingBallPos.y + bouncingBallRadius) >= GetScreenHeight())) bouncingBallSpeed.y *= -1; + + Vector2 mousePos = GetMousePosition(); + + if (CheckCollisionPointCircle(mousePos, bouncingBallPos, 120)) + { + bouncingBallPos.x = GetRandomValue(80, 1200); + bouncingBallPos.y = GetRandomValue(80, 650); + } + + if (CheckCollisionPointCircle(mousePos, holeCirclePos, 120)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + holeCirclePos = mousePos; + + if ((holeCirclePos.x - holeCircleRadius) <= 0) holeCirclePos.x = holeCircleRadius; + else if ((holeCirclePos.x + holeCircleRadius) >= GetScreenWidth()) holeCirclePos.x = GetScreenWidth() - holeCircleRadius; + + if ((holeCirclePos.y - holeCircleRadius) <= 0) holeCirclePos.y = holeCircleRadius; + else if ((holeCirclePos.y + holeCircleRadius) >= GetScreenHeight()) holeCirclePos.y = GetScreenHeight() - holeCircleRadius; + } + } + + if (Vector2Distance(bouncingBallPos, holeCirclePos) < 20) + { + ballOnHole = true; + PlaySound(levelWin); + } + } + + if (ballOnHole && !levelFinished) + { + levelTimeSec = framesCounter/60; + levelFinished = true; + framesCounter = 0; + } + + if (levelFinished) + { + framesCounter++; + + if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true; + } +} + +// Level02 Screen Draw logic +void DrawLevel02Screen(void) +{ + // Draw Level02 screen + + DrawCircleV(holeCirclePos, holeCircleRadius, LIGHTGRAY); + DrawCircleV(bouncingBallPos, bouncingBallRadius, DARKGRAY); + + DrawCircleLines(bouncingBallPos.x, bouncingBallPos.y, 120, Fade(LIGHTGRAY, 0.8f)); + + + + if (levelFinished) + { + DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f)); + DrawText("LEVEL 02", GetScreenWidth()/2 - MeasureText("LEVEL 02", 30)/2, 20, 30, GRAY); + DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY); + } + else DrawText("LEVEL 02", GetScreenWidth()/2 - MeasureText("LEVEL 02", 30)/2, 20, 30, LIGHTGRAY); +} + +// Level02 Screen Unload logic +void UnloadLevel02Screen(void) +{ + // TODO: Unload Level02 screen variables here! +} + +// Level02 Screen should finish? +int FinishLevel02Screen(void) +{ + return finishScreen; +} + +// Calculate distance between two points +float Vector2Distance(Vector2 v1, Vector2 v2) +{ + float result; + + float dx = v2.x - v1.x; + float dy = v2.y - v1.y; + + result = sqrt(dx*dx + dy*dy); + + return result; +} \ No newline at end of file diff --git a/games/just_do/screens/screen_level03.c b/games/just_do/screens/screen_level03.c new file mode 100644 index 000000000..e87324149 --- /dev/null +++ b/games/just_do/screens/screen_level03.c @@ -0,0 +1,134 @@ +/********************************************************************************************** +* +* raylib - Standard Game template +* +* Level03 Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 "raylib.h" +#include "screens.h" + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Level03 screen global variables +static int framesCounter; +static int finishScreen; + +static Rectangle holeRec, pieceRec; +static bool showPiece = false; +static bool pieceSelected = false; + +static bool done = false; +static int levelTimeSec = 0; +static bool levelFinished = false; + +//---------------------------------------------------------------------------------- +// Level03 Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Level03 Screen Initialization logic +void InitLevel03Screen(void) +{ + // Initialize Level03 screen variables here! + framesCounter = 0; + finishScreen = 0; + + holeRec = (Rectangle){ GetScreenWidth()/2 - 50, GetScreenHeight()/2 - 50, 100, 100 }; + pieceRec = (Rectangle){ 200, 400, 100, 100 }; +} + +// Level03 Screen Update logic +void UpdateLevel03Screen(void) +{ + // Update Level03 screen variables here! + framesCounter++; + + Vector2 mousePos = GetMousePosition(); + + if (!done) + { + if (CheckCollisionPointRec(mousePos, holeRec)) showPiece = true; + else showPiece = false; + + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CheckCollisionPointRec(mousePos, pieceRec)) + { + pieceSelected = true; + + pieceRec.x = ((int)mousePos.x - 50); + pieceRec.y = ((int)mousePos.y - 50); + } + } + + if ((pieceRec.x == holeRec.x) && !(CheckCollisionPointRec(mousePos, holeRec))) + { + done = true; + PlaySound(levelWin); + } + } + + if (done && !levelFinished) + { + levelTimeSec = framesCounter/60; + levelFinished = true; + framesCounter = 0; + } + + if (levelFinished) + { + framesCounter++; + + if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true; + } +} + +// Level03 Screen Draw logic +void DrawLevel03Screen(void) +{ + // Draw Level03 screen + DrawRectangleRec(holeRec, GRAY); + DrawRectangleRec(pieceRec, RAYWHITE); + + if (showPiece) DrawRectangleLines(pieceRec.x, pieceRec.y, pieceRec.width, pieceRec.height, Fade(LIGHTGRAY, 0.8f)); + + if (levelFinished) + { + DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f)); + DrawText("LEVEL 03", GetScreenWidth()/2 - MeasureText("LEVEL 03", 30)/2, 20, 30, GRAY); + DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY); + } + else DrawText("LEVEL 03", GetScreenWidth()/2 - MeasureText("LEVEL 03", 30)/2, 20, 30, LIGHTGRAY); +} + +// Level03 Screen Unload logic +void UnloadLevel03Screen(void) +{ + // TODO: Unload Level03 screen variables here! +} + +// Level03 Screen should finish? +int FinishLevel03Screen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/just_do/screens/screen_level04.c b/games/just_do/screens/screen_level04.c new file mode 100644 index 000000000..c4e4e2c00 --- /dev/null +++ b/games/just_do/screens/screen_level04.c @@ -0,0 +1,147 @@ +/********************************************************************************************** +* +* raylib - Standard Game template +* +* Level04 Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 "raylib.h" +#include "screens.h" + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Level04 screen global variables +static int framesCounter; +static int finishScreen; + +static Vector2 circlesCenter; +static float innerCircleRadius = 40; +static float outerCircleRadius = 300; + +static bool done = false; +static int levelTimeSec = 0; +static bool levelFinished = false; + +//---------------------------------------------------------------------------------- +// Level04 Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Level04 Screen Initialization logic +void InitLevel04Screen(void) +{ + // Initialize Level04 screen variables here! + framesCounter = 0; + finishScreen = 0; + + circlesCenter = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 }; +} + +// Level04 Screen Update logic +void UpdateLevel04Screen(void) +{ + // Update Level04 screen variables here! + framesCounter++; + + if (!done) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CheckCollisionPointCircle(GetMousePosition(), circlesCenter, innerCircleRadius)) + { + innerCircleRadius += 2; + } + else if (CheckCollisionPointCircle(GetMousePosition(), circlesCenter, outerCircleRadius)) + { + outerCircleRadius += 2; + } + else + { + outerCircleRadius -= 2; + + if (outerCircleRadius <= 260) outerCircleRadius = 260; + } + } + else + { + if (!done) + { + innerCircleRadius -= 2; + if (outerCircleRadius > 300) outerCircleRadius -= 2; + } + } + + if (innerCircleRadius >= 270) innerCircleRadius = 270; + else if (innerCircleRadius <= 40) innerCircleRadius = 40; + + if (outerCircleRadius >= 600) outerCircleRadius = 600; + + if (innerCircleRadius >= outerCircleRadius) + { + done = true; + PlaySound(levelWin); + } + } + + if (done && !levelFinished) + { + levelTimeSec = framesCounter/60; + levelFinished = true; + framesCounter = 0; + } + + if (levelFinished) + { + framesCounter++; + + if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true; + } +} + +// Level04 Screen Draw logic +void DrawLevel04Screen(void) +{ + // Draw Level04 screen here! + //DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), GRAY); + DrawCircleV(circlesCenter, outerCircleRadius, GRAY); + DrawCircleV(circlesCenter, innerCircleRadius, RAYWHITE); + + if (levelFinished) + { + DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f)); + DrawText("LEVEL 04", GetScreenWidth()/2 - MeasureText("LEVEL 04", 30)/2, 20, 30, GRAY); + DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY); + } + else DrawText("LEVEL 04", GetScreenWidth()/2 - MeasureText("LEVEL 04", 30)/2, 20, 30, LIGHTGRAY); +} + +// Level04 Screen Unload logic +void UnloadLevel04Screen(void) +{ + // TODO: Unload Level04 screen variables here! +} + +// Level04 Screen should finish? +int FinishLevel04Screen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/just_do/screens/screen_level05.c b/games/just_do/screens/screen_level05.c new file mode 100644 index 000000000..f2e4d852a --- /dev/null +++ b/games/just_do/screens/screen_level05.c @@ -0,0 +1,185 @@ +/********************************************************************************************** +* +* raylib - Standard Game template +* +* Level05 Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 "raylib.h" +#include "screens.h" + +#define NUM_CIRCLES 10 + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Level05 screen global variables +static int framesCounter; +static int finishScreen; + +static Vector2 circleCenter; +static float circleRadius[NUM_CIRCLES]; +static bool circleLocked[NUM_CIRCLES]; +static Color circleColor[NUM_CIRCLES]; + +static bool done = false; +static int levelTimeSec = 0; +static bool levelFinished = false; + +//---------------------------------------------------------------------------------- +// Level05 Screen Functions Definition +//---------------------------------------------------------------------------------- +static bool CheckColor(Color col1, Color col2); + +// Level05 Screen Initialization logic +void InitLevel05Screen(void) +{ + // Initialize Level05 screen variables here! + framesCounter = 0; + finishScreen = 0; + + circleCenter = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 }; + + for (int i = 0; i < NUM_CIRCLES; i++) + { + circleRadius[i] = 760/NUM_CIRCLES*(NUM_CIRCLES - i); + circleLocked[i] = false; + } + + // That's a dirty hack to give sonme coherence to this puzzle... + circleColor[9] = GRAY; + circleColor[8] = RAYWHITE; + circleColor[7] = RAYWHITE; + circleColor[6] = GRAY; + circleColor[5] = RAYWHITE; + circleColor[4] = GRAY; + circleColor[3] = GRAY; + circleColor[2] = GRAY; + circleColor[1] = RAYWHITE; + circleColor[0] = GRAY; +} + +// Level05 Screen Update logic +void UpdateLevel05Screen(void) +{ + // Update Level05 screen variables here! + framesCounter++; + + if (!done) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + for (int i = NUM_CIRCLES - 1; i >= 0; i--) + { + if (CheckCollisionPointCircle(GetMousePosition(), circleCenter, circleRadius[i])) + { + if (i == 0) + { + if (CheckColor(circleColor[8], GRAY)) circleColor[8] = RAYWHITE; + else circleColor[8] = GRAY; + } + else if (i == 2) + { + if (CheckColor(circleColor[5], GRAY)) circleColor[5] = RAYWHITE; + else circleColor[5] = GRAY; + } + else if (i == 3) + { + if (CheckColor(circleColor[6], GRAY)) circleColor[6] = RAYWHITE; + else circleColor[6] = GRAY; + } + else + { + if (CheckColor(circleColor[i], GRAY)) circleColor[i] = RAYWHITE; + else circleColor[i] = GRAY; + } + return; + } + } + } + + // Check all cicles done + for (int i = 0; i < NUM_CIRCLES; i++) + { + done = true; + + if (CheckColor(circleColor[i], RAYWHITE)) + { + done = false; + return; + } + + //if (done) PlaySound(levelWin); + } + } + + if (done && !levelFinished) + { + levelTimeSec = framesCounter/60; + levelFinished = true; + framesCounter = 0; + } + + if (levelFinished) + { + framesCounter++; + + if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true; + } +} + +// Level05 Screen Draw logic +void DrawLevel05Screen(void) +{ + // Draw Level05 screen + for (int i = 0; i < NUM_CIRCLES; i++) + { + DrawPoly(circleCenter, 64, circleRadius[i], 0.0f, circleColor[i]); + } + + + + if (levelFinished) + { + DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f)); + DrawText("LEVEL 05", GetScreenWidth()/2 - MeasureText("LEVEL 05", 30)/2, 20, 30, GRAY); + DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY); + } + else DrawText("LEVEL 05", GetScreenWidth()/2 - MeasureText("LEVEL 05", 30)/2, 20, 30, LIGHTGRAY); +} + +// Level05 Screen Unload logic +void UnloadLevel05Screen(void) +{ + // TODO: Unload Level05 screen variables here! +} + +// Level05 Screen should finish? +int FinishLevel05Screen(void) +{ + return finishScreen; +} + +static bool CheckColor(Color col1, Color col2) +{ + return ((col1.r == col2.r) && (col1.g == col2.g) && (col1.b == col2.b) && (col1.a == col2.a)); +} \ No newline at end of file diff --git a/games/just_do/screens/screen_level06.c b/games/just_do/screens/screen_level06.c new file mode 100644 index 000000000..b5881db41 --- /dev/null +++ b/games/just_do/screens/screen_level06.c @@ -0,0 +1,156 @@ +/********************************************************************************************** +* +* raylib - Standard Game template +* +* Level06 Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 "raylib.h" +#include "screens.h" + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Level06 screen global variables +static int framesCounter; +static int finishScreen; + +static Rectangle centerRec; + +static Rectangle movingRecs[4]; +static int speedRecs[4]; +static bool stoppedRec[4]; +static int mouseOverNum = -1; + +static bool done = false; +static int levelTimeSec = 0; +static bool levelFinished = false; + +//---------------------------------------------------------------------------------- +// Level06 Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Level06 Screen Initialization logic +void InitLevel06Screen(void) +{ + // Initialize Level06 screen variables here! + framesCounter = 0; + finishScreen = 0; + + centerRec = (Rectangle){ GetScreenWidth()/2 - 100, 0, 200, GetScreenHeight() }; + + for (int i = 0; i < 4; i++) + { + movingRecs[i] = (Rectangle){ GetRandomValue(0, 5)*150, (i*150) + 90, 100, 100 }; + stoppedRec[i] = false; + speedRecs[i] = GetRandomValue(4, 8); + } +} + +// Level06 Screen Update logic +void UpdateLevel06Screen(void) +{ + // Update Level06 screen variables here! + framesCounter++; + + if (!done) + { + for (int i = 0; i < 4; i++) + { + if (!stoppedRec[i]) movingRecs[i].x += speedRecs[i]; + + if (movingRecs[i].x >= GetScreenWidth()) movingRecs[i].x = -movingRecs[i].width; + + if (CheckCollisionPointRec(GetMousePosition(), movingRecs[i])) + { + mouseOverNum = i; + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + if (i == 0) stoppedRec[3] = !stoppedRec[3]; + else if (i == 1) stoppedRec[2] = !stoppedRec[2]; + else if (i == 2) stoppedRec[0] = !stoppedRec[0]; + else if (i == 3) stoppedRec[1] = !stoppedRec[1]; + } + } + } + + // Check if all boxes are aligned + if (((movingRecs[0].x > centerRec.x) && ((movingRecs[0].x + movingRecs[0].width) < (centerRec.x + centerRec.width))) && + ((movingRecs[1].x > centerRec.x) && ((movingRecs[1].x + movingRecs[1].width) < (centerRec.x + centerRec.width))) && + ((movingRecs[2].x > centerRec.x) && ((movingRecs[2].x + movingRecs[2].width) < (centerRec.x + centerRec.width))) && + ((movingRecs[3].x > centerRec.x) && ((movingRecs[3].x + movingRecs[3].width) < (centerRec.x + centerRec.width)))) + { + done = true; + PlaySound(levelWin); + } + } + + + if (done && !levelFinished) + { + levelTimeSec = framesCounter/60; + levelFinished = true; + framesCounter = 0; + } + + if (levelFinished) + { + framesCounter++; + + if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true; + } +} + +// Level06 Screen Draw logic +void DrawLevel06Screen(void) +{ + // Draw Level06 screen + DrawRectangleRec(centerRec, LIGHTGRAY); + + for (int i = 0; i < 4; i++) + { + DrawRectangleRec(movingRecs[i], GRAY); + } + + if (!done & (mouseOverNum >= 0)) DrawRectangleLines(movingRecs[mouseOverNum].x - 5, movingRecs[mouseOverNum].y - 5, movingRecs[mouseOverNum].width + 10, movingRecs[mouseOverNum].height + 10, Fade(LIGHTGRAY, 0.8f)); + + if (levelFinished) + { + DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f)); + DrawText("LEVEL 06", GetScreenWidth()/2 - MeasureText("LEVEL 06", 30)/2, 20, 30, GRAY); + DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY); + } + else DrawText("LEVEL 06", GetScreenWidth()/2 - MeasureText("LEVEL 06", 30)/2, 20, 30, LIGHTGRAY); +} + +// Level06 Screen Unload logic +void UnloadLevel06Screen(void) +{ + // TODO: Unload Level06 screen variables here! +} + +// Level06 Screen should finish? +int FinishLevel06Screen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/just_do/screens/screen_level07.c b/games/just_do/screens/screen_level07.c new file mode 100644 index 000000000..d305b0255 --- /dev/null +++ b/games/just_do/screens/screen_level07.c @@ -0,0 +1,178 @@ +/********************************************************************************************** +* +* raylib - Standard Game template +* +* Level07 Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 "raylib.h" +#include "screens.h" + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Level07 screen global variables +static int framesCounter; +static int finishScreen; + +static Vector2 leftCirclePos, middleCirclePos, rightCirclePos; +static Vector2 leftBtnPos, middleBtnPos, rightBtnPos; +static float circleRadius = 100; +static float btnRadius = 80; + +static bool leftCircleActive, middleCircleActive, rightCircleActive; +static Color leftCircleColor, middleCircleColor, rightCircleColor; + +static bool done = false; +static int levelTimeSec = 0; +static bool levelFinished = false; + +//---------------------------------------------------------------------------------- +// Level07 Screen Functions Definition +//---------------------------------------------------------------------------------- +static bool CheckColor(Color col1, Color col2); + +// Level07 Screen Initialization logic +void InitLevel07Screen(void) +{ + // Initialize Level07 screen variables here! + framesCounter = 0; + finishScreen = 0; + + leftCirclePos = (Vector2){ GetScreenWidth()/2 - 340, GetScreenHeight()/2 - 100 }; + middleCirclePos = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 - 100 }; + rightCirclePos = (Vector2){ GetScreenWidth()/2 + 340, GetScreenHeight()/2 - 100 }; + + leftBtnPos = (Vector2){ GetScreenWidth()/2 - 340, GetScreenHeight()/2 + 120 }; + middleBtnPos = (Vector2){ GetScreenWidth()/2, GetScreenHeight()/2 + 120 }; + rightBtnPos = (Vector2){ GetScreenWidth()/2 + 340, GetScreenHeight()/2 + 120 }; + + leftCircleActive = false; + middleCircleActive = true; + rightCircleActive = false; + + leftCircleColor = GRAY; + middleCircleColor = GRAY; + rightCircleColor = GRAY; +} + +// Level07 Screen Update logic +void UpdateLevel07Screen(void) +{ + // Update Level07 screen variables here! + framesCounter++; + + if (!done) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + if (CheckCollisionPointCircle(GetMousePosition(), leftBtnPos, btnRadius)) leftCircleActive = !leftCircleActive; + else if (CheckCollisionPointCircle(GetMousePosition(), middleBtnPos, btnRadius)) middleCircleActive = !middleCircleActive; + else if (CheckCollisionPointCircle(GetMousePosition(), rightBtnPos, btnRadius)) rightCircleActive = !rightCircleActive; + + if (rightCircleActive && CheckCollisionPointCircle(GetMousePosition(), leftCirclePos, circleRadius)) + { + if (CheckColor(leftCircleColor, GRAY)) leftCircleColor = LIGHTGRAY; + else leftCircleColor = GRAY; + } + + if (middleCircleActive && CheckCollisionPointCircle(GetMousePosition(), middleCirclePos, circleRadius)) + { + if (CheckColor(middleCircleColor, GRAY)) middleCircleColor = LIGHTGRAY; + else middleCircleColor = GRAY; + } + + if (rightCircleActive && leftCircleActive && CheckCollisionPointCircle(GetMousePosition(), rightCirclePos, circleRadius)) + { + if (CheckColor(rightCircleColor, GRAY)) rightCircleColor = LIGHTGRAY; + else rightCircleColor = GRAY; + } + } + + // Check all cicles done + if (CheckColor(leftCircleColor, LIGHTGRAY) && CheckColor(middleCircleColor, LIGHTGRAY) && CheckColor(rightCircleColor, LIGHTGRAY) && + !leftCircleActive && !middleCircleActive && !rightCircleActive) + { + done = true; + PlaySound(levelWin); + } + } + + if (done && !levelFinished) + { + levelTimeSec = framesCounter/60; + levelFinished = true; + framesCounter = 0; + } + + if (levelFinished) + { + framesCounter++; + + if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true; + } +} + +// Level07 Screen Draw logic +void DrawLevel07Screen(void) +{ + // Draw Level07 screen here! + DrawCircleV(leftCirclePos, circleRadius, leftCircleColor); + DrawCircleV(middleCirclePos, circleRadius, middleCircleColor); + DrawCircleV(rightCirclePos, circleRadius, rightCircleColor); + + if (leftCircleActive) DrawCircleV(leftBtnPos, btnRadius, GRAY); + else DrawCircleV(leftBtnPos, btnRadius, LIGHTGRAY); + + if (middleCircleActive) DrawCircleV(middleBtnPos, btnRadius, GRAY); + else DrawCircleV(middleBtnPos, btnRadius, LIGHTGRAY); + + if (rightCircleActive) DrawCircleV(rightBtnPos, btnRadius, GRAY); + else DrawCircleV(rightBtnPos, btnRadius, LIGHTGRAY); + + + + if (levelFinished) + { + DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f)); + DrawText("LEVEL 07", GetScreenWidth()/2 - MeasureText("LEVEL 07", 30)/2, 20, 30, GRAY); + DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY); + } + else DrawText("LEVEL 07", GetScreenWidth()/2 - MeasureText("LEVEL 07", 30)/2, 20, 30, LIGHTGRAY); +} + +// Level07 Screen Unload logic +void UnloadLevel07Screen(void) +{ + // TODO: Unload Level07 screen variables here! +} + +// Level07 Screen should finish? +int FinishLevel07Screen(void) +{ + return finishScreen; +} + +static bool CheckColor(Color col1, Color col2) +{ + return ((col1.r == col2.r) && (col1.g == col2.g) && (col1.b == col2.b) && (col1.a == col2.a)); +} \ No newline at end of file diff --git a/games/just_do/screens/screen_level08.c b/games/just_do/screens/screen_level08.c new file mode 100644 index 000000000..4cb0443be --- /dev/null +++ b/games/just_do/screens/screen_level08.c @@ -0,0 +1,157 @@ +/********************************************************************************************** +* +* raylib - Standard Game template +* +* Level08 Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 "raylib.h" +#include "screens.h" + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Level08 screen global variables +static int framesCounter; +static int finishScreen; + +static Rectangle leftColumnRec, middleColumnRec, rightColumnRec; +static Rectangle movingBox; +static int moveSpeed = 4; + +static bool leftColumnActive, middleColumnActive, rightColumnActive; + +static bool done = false; +static int levelTimeSec = 0; +static bool levelFinished = false; + +//---------------------------------------------------------------------------------- +// Level08 Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Level08 Screen Initialization logic +void InitLevel08Screen(void) +{ + // TODO: Initialize Level08 screen variables here! + framesCounter = 0; + finishScreen = 0; + + movingBox = (Rectangle){ 20, GetScreenHeight()/2 - 20, 40, 40 }; + + leftColumnRec = (Rectangle){ 240, 0, 100, GetScreenHeight() }; + middleColumnRec = (Rectangle){ GetScreenWidth()/2 - 50, 0, 100, GetScreenHeight() }; + rightColumnRec = (Rectangle){ 920, 0, 100, GetScreenHeight() }; + + leftColumnActive = true; + middleColumnActive = false; + rightColumnActive = true; +} + +// Level08 Screen Update logic +void UpdateLevel08Screen(void) +{ + // Update Level08 screen variables here! + framesCounter++; + + if (!done) + { + movingBox.x += moveSpeed; + + if (movingBox.x <= 0) moveSpeed *= -1; + + if ((leftColumnActive && (CheckCollisionRecs(leftColumnRec, movingBox))) || + (middleColumnActive && (CheckCollisionRecs(middleColumnRec, movingBox))) || + (rightColumnActive && (CheckCollisionRecs(rightColumnRec, movingBox)))) moveSpeed *= -1; + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + if (CheckCollisionPointRec(GetMousePosition(), leftColumnRec)) + { + middleColumnActive = false; + rightColumnActive = true; + } + else if (CheckCollisionPointRec(GetMousePosition(), middleColumnRec)) + { + rightColumnActive = false; + leftColumnActive = true; + } + else if (CheckCollisionPointRec(GetMousePosition(), rightColumnRec)) + { + leftColumnActive = false; + middleColumnActive = true; + } + } + + if (movingBox.x >= 1100) + { + done = true; + PlaySound(levelWin); + } + } + + if (done && !levelFinished) + { + levelTimeSec = framesCounter/60; + levelFinished = true; + framesCounter = 0; + } + + if (levelFinished) + { + framesCounter++; + + if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true; + } +} + +// Level08 Screen Draw logic +void DrawLevel08Screen(void) +{ + // Draw Level08 screen + DrawRectangle(1100, GetScreenHeight()/2 - 20, 40, 40, GRAY); + + DrawRectangleRec(movingBox, LIGHTGRAY); + + if (leftColumnActive) DrawRectangleRec(leftColumnRec, GRAY); + if (middleColumnActive) DrawRectangleRec(middleColumnRec, GRAY); + if (rightColumnActive) DrawRectangleRec(rightColumnRec, GRAY); + + if (levelFinished) + { + DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f)); + DrawText("LEVEL 08", GetScreenWidth()/2 - MeasureText("LEVEL 08", 30)/2, 20, 30, GRAY); + DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY); + } + else DrawText("LEVEL 08", GetScreenWidth()/2 - MeasureText("LEVEL 08", 30)/2, 20, 30, LIGHTGRAY); +} + +// Level08 Screen Unload logic +void UnloadLevel08Screen(void) +{ + // TODO: Unload Level08 screen variables here! +} + +// Level08 Screen should finish? +int FinishLevel08Screen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/just_do/screens/screen_level09.c b/games/just_do/screens/screen_level09.c new file mode 100644 index 000000000..d20f4bfb2 --- /dev/null +++ b/games/just_do/screens/screen_level09.c @@ -0,0 +1,199 @@ +/********************************************************************************************** +* +* raylib - Standard Game template +* +* Level09 Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 "raylib.h" +#include "screens.h" + +#define NUM_BOXES 21 + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Level09 screen global variables +static int framesCounter; +static int finishScreen; + +static Rectangle bwRecs[NUM_BOXES]; +static Color bwColors[NUM_BOXES]; +static bool activated[NUM_BOXES]; +static int resetCounter = 0; +static bool enableCounter = 0; + +static bool done = false; +static int levelTimeSec = 0; +static bool levelFinished = false; + +//---------------------------------------------------------------------------------- +// Level09 Screen Functions Definition +//---------------------------------------------------------------------------------- +static bool CheckColor(Color col1, Color col2); + +// Level09 Screen Initialization logic +void InitLevel09Screen(void) +{ + // Initialize Level09 screen variables here! + framesCounter = 0; + finishScreen = 0; + + for (int i = 0; i < NUM_BOXES; i++) + { + bwRecs[i].x = GetScreenWidth()/7*(i%7); + bwRecs[i].y = GetScreenHeight()/3*(i/7); + bwRecs[i].width = GetScreenWidth()/7; + bwRecs[i].height = GetScreenHeight()/3; + + activated[i] = false; + + if (i%2 == 0) bwColors[i] = LIGHTGRAY; + else bwColors[i] = GRAY; + } + + bwColors[10] = RAYWHITE; +} + +// Level09 Screen Update logic +void UpdateLevel09Screen(void) +{ + // Update Level09 screen variables here! + framesCounter++; + if (enableCounter) resetCounter++; + + if (!done) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + for (int i = 0; i < NUM_BOXES; i++) + { + if (CheckCollisionPointRec(GetMousePosition(), bwRecs[i])) + { + if (i == 10) + { + if (CheckColor(bwColors[i], RAYWHITE)) + { + bwColors[i] = LIGHTGRAY; + enableCounter = true; + resetCounter = 0; + activated[1] = true; + } + else + { + bwColors[i] = RAYWHITE; + enableCounter = false; + resetCounter = 5*60; + + for (int i = 0; i < NUM_BOXES; i++) activated[i] = false; + } + } + else if ((i%2 == 1) && enableCounter) + { + if (activated[i]) + { + bwColors[i] = LIGHTGRAY; + if (i != 19) activated[i + 2] = true; + } + } + } + } + } + + if (resetCounter > (4*60 + 10)) + { + for (int i = 0; i < NUM_BOXES; i++) + { + if (i%2 == 0) bwColors[i] = LIGHTGRAY; + else bwColors[i] = GRAY; + + activated[i] = false; + } + + bwColors[10] = RAYWHITE; + enableCounter = false; + resetCounter = 0; + } + + for (int i = 0; i < NUM_BOXES; i++) + { + done = true; + + if (!CheckColor(bwColors[i], LIGHTGRAY)) + { + done = false; + return; + } + + //if (done) PlaySound(levelWin); + } + } + + if (done && !levelFinished) + { + levelTimeSec = framesCounter/60; + levelFinished = true; + framesCounter = 0; + } + + if (levelFinished) + { + framesCounter++; + + if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true; + } +} + +// Level09 Screen Draw logic +void DrawLevel09Screen(void) +{ + // Draw Level09 screen + for (int i = 0; i < NUM_BOXES; i++) + { + DrawRectangleRec(bwRecs[i], bwColors[i]); + } + + if (levelFinished) + { + DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(RAYWHITE, 0.6f)); + DrawText("LEVEL 09", GetScreenWidth()/2 - MeasureText("LEVEL 09", 30)/2, 20, 30, GRAY); + DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY); + } + else DrawText("LEVEL 09", GetScreenWidth()/2 - MeasureText("LEVEL 09", 30)/2, 20, 30, LIGHTGRAY); +} + +// Level09 Screen Unload logic +void UnloadLevel09Screen(void) +{ + // TODO: Unload Level09 screen variables here! +} + +// Level09 Screen should finish? +int FinishLevel09Screen(void) +{ + return finishScreen; +} + +static bool CheckColor(Color col1, Color col2) +{ + return ((col1.r == col2.r) && (col1.g == col2.g) && (col1.b == col2.b) && (col1.a == col2.a)); +} \ No newline at end of file diff --git a/games/just_do/screens/screen_level10.c b/games/just_do/screens/screen_level10.c new file mode 100644 index 000000000..338060068 --- /dev/null +++ b/games/just_do/screens/screen_level10.c @@ -0,0 +1,153 @@ +/********************************************************************************************** +* +* raylib - Standard Game template +* +* Level10 Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 "raylib.h" +#include "screens.h" + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Level10 screen global variables +static int framesCounter; +static int finishScreen; + +static Rectangle leftColumnRec, middleColumnRec, rightColumnRec; +static Rectangle movingBox; +static int moveSpeed = 4; + +static bool leftColumnActive, middleColumnActive, rightColumnActive; + +static bool done = false; +static int levelTimeSec = 0; +static bool levelFinished = false; + +//---------------------------------------------------------------------------------- +// Level10 Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Level10 Screen Initialization logic +void InitLevel10Screen(void) +{ + // TODO: Initialize Level10 screen variables here! + framesCounter = 0; + finishScreen = 0; + + movingBox = (Rectangle){ 20, GetScreenHeight()/2 - 20, 40, 40 }; + + leftColumnRec = (Rectangle){ 240, 0, 100, GetScreenHeight() }; + middleColumnRec = (Rectangle){ GetScreenWidth()/2 - 50, 0, 100, GetScreenHeight() }; + rightColumnRec = (Rectangle){ 920, 0, 100, GetScreenHeight() }; + + leftColumnActive = true; + middleColumnActive = false; + rightColumnActive = true; +} + +// Level10 Screen Update logic +void UpdateLevel10Screen(void) +{ + // Update Level10 screen variables here! + framesCounter++; + + if (!done) + { + movingBox.x += moveSpeed; + + if (movingBox.x <= 0) moveSpeed *= -1; + + if ((leftColumnActive && (CheckCollisionRecs(leftColumnRec, movingBox))) || + (middleColumnActive && (CheckCollisionRecs(middleColumnRec, movingBox))) || + (rightColumnActive && (CheckCollisionRecs(rightColumnRec, movingBox)))) moveSpeed *= -1; + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + if (CheckCollisionPointRec(GetMousePosition(), leftColumnRec)) + { + middleColumnActive = false; + rightColumnActive = true; + } + else if (CheckCollisionPointRec(GetMousePosition(), middleColumnRec)) + { + rightColumnActive = false; + leftColumnActive = true; + } + else if (CheckCollisionPointRec(GetMousePosition(), rightColumnRec)) + { + leftColumnActive = false; + middleColumnActive = true; + } + } + } + + if (movingBox.x >= 1100) done = true; + + if (done && !levelFinished) + { + levelTimeSec = framesCounter/60; + levelFinished = true; + framesCounter = 0; + } + + if (levelFinished) + { + framesCounter++; + + if ((framesCounter > 90) && (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) finishScreen = true; + } +} + +// Level10 Screen Draw logic +void DrawLevel10Screen(void) +{ + // Draw Level10 screen + DrawRectangle(1100, GetScreenHeight()/2 - 20, 40, 40, GRAY); + + DrawRectangleRec(movingBox, LIGHTGRAY); + + if (leftColumnActive) DrawRectangleRec(leftColumnRec, GRAY); + if (middleColumnActive) DrawRectangleRec(middleColumnRec, GRAY); + if (rightColumnActive) DrawRectangleRec(rightColumnRec, GRAY); + + if (levelFinished) + { + DrawRectangleBordersRec((Rectangle){0, 0, GetScreenWidth(), GetScreenHeight()}, 0, 0, 60, Fade(LIGHTGRAY, 0.6f)); + DrawText("LEVEL 08", GetScreenWidth()/2 - MeasureText("LEVEL 08", 30)/2, 20, 30, GRAY); + DrawText(FormatText("DONE! (Seconds: %03i)", levelTimeSec), GetScreenWidth()/2 - MeasureText("DONE! (Seconds: 000)", 30)/2, GetScreenHeight() - 40, 30, GRAY); + } + else DrawText("LEVEL 08", GetScreenWidth()/2 - MeasureText("LEVEL 08", 30)/2, 20, 30, LIGHTGRAY); +} + +// Level10 Screen Unload logic +void UnloadLevel10Screen(void) +{ + // TODO: Unload Level10 screen variables here! +} + +// Level10 Screen should finish? +int FinishLevel10Screen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/just_do/screens/screen_logo.c b/games/just_do/screens/screen_logo.c new file mode 100644 index 000000000..9639602de --- /dev/null +++ b/games/just_do/screens/screen_logo.c @@ -0,0 +1,227 @@ +/********************************************************************************************** +* +* raylib - Standard Game template +* +* Logo Screen Functions Definitions (Init, Update, Draw, Unload) +* +* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 "raylib.h" +#include "screens.h" + +#include + +//---------------------------------------------------------------------------------- +// Global Variables Definition (local to this module) +//---------------------------------------------------------------------------------- + +// Logo screen global variables +static int framesCounter; +static int finishScreen; + +const char msgLogoA[64] = "A simple and easy-to-use library"; +const char msgLogoB[64] = "to learn videogames programming"; + +int logoPositionX; +int logoPositionY; + +int raylibLettersCount = 0; + +int topSideRecWidth = 16; +int leftSideRecHeight = 16; + +int bottomSideRecWidth = 16; +int rightSideRecHeight = 16; + +char raylib[8] = " \0"; // raylib text array, max 8 letters + +int logoScreenState = 0; // Tracking animation states (State Machine) +bool msgLogoADone = false; +bool msgLogoBDone = false; + +int lettersCounter = 0; +char msgBuffer[128] = { ' ' }; + +//---------------------------------------------------------------------------------- +// Logo Screen Functions Definition +//---------------------------------------------------------------------------------- + +// Logo Screen Initialization logic +void InitLogoScreen(void) +{ + // Initialize LOGO screen variables here! + framesCounter = 0; + finishScreen = 0; + + logoPositionX = GetScreenWidth()/2 - 128; + logoPositionY = GetScreenHeight()/2 - 128; +} + +// Logo Screen Update logic +void UpdateLogoScreen(void) +{ + // Update LOGO screen + framesCounter++; // Count frames + + // Update LOGO screen variables + if (logoScreenState == 0) // State 0: Small box blinking + { + framesCounter++; + + if (framesCounter == 120) + { + logoScreenState = 1; + framesCounter = 0; // Reset counter... will be used later... + } + } + else if (logoScreenState == 1) // State 1: Top and left bars growing + { + topSideRecWidth += 4; + leftSideRecHeight += 4; + + if (topSideRecWidth == 256) logoScreenState = 2; + } + else if (logoScreenState == 2) // State 2: Bottom and right bars growing + { + bottomSideRecWidth += 4; + rightSideRecHeight += 4; + + if (bottomSideRecWidth == 256) + { + lettersCounter = 0; + for (int i = 0; i < strlen(msgBuffer); i++) msgBuffer[i] = ' '; + + logoScreenState = 3; + } + } + else if (logoScreenState == 3) // State 3: Letters appearing (one by one) + { + framesCounter++; + + // Every 12 frames, one more letter! + if ((framesCounter%12) == 0) raylibLettersCount++; + + switch (raylibLettersCount) + { + case 1: raylib[0] = 'r'; break; + case 2: raylib[1] = 'a'; break; + case 3: raylib[2] = 'y'; break; + case 4: raylib[3] = 'l'; break; + case 5: raylib[4] = 'i'; break; + case 6: raylib[5] = 'b'; break; + default: break; + } + + if (raylibLettersCount >= 10) + { + // Write raylib description messages + if ((framesCounter%2) == 0) lettersCounter++; + + if (!msgLogoADone) + { + if (lettersCounter <= strlen(msgLogoA)) strncpy(msgBuffer, msgLogoA, lettersCounter); + else + { + for (int i = 0; i < strlen(msgBuffer); i++) msgBuffer[i] = ' '; + + lettersCounter = 0; + msgLogoADone = true; + } + } + else if (!msgLogoBDone) + { + if (lettersCounter <= strlen(msgLogoB)) strncpy(msgBuffer, msgLogoB, lettersCounter); + else + { + msgLogoBDone = true; + framesCounter = 0; + PlaySound(levelWin); + } + } + } + } + + // Wait for 2 seconds (60 frames) before jumping to TITLE screen + if (msgLogoBDone) + { + framesCounter++; + + if (framesCounter > 90) finishScreen = true; + } +} + +// Logo Screen Draw logic +void DrawLogoScreen(void) +{ + // Draw LOGO screen + if (logoScreenState == 0) + { + if ((framesCounter/15)%2) DrawRectangle(logoPositionX, logoPositionY - 60, 16, 16, BLACK); + } + else if (logoScreenState == 1) + { + DrawRectangle(logoPositionX, logoPositionY - 60, topSideRecWidth, 16, BLACK); + DrawRectangle(logoPositionX, logoPositionY - 60, 16, leftSideRecHeight, BLACK); + } + else if (logoScreenState == 2) + { + DrawRectangle(logoPositionX, logoPositionY - 60, topSideRecWidth, 16, BLACK); + DrawRectangle(logoPositionX, logoPositionY - 60, 16, leftSideRecHeight, BLACK); + + DrawRectangle(logoPositionX + 240, logoPositionY - 60, 16, rightSideRecHeight, BLACK); + DrawRectangle(logoPositionX, logoPositionY + 240 - 60, bottomSideRecWidth, 16, BLACK); + } + else if (logoScreenState == 3) + { + DrawRectangle(logoPositionX, logoPositionY - 60, topSideRecWidth, 16, BLACK); + DrawRectangle(logoPositionX, logoPositionY + 16 - 60, 16, leftSideRecHeight - 32, BLACK); + + DrawRectangle(logoPositionX + 240, logoPositionY + 16 - 60, 16, rightSideRecHeight - 32, BLACK); + DrawRectangle(logoPositionX, logoPositionY + 240 - 60, bottomSideRecWidth, 16, BLACK); + + DrawRectangle(GetScreenWidth()/2 - 112, GetScreenHeight()/2 - 112 - 60, 224, 224, RAYWHITE); + + DrawText(raylib, GetScreenWidth()/2 - 44, GetScreenHeight()/2 + 48 - 60, 50, BLACK); + + if (!msgLogoADone) DrawText(msgBuffer, GetScreenWidth()/2 - MeasureText(msgLogoA, 30)/2, logoPositionY + 230, 30, GRAY); + else + { + DrawText(msgLogoA, GetScreenWidth()/2 - MeasureText(msgLogoA, 30)/2, logoPositionY + 230, 30, GRAY); + + if (!msgLogoBDone) DrawText(msgBuffer, GetScreenWidth()/2 - MeasureText(msgLogoB, 30)/2, logoPositionY + 280, 30, GRAY); + else + { + DrawText(msgLogoB, GetScreenWidth()/2 - MeasureText(msgLogoA, 30)/2, logoPositionY + 280, 30, GRAY); + } + } + } +} + +// Logo Screen Unload logic +void UnloadLogoScreen(void) +{ + // TODO: Unload LOGO screen variables here! +} + +// Logo Screen should finish? +int FinishLogoScreen(void) +{ + return finishScreen; +} \ No newline at end of file diff --git a/games/just_do/screens/screens.h b/games/just_do/screens/screens.h new file mode 100644 index 000000000..7fa594053 --- /dev/null +++ b/games/just_do/screens/screens.h @@ -0,0 +1,150 @@ +/********************************************************************************************** +* +* raylib - Standard Game template +* +* Screens Functions Declarations (Init, Update, Draw, Unload) +* +* Copyright (c) 2014 Ramon Santamaria (Ray San - raysan@raysanweb.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 SCREENS_H +#define SCREENS_H + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum GameScreen { LOGO, LEVEL00, LEVEL01, LEVEL02, LEVEL03, LEVEL04, LEVEL05, LEVEL06, LEVEL07, LEVEL08, LEVEL09 } GameScreen; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +GameScreen currentScreen; +Sound levelWin; + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + +//---------------------------------------------------------------------------------- +// Logo Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitLogoScreen(void); +void UpdateLogoScreen(void); +void DrawLogoScreen(void); +void UnloadLogoScreen(void); +int FinishLogoScreen(void); + +//---------------------------------------------------------------------------------- +// Level00 Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitLevel00Screen(void); +void UpdateLevel00Screen(void); +void DrawLevel00Screen(void); +void UnloadLevel00Screen(void); +int FinishLevel00Screen(void); + +//---------------------------------------------------------------------------------- +// Level01 Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitLevel01Screen(void); +void UpdateLevel01Screen(void); +void DrawLevel01Screen(void); +void UnloadLevel01Screen(void); +int FinishLevel01Screen(void); + +//---------------------------------------------------------------------------------- +// Level02 Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitLevel02Screen(void); +void UpdateLevel02Screen(void); +void DrawLevel02Screen(void); +void UnloadLevel02Screen(void); +int FinishLevel02Screen(void); + +//---------------------------------------------------------------------------------- +// Level03 Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitLevel03Screen(void); +void UpdateLevel03Screen(void); +void DrawLevel03Screen(void); +void UnloadLevel03Screen(void); +int FinishLevel03Screen(void); + +//---------------------------------------------------------------------------------- +// Level04 Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitLevel04Screen(void); +void UpdateLevel04Screen(void); +void DrawLevel04Screen(void); +void UnloadLevel04Screen(void); +int FinishLevel04Screen(void); + +//---------------------------------------------------------------------------------- +// Level05 Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitLevel05Screen(void); +void UpdateLevel05Screen(void); +void DrawLevel05Screen(void); +void UnloadLevel05Screen(void); +int FinishLevel05Screen(void); + +//---------------------------------------------------------------------------------- +// Level06 Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitLevel06Screen(void); +void UpdateLevel06Screen(void); +void DrawLevel06Screen(void); +void UnloadLevel06Screen(void); +int FinishLevel06Screen(void); + +//---------------------------------------------------------------------------------- +// Level07 Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitLevel07Screen(void); +void UpdateLevel07Screen(void); +void DrawLevel07Screen(void); +void UnloadLevel07Screen(void); +int FinishLevel07Screen(void); + +//---------------------------------------------------------------------------------- +// Level08 Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitLevel08Screen(void); +void UpdateLevel08Screen(void); +void DrawLevel08Screen(void); +void UnloadLevel08Screen(void); +int FinishLevel08Screen(void); + +//---------------------------------------------------------------------------------- +// Level09 Screen Functions Declaration +//---------------------------------------------------------------------------------- +void InitLevel09Screen(void); +void UpdateLevel09Screen(void); +void DrawLevel09Screen(void); +void UnloadLevel09Screen(void); +int FinishLevel09Screen(void); + + +void DrawRectangleBordersRec(Rectangle rec, int offsetX, int offsetY, int borderSize, Color col); + +#ifdef __cplusplus +} +#endif + +#endif // SCREENS_H \ No newline at end of file diff --git a/shaders/gl330/base.vs b/shaders/gl330/base.vs index 59eae0a00..b0f930b70 100644 --- a/shaders/gl330/base.vs +++ b/shaders/gl330/base.vs @@ -6,8 +6,7 @@ in vec3 vertexNormal; out vec2 fragTexCoord; -uniform mat4 projectionMatrix; -uniform mat4 modelviewMatrix; +uniform mat4 mvpMatrix; // NOTE: Add here your custom variables @@ -15,5 +14,5 @@ void main() { fragTexCoord = vertexTexCoord; - gl_Position = projectionMatrix*modelviewMatrix*vec4(vertexPosition, 1.0); + gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); } \ No newline at end of file diff --git a/shaders/gl330/bloom.fs b/shaders/gl330/bloom.fs index f9cebe18a..34b6295c6 100644 --- a/shaders/gl330/bloom.fs +++ b/shaders/gl330/bloom.fs @@ -5,7 +5,7 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables @@ -18,23 +18,23 @@ void main() { for (int j = -3; j < 3; j++) { - sum += texture2D(texture0, fragTexCoord + vec2(j, i)*0.004) * 0.25; + sum += texture(texture0, fragTexCoord + vec2(j, i)*0.004) * 0.25; } } - if (texture2D(texture0, fragTexCoord).r < 0.3) + if (texture(texture0, fragTexCoord).r < 0.3) { - tc = sum*sum*0.012 + texture2D(texture0, fragTexCoord); + tc = sum*sum*0.012 + texture(texture0, fragTexCoord); } else { - if (texture2D(texture0, fragTexCoord).r < 0.5) + if (texture(texture0, fragTexCoord).r < 0.5) { - tc = sum*sum*0.009 + texture2D(texture0, fragTexCoord); + tc = sum*sum*0.009 + texture(texture0, fragTexCoord); } else { - tc = sum*sum*0.0075 + texture2D(texture0, fragTexCoord); + tc = sum*sum*0.0075 + texture(texture0, fragTexCoord); } } diff --git a/shaders/gl330/blur.fs b/shaders/gl330/blur.fs index b4e5bd2bc..44ea42b14 100644 --- a/shaders/gl330/blur.fs +++ b/shaders/gl330/blur.fs @@ -5,24 +5,24 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables -const float renderWidth = 1280; -const float renderHeight = 720; +const float renderWidth = 1280.0; +const float renderHeight = 720.0; float offset[3] = float[](0.0, 1.3846153846, 3.2307692308); float weight[3] = float[](0.2270270270, 0.3162162162, 0.0702702703); void main() { - vec3 tc = texture2D(texture0, fragTexCoord).rgb*weight[0]; + vec3 tc = texture(texture0, fragTexCoord).rgb*weight[0]; for (int i = 1; i < 3; i++) { - tc += texture2D(texture0, fragTexCoord + vec2(offset[i])/renderWidth, 0.0).rgb*weight[i]; - tc += texture2D(texture0, fragTexCoord - vec2(offset[i])/renderWidth, 0.0).rgb*weight[i]; + tc += texture(texture0, fragTexCoord + vec2(offset[i])/renderWidth, 0.0).rgb*weight[i]; + tc += texture(texture0, fragTexCoord - vec2(offset[i])/renderWidth, 0.0).rgb*weight[i]; } fragColor = vec4(tc, 1.0); diff --git a/shaders/gl330/cross_hatching.fs b/shaders/gl330/cross_hatching.fs index e23622120..6f5df9647 100644 --- a/shaders/gl330/cross_hatching.fs +++ b/shaders/gl330/cross_hatching.fs @@ -5,20 +5,20 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables -float hatchOffsetY = 5.0f; -float lumThreshold01 = 0.9f; -float lumThreshold02 = 0.7f; -float lumThreshold03 = 0.5f; -float lumThreshold04 = 0.3f; +float hatchOffsetY = 5.0; +float lumThreshold01 = 0.9; +float lumThreshold02 = 0.7; +float lumThreshold03 = 0.5; +float lumThreshold04 = 0.3; void main() { vec3 tc = vec3(1.0, 1.0, 1.0); - float lum = length(texture2D(texture0, fragTexCoord).rgb); + float lum = length(texture(texture0, fragTexCoord).rgb); if (lum < lumThreshold01) { diff --git a/shaders/gl330/cross_stitching.fs b/shaders/gl330/cross_stitching.fs index 041bf1dcc..dcb26e79b 100644 --- a/shaders/gl330/cross_stitching.fs +++ b/shaders/gl330/cross_stitching.fs @@ -5,14 +5,14 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables -const float renderWidth = 1280; -const float renderHeight = 720; +const float renderWidth = 1280.0; +const float renderHeight = 720.0; -float stitchingSize = 6.0f; +float stitchingSize = 6.0; uniform int invert = 0; @@ -35,11 +35,11 @@ vec4 PostFX(sampler2D tex, vec2 uv) if ((remX == remY) || (((int(cPos.x) - int(blPos.x)) == (int(blPos.y) - int(cPos.y))))) { if (invert == 1) c = vec4(0.2, 0.15, 0.05, 1.0); - else c = texture2D(tex, tlPos * vec2(1.0/renderWidth, 1.0/renderHeight)) * 1.4; + else c = texture(tex, tlPos * vec2(1.0/renderWidth, 1.0/renderHeight)) * 1.4; } else { - if (invert == 1) c = texture2D(tex, tlPos * vec2(1.0/renderWidth, 1.0/renderHeight)) * 1.4; + if (invert == 1) c = texture(tex, tlPos * vec2(1.0/renderWidth, 1.0/renderHeight)) * 1.4; else c = vec4(0.0, 0.0, 0.0, 1.0); } diff --git a/shaders/gl330/dream_vision.fs b/shaders/gl330/dream_vision.fs index de9c04ebf..0ea4ce200 100644 --- a/shaders/gl330/dream_vision.fs +++ b/shaders/gl330/dream_vision.fs @@ -5,27 +5,27 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables void main() { - vec4 color = texture2D(texture0, fragTexCoord); + vec4 color = texture(texture0, fragTexCoord); - color += texture2D(texture0, fragTexCoord + 0.001); - color += texture2D(texture0, fragTexCoord + 0.003); - color += texture2D(texture0, fragTexCoord + 0.005); - color += texture2D(texture0, fragTexCoord + 0.007); - color += texture2D(texture0, fragTexCoord + 0.009); - color += texture2D(texture0, fragTexCoord + 0.011); + color += texture(texture0, fragTexCoord + 0.001); + color += texture(texture0, fragTexCoord + 0.003); + color += texture(texture0, fragTexCoord + 0.005); + color += texture(texture0, fragTexCoord + 0.007); + color += texture(texture0, fragTexCoord + 0.009); + color += texture(texture0, fragTexCoord + 0.011); - color += texture2D(texture0, fragTexCoord - 0.001); - color += texture2D(texture0, fragTexCoord - 0.003); - color += texture2D(texture0, fragTexCoord - 0.005); - color += texture2D(texture0, fragTexCoord - 0.007); - color += texture2D(texture0, fragTexCoord - 0.009); - color += texture2D(texture0, fragTexCoord - 0.011); + color += texture(texture0, fragTexCoord - 0.001); + color += texture(texture0, fragTexCoord - 0.003); + color += texture(texture0, fragTexCoord - 0.005); + color += texture(texture0, fragTexCoord - 0.007); + color += texture(texture0, fragTexCoord - 0.009); + color += texture(texture0, fragTexCoord - 0.011); color.rgb = vec3((color.r + color.g + color.b)/3.0); color = color/9.5; diff --git a/shaders/gl330/fisheye.fs b/shaders/gl330/fisheye.fs index d0e42cca4..5bd9abf4b 100644 --- a/shaders/gl330/fisheye.fs +++ b/shaders/gl330/fisheye.fs @@ -5,7 +5,7 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables @@ -13,7 +13,7 @@ const float PI = 3.1415926535; void main() { - float aperture = 178.0f; + float aperture = 178.0; float apertureHalf = 0.5 * aperture * (PI / 180.0); float maxFactor = sin(apertureHalf); @@ -36,5 +36,5 @@ void main() uv = fragTexCoord.xy; } - fragColor = texture2D(texture0, uv); + fragColor = texture(texture0, uv); } \ No newline at end of file diff --git a/shaders/gl330/grayscale.fs b/shaders/gl330/grayscale.fs index 38337e007..b3a695bfb 100644 --- a/shaders/gl330/grayscale.fs +++ b/shaders/gl330/grayscale.fs @@ -5,16 +5,16 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables void main() { - vec4 base = texture2D(texture0, fragTexCoord)*tintColor; + vec4 base = texture(texture0, fragTexCoord)*fragTintColor; // Convert to grayscale using NTSC conversion weights float gray = dot(base.rgb, vec3(0.299, 0.587, 0.114)); - fragColor = vec4(gray, gray, gray, tintColor.a); + fragColor = vec4(gray, gray, gray, fragTintColor.a); } \ No newline at end of file diff --git a/shaders/gl330/phong.fs b/shaders/gl330/phong.fs new file mode 100644 index 000000000..75b7e6d73 --- /dev/null +++ b/shaders/gl330/phong.fs @@ -0,0 +1,76 @@ +#version 330 + +// Vertex shader input data +in vec2 fragTexCoord; +in vec3 fragNormal; + +// Diffuse data +uniform sampler2D texture0; +uniform vec4 fragTintColor; + +// Light attributes +uniform vec3 light_ambientColor = vec3(0.6, 0.3, 0); +uniform vec3 light_diffuseColor = vec3(1, 0.5, 0); +uniform vec3 light_specularColor = vec3(0, 1, 0); +uniform float light_intensity = 1; +uniform float light_specIntensity = 1; + +// Material attributes +uniform vec3 mat_ambientColor = vec3(1, 1, 1); +uniform vec3 mat_specularColor = vec3(1, 1, 1); +uniform float mat_glossiness = 50; + +// World attributes +uniform vec3 lightPos; +uniform vec3 cameraPos; + +// Fragment shader output data +out vec4 fragColor; + +vec3 AmbientLighting() +{ + return mat_ambientColor * light_ambientColor; +} + +vec3 DiffuseLighting(in vec3 N, in vec3 L) +{ + // Lambertian reflection calculation + float diffuse = clamp(dot(N, L), 0, 1); + + return tintColor.xyz * light_diffuseColor * light_intensity * diffuse; +} + +vec3 SpecularLighting(in vec3 N, in vec3 L, in vec3 V) +{ + float specular = 0; + + // Calculate specular reflection only if the surface is oriented to the light source + if(dot(N, L) > 0) + { + // Calculate half vector + vec3 H = normalize(L + V); + + // Calculate specular intensity + specular = pow(dot(N, H), 3 + mat_glossiness); + } + + return mat_specularColor * light_specularColor * light_specIntensity * specular; +} + +void main() +{ + // Normalize input vectors + vec3 L = normalize(lightPos); + vec3 V = normalize(cameraPos); + vec3 N = normalize(fragNormal); + + vec3 ambient = AmbientLighting(); + vec3 diffuse = DiffuseLighting(N, L); + vec3 specular = SpecularLighting(N, L, V); + + // Get base color from texture + vec4 textureColor = texture(texture0, fragTexCoord); + vec3 finalColor = textureColor.rgb; + + fragColor = vec4(finalColor * (ambient + diffuse + specular), textureColor.a); +} \ No newline at end of file diff --git a/shaders/gl330/phong.vs b/shaders/gl330/phong.vs new file mode 100644 index 000000000..ee6d34bfa --- /dev/null +++ b/shaders/gl330/phong.vs @@ -0,0 +1,27 @@ +#version 330 + +// Vertex input data +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; + +// Projection and model data +uniform mat4 mvpMatrix; +uniform mat4 modelMatrix; + +// Attributes to fragment shader +out vec2 fragTexCoord; +out vec3 fragNormal; + +void main() +{ + // Send texture coord to fragment shader + fragTexCoord = vertexTexCoord; + + // Calculate view vector normal from model + mat3 normalMatrix = transpose(inverse(mat3(modelMatrix))); + fragNormal = normalize(normalMatrix*vertexNormal); + + // Calculate final vertex position + gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); +} \ No newline at end of file diff --git a/shaders/gl330/pixel.fs b/shaders/gl330/pixel.fs index ec9e13d7c..aa5a22fe1 100644 --- a/shaders/gl330/pixel.fs +++ b/shaders/gl330/pixel.fs @@ -5,15 +5,15 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables -const float renderWidth = 1280; -const float renderHeight = 720; +const float renderWidth = 1280.0; +const float renderHeight = 720.0; -uniform float pixelWidth = 5.0f; -uniform float pixelHeight = 5.0f; +uniform float pixelWidth = 5.0; +uniform float pixelHeight = 5.0; void main() { @@ -22,7 +22,7 @@ void main() vec2 coord = vec2(dx*floor(fragTexCoord.x/dx), dy*floor(fragTexCoord.y/dy)); - vec3 tc = texture2D(texture0, coord).rgb; + vec3 tc = texture(texture0, coord).rgb; fragColor = vec4(tc, 1.0); } \ No newline at end of file diff --git a/shaders/gl330/posterization.fs b/shaders/gl330/posterization.fs index 652cf609a..5215bd8bc 100644 --- a/shaders/gl330/posterization.fs +++ b/shaders/gl330/posterization.fs @@ -5,16 +5,16 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables -float gamma = 0.6f; -float numColors = 8.0f; +float gamma = 0.6; +float numColors = 8.0; void main() { - vec3 color = texture2D(texture0, fragTexCoord.xy).rgb; + vec3 color = texture(texture0, fragTexCoord.xy).rgb; color = pow(color, vec3(gamma, gamma, gamma)); color = color*numColors; diff --git a/shaders/gl330/predator.fs b/shaders/gl330/predator.fs index 778829172..85c93d0cd 100644 --- a/shaders/gl330/predator.fs +++ b/shaders/gl330/predator.fs @@ -5,13 +5,13 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables void main() { - vec3 color = texture2D(texture0, fragTexCoord).rgb; + vec3 color = texture(texture0, fragTexCoord).rgb; vec3 colors[3]; colors[0] = vec3(0.0, 0.0, 1.0); colors[1] = vec3(1.0, 1.0, 0.0); diff --git a/shaders/gl330/scanlines.fs b/shaders/gl330/scanlines.fs index 7f33f882b..0c89e6107 100644 --- a/shaders/gl330/scanlines.fs +++ b/shaders/gl330/scanlines.fs @@ -5,12 +5,12 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables -float offset = 0; -float frequency = 720/3.0; +float offset = 0.0; +float frequency = 720.0/3.0; uniform float time; @@ -21,7 +21,7 @@ void main (void) float tval = 0; //time vec2 uv = 0.5 + (fragTexCoord - 0.5)*(0.9 + 0.01*sin(0.5*tval)); - vec4 color = texture2D(texture0, fragTexCoord); + vec4 color = texture(texture0, fragTexCoord); color = clamp(color*0.5 + 0.5*color*color*1.2, 0.0, 1.0); color *= 0.5 + 0.5*16.0*uv.x*uv.y*(1.0 - uv.x)*(1.0 - uv.y); @@ -35,7 +35,7 @@ void main (void) float globalPos = (fragTexCoord.y + offset) * frequency; float wavePos = cos((fract(globalPos) - 0.5)*3.14); - vec4 color = texture2D(texture0, fragTexCoord); + vec4 color = texture(texture0, fragTexCoord); - fragColor = mix(vec4(0, 0.3, 0, 0), color, wavePos); + fragColor = mix(vec4(0.0, 0.3, 0.0, 0.0), color, wavePos); } \ No newline at end of file diff --git a/shaders/gl330/swirl.fs b/shaders/gl330/swirl.fs index 18a47cec4..19d7468b1 100644 --- a/shaders/gl330/swirl.fs +++ b/shaders/gl330/swirl.fs @@ -5,17 +5,17 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables -const float renderWidth = 1280; -const float renderHeight = 720; +const float renderWidth = 1280.0; +const float renderHeight = 720.0; float radius = 250.0; float angle = 0.8; -uniform vec2 center = vec2(200, 200); +uniform vec2 center = vec2(200.0, 200.0); void main (void) { @@ -35,7 +35,7 @@ void main (void) } tc += center; - vec3 color = texture2D(texture0, tc/texSize).rgb; + vec3 color = texture(texture0, tc/texSize).rgb; fragColor = vec4(color, 1.0);; } \ No newline at end of file diff --git a/shaders/gl330/template.fs b/shaders/gl330/template.fs index 922219598..ad7210a4c 100644 --- a/shaders/gl330/template.fs +++ b/shaders/gl330/template.fs @@ -5,15 +5,15 @@ in vec2 fragTexCoord; out vec4 fragColor; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables void main() { - vec4 texelColor = texture2D(texture0, fragTexCoord); + vec4 texelColor = texture(texture0, fragTexCoord); // NOTE: Implement here your fragment shader code - fragColor = texelColor*tintColor; + fragColor = texelColor*fragTintColor; } diff --git a/shaders/gles100/base.vs b/shaders/gles100/base.vs index eff89c56a..9f339382b 100644 --- a/shaders/gles100/base.vs +++ b/shaders/gles100/base.vs @@ -6,8 +6,7 @@ attribute vec3 vertexNormal; varying vec2 fragTexCoord; -uniform mat4 projectionMatrix; -uniform mat4 modelviewMatrix; +uniform mat4 mvpMatrix; // NOTE: Add here your custom variables @@ -17,5 +16,5 @@ void main() fragTexCoord = vertexTexCoord; - gl_Position = projectionMatrix*modelviewMatrix*vec4(vertexPosition, 1.0); + gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); } \ No newline at end of file diff --git a/shaders/gles100/bloom.fs b/shaders/gles100/bloom.fs index eba44d41d..33754c7ef 100644 --- a/shaders/gles100/bloom.fs +++ b/shaders/gles100/bloom.fs @@ -5,7 +5,7 @@ precision mediump float; varying vec2 fragTexCoord; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables diff --git a/shaders/gles100/blur.fs b/shaders/gles100/blur.fs index 3c865ca0c..a1069c6fd 100644 --- a/shaders/gles100/blur.fs +++ b/shaders/gles100/blur.fs @@ -4,7 +4,7 @@ precision mediump float; varying vec2 fragTexCoord; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables diff --git a/shaders/gles100/cross_hatching.fs b/shaders/gles100/cross_hatching.fs index c308acb6a..cf01b65ed 100644 --- a/shaders/gles100/cross_hatching.fs +++ b/shaders/gles100/cross_hatching.fs @@ -5,7 +5,7 @@ precision mediump float; varying vec2 fragTexCoord; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables diff --git a/shaders/gles100/cross_stitching.fs b/shaders/gles100/cross_stitching.fs index 09b3ad4a7..f1afef048 100644 --- a/shaders/gles100/cross_stitching.fs +++ b/shaders/gles100/cross_stitching.fs @@ -5,7 +5,7 @@ precision mediump float; varying vec2 fragTexCoord; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables diff --git a/shaders/gles100/dream_vision.fs b/shaders/gles100/dream_vision.fs index 6cbdfcd6a..bb8289700 100644 --- a/shaders/gles100/dream_vision.fs +++ b/shaders/gles100/dream_vision.fs @@ -5,7 +5,7 @@ precision mediump float; varying vec2 fragTexCoord; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables diff --git a/shaders/gles100/fisheye.fs b/shaders/gles100/fisheye.fs index a21257c79..e7a4485c7 100644 --- a/shaders/gles100/fisheye.fs +++ b/shaders/gles100/fisheye.fs @@ -5,7 +5,7 @@ precision mediump float; varying vec2 fragTexCoord; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables diff --git a/shaders/gles100/grayscale.fs b/shaders/gles100/grayscale.fs index 07e796145..e55545e22 100644 --- a/shaders/gles100/grayscale.fs +++ b/shaders/gles100/grayscale.fs @@ -5,16 +5,16 @@ precision mediump float; varying vec2 fragTexCoord; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables void main() { - vec4 base = texture2D(texture0, fragTexCoord)*tintColor; + vec4 base = texture2D(texture0, fragTexCoord)*fragTintColor; // Convert to grayscale using NTSC conversion weights float gray = dot(base.rgb, vec3(0.299, 0.587, 0.114)); - gl_FragColor = vec4(gray, gray, gray, tintColor.a); + gl_FragColor = vec4(gray, gray, gray, fragTintColor.a); } \ No newline at end of file diff --git a/shaders/gles100/pixel.fs b/shaders/gles100/pixel.fs index eceff6e33..552e89004 100644 --- a/shaders/gles100/pixel.fs +++ b/shaders/gles100/pixel.fs @@ -5,7 +5,7 @@ precision mediump float; varying vec2 fragTexCoord; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables diff --git a/shaders/gles100/posterization.fs b/shaders/gles100/posterization.fs index f635305e6..4f4c4b935 100644 --- a/shaders/gles100/posterization.fs +++ b/shaders/gles100/posterization.fs @@ -5,7 +5,7 @@ precision mediump float; varying vec2 fragTexCoord; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables diff --git a/shaders/gles100/predator.fs b/shaders/gles100/predator.fs index c85048a6c..2fbdc7afb 100644 --- a/shaders/gles100/predator.fs +++ b/shaders/gles100/predator.fs @@ -5,7 +5,7 @@ precision mediump float; varying vec2 fragTexCoord; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables diff --git a/shaders/gles100/scanlines.fs b/shaders/gles100/scanlines.fs index 56a6f6941..85de158d8 100644 --- a/shaders/gles100/scanlines.fs +++ b/shaders/gles100/scanlines.fs @@ -5,7 +5,7 @@ precision mediump float; varying vec2 fragTexCoord; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables diff --git a/shaders/gles100/swirl.fs b/shaders/gles100/swirl.fs index b50ed39ed..b0d54b235 100644 --- a/shaders/gles100/swirl.fs +++ b/shaders/gles100/swirl.fs @@ -5,7 +5,7 @@ precision mediump float; varying vec2 fragTexCoord; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables diff --git a/shaders/gles100/template.fs b/shaders/gles100/template.fs index 9d9499f36..1f4b8ccfa 100644 --- a/shaders/gles100/template.fs +++ b/shaders/gles100/template.fs @@ -5,7 +5,7 @@ precision mediump float; varying vec2 fragTexCoord; uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // NOTE: Add here your custom variables @@ -15,5 +15,5 @@ void main() // NOTE: Implement here your fragment shader code - gl_FragColor = texelColor*tintColor; + gl_FragColor = texelColor*fragTintColor; } \ No newline at end of file diff --git a/src/audio.c b/src/audio.c index 8ef711163..6313c9dc5 100644 --- a/src/audio.c +++ b/src/audio.c @@ -92,7 +92,7 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -bool musicEnabled = false; +static bool musicEnabled = false; static Music currentMusic; // Current music loaded // NOTE: Only one music file playing at a time diff --git a/src/camera.c b/src/camera.c index f2ac32753..4768b1766 100644 --- a/src/camera.c +++ b/src/camera.c @@ -317,7 +317,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance; camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance; - if (camera->target.y < 0) camera->target.y = -0.001; + // if (camera->target.y < 0) camera->target.y = -0.001; } else if ((camera->position.y > camera->target.y) && (camera->target.y < 0) && (mouseWheelMove > 0)) { @@ -337,7 +337,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) camera->target.y += mouseWheelMove*(camera->target.y - camera->position.y)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance; camera->target.z += mouseWheelMove*(camera->target.z - camera->position.z)*CAMERA_SCROLL_SENSITIVITY/cameraTargetDistance; - if (camera->target.y > 0) camera->target.y = 0.001; + // if (camera->target.y > 0) camera->target.y = 0.001; } else if ((camera->position.y < camera->target.y) && (camera->target.y > 0) && (mouseWheelMove > 0)) { diff --git a/src/core.c b/src/core.c index b2d945063..7b7d65fc1 100644 --- a/src/core.c +++ b/src/core.c @@ -66,7 +66,7 @@ #include // Java native interface #include // Android sensors functions #include // Defines AWINDOW_FLAG_FULLSCREEN and others - //#include // Defines basic app state struct and manages activity + #include // Defines basic app state struct and manages activity #include // Khronos EGL library - Native platform display device control functions #include // Khronos OpenGL ES 2.0 library @@ -103,7 +103,6 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define MAX_TOUCH_POINTS 256 //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -121,7 +120,10 @@ static struct android_app *app; // Android activity static struct android_poll_source *source; // Android events polling source static int ident, events; static bool windowReady = false; // Used to detect display initialization - +static bool appEnabled = true; // Used to detec if app is active +static bool contextRebindRequired = false; // Used to know context rebind required +static int previousButtonState[128] = { 1 }; // Required to check if button pressed/released once +static int currentButtonState[128] = { 1 }; // Required to check if button pressed/released once #elif defined(PLATFORM_RPI) static EGL_DISPMANX_WINDOW_T nativeWindow; // Native window (graphic device) @@ -149,6 +151,7 @@ static int gamepadStream = -1; // Gamepad device file descripto static EGLDisplay display; // Native display device (physical screen connection) static EGLSurface surface; // Surface to draw on, framebuffers (connected to context) static EGLContext context; // Graphic context, mode in which drawing can be done +static EGLConfig config; // Graphic config static uint64_t baseTime; // Base time measure for hi-res timer static bool windowShouldClose = false; // Flag to set window for closing #endif @@ -254,10 +257,12 @@ static void TakeScreenshot(void); #if defined(PLATFORM_ANDROID) static void AndroidCommandCallback(struct android_app *app, int32_t cmd); // Process Android activity lifecycle commands +static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event); // Process Android inputs #endif #if defined(PLATFORM_WEB) static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *e, void *userData); +static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData); #endif //---------------------------------------------------------------------------------- @@ -267,7 +272,7 @@ static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const Emscripte // Initialize Window and Graphics Context (OpenGL) void InitWindow(int width, int height, const char *title) { - TraceLog(INFO, "Initializing raylib (v1.3.0)"); + TraceLog(INFO, "Initializing raylib (v1.4.0)"); // Store window title (could be useful...) windowTitle = title; @@ -293,13 +298,19 @@ void InitWindow(int width, int height, const char *title) #endif #if defined(PLATFORM_WEB) - InitGesturesSystem(); - emscripten_set_fullscreenchange_callback(0, 0, 1, EmscriptenFullscreenChangeCallback); + + // NOTE: Some code examples + //emscripten_set_touchstart_callback(0, NULL, 1, Emscripten_HandleTouch); + //emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch); + emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenInputCallback); + emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenInputCallback); + emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenInputCallback); + emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenInputCallback); #endif - mousePosition.x = screenWidth/2; - mousePosition.y = screenHeight/2; + mousePosition.x = (float)screenWidth/2.0f; + mousePosition.y = (float)screenHeight/2.0f; // raylib logo appearing animation (if enabled) if (showLogo) @@ -313,7 +324,7 @@ void InitWindow(int width, int height, const char *title) // Android activity initialization void InitWindow(int width, int height, struct android_app *state) { - TraceLog(INFO, "Initializing raylib (v1.3.0)"); + TraceLog(INFO, "Initializing raylib (v1.4.0)"); app_dummy(); @@ -350,26 +361,30 @@ void InitWindow(int width, int height, struct android_app *state) //state->userData = &engine; app->onAppCmd = AndroidCommandCallback; + app->onInputEvent = AndroidInputCallback; - //InitGesturesSystem(app); // NOTE: Must be called by user - InitAssetManager(app->activity->assetManager); - - InitGesturesSystem(app); TraceLog(INFO, "Android app initialized successfully"); + // Init button states values (default up) + for(int i = 0; i < 128; i++) + { + currentButtonState[i] = 1; + previousButtonState[i] = 1; + } + + // Wait for window to be initialized (display and context) while (!windowReady) { - // Wait for window to be initialized (display and context) // Process events loop while ((ident = ALooper_pollAll(0, NULL, &events,(void**)&source)) >= 0) { // Process this event if (source != NULL) source->process(app, source); - // Check if we are exiting - if (app->destroyRequested != 0) windowShouldClose = true; + // NOTE: Never close window, native activity is controlled by the system! + //if (app->destroyRequested != 0) windowShouldClose = true; } } } @@ -504,12 +519,23 @@ void BeginDrawing(void) rlLoadIdentity(); // Reset current matrix (MODELVIEW) - rlMultMatrixf(GetMatrixVector(downscaleView)); // If downscale required, apply it here + rlMultMatrixf(MatrixToFloat(downscaleView)); // If downscale required, apply it here //rlTranslatef(0.375, 0.375, 0); // HACK to have 2D pixel-perfect drawing on OpenGL 1.1 // NOTE: Not required with OpenGL 3.3+ } +// Setup drawing canvas with extended parameters +void BeginDrawingEx(int blendMode, Shader shader, Matrix transform) +{ + BeginDrawing(); + + SetBlendMode(blendMode); + SetPostproShader(shader); + + rlMultMatrixf(MatrixToFloat(transform)); +} + // End canvas drawing and Swap Buffers (Double Buffering) void EndDrawing(void) { @@ -551,7 +577,7 @@ void Begin3dMode(Camera camera) // Setup perspective projection float aspect = (float)screenWidth/(float)screenHeight; - double top = 0.1f*tan(45.0f*PI / 360.0f); + double top = 0.1f*tan(45.0f*PI/360.0f); double right = top*aspect; // NOTE: zNear and zFar values are important when computing depth buffer values @@ -561,8 +587,8 @@ void Begin3dMode(Camera camera) rlLoadIdentity(); // Reset current matrix (MODELVIEW) // Setup Camera view - Matrix view = MatrixLookAt(camera.position, camera.target, camera.up); - rlMultMatrixf(GetMatrixVector(view)); // Multiply MODELVIEW matrix by view matrix (camera) + Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); + rlMultMatrixf(MatrixToFloat(matView)); // Multiply MODELVIEW matrix by view matrix (camera) } // Ends 3D mode and returns to default 2D orthographic mode @@ -582,7 +608,7 @@ void End3dMode(void) // Set target FPS for the game void SetTargetFPS(int fps) { - targetTime = 1 / (double)fps; + targetTime = 1.0/(double)fps; TraceLog(INFO, "Target time per frame: %02.03f milliseconds", (float)targetTime*1000); } @@ -599,11 +625,24 @@ float GetFrameTime(void) // As we are operate quite a lot with frameTime, // it could be no stable, so we round it before passing it around // NOTE: There are still problems with high framerates (>500fps) - double roundedFrameTime = round(frameTime*10000)/10000; + double roundedFrameTime = round(frameTime*10000)/10000.0; return (float)roundedFrameTime; // Time in seconds to run a frame } +// Converts Color to float array and normalizes +float *ColorToFloat(Color color) +{ + static float buffer[4]; + + buffer[0] = (float)color.r/255; + buffer[1] = (float)color.g/255; + buffer[2] = (float)color.b/255; + buffer[3] = (float)color.a/255; + + return buffer; +} + // Returns a Color struct from hexadecimal value Color GetColor(int hexValue) { @@ -691,46 +730,161 @@ void ClearDroppedFiles(void) } #endif -// TODO: Gives the ray trace from mouse position +// Storage save integer value (to defined position) +// NOTE: Storage positions is directly related to file memory layout (4 bytes each integer) +void StorageSaveValue(int position, int value) +{ + FILE *storageFile = NULL; + + // Try open existing file to append data + storageFile = fopen("storage.data", "rb+"); + + // If file doesn't exist, create a new storage data file + if (!storageFile) storageFile = fopen("storage.data", "wb"); + + if (!storageFile) TraceLog(WARNING, "Storage data file could not be created"); + else + { + // Get file size + fseek(storageFile, 0, SEEK_END); + int fileSize = ftell(storageFile); // Size in bytes + fseek(storageFile, 0, SEEK_SET); + + if (fileSize < (position*4)) TraceLog(WARNING, "Storage position could not be found"); + else + { + fseek(storageFile, (position*4), SEEK_SET); + fwrite(&value, 1, 4, storageFile); + } + + fclose(storageFile); + } +} + +// Storage load integer value (from defined position) +// NOTE: If requested position could not be found, value 0 is returned +int StorageLoadValue(int position) +{ + int value = 0; + + // Try open existing file to append data + FILE *storageFile = fopen("storage.data", "rb"); + + if (!storageFile) TraceLog(WARNING, "Storage data file could not be found"); + else + { + // Get file size + fseek(storageFile, 0, SEEK_END); + int fileSize = ftell(storageFile); // Size in bytes + rewind(storageFile); + + if (fileSize < (position*4)) TraceLog(WARNING, "Storage position could not be found"); + else + { + fseek(storageFile, (position*4), SEEK_SET); + fread(&value, 1, 4, storageFile); + } + + fclose(storageFile); + } + + return value; +} + +// Returns a ray trace from mouse position +//http://www.songho.ca/opengl/gl_transform.html +//http://www.songho.ca/opengl/gl_matrix.html +//http://www.sjbaker.org/steve/omniv/matrices_can_be_your_friends.html +//https://www.opengl.org/archives/resources/faq/technical/transformations.htm Ray GetMouseRay(Vector2 mousePosition, Camera camera) { + // Tutorial used: https://mkonrad.net/2014/08/07/simple-opengl-object-picking-in-3d.html + // Similar to http://antongerdelan.net, the problem is maybe in MatrixPerspective vs MatrixFrustum + // or matrix order (transpose it or not... that's the question) + Ray ray; - - Matrix proj = MatrixIdentity(); - Matrix view = MatrixLookAt(camera.position, camera.target, camera.up); - - // Calculate projection matrix for the camera - float aspect = (float)GetScreenWidth()/(float)GetScreenHeight(); - double top = 0.1f*tanf(45.0f*PI/360.0f); - double right = top*aspect; - - // NOTE: zNear and zFar values are important for depth - proj = MatrixFrustum(-right, right, -top, top, 0.01f, 1000.0f); - MatrixTranspose(&proj); - - // NOTE: Our screen origin is top-left instead of bottom-left: transform required! - float invertedMouseY = (float)GetScreenHeight() - mousePosition.y; - - // NOTE: Do I really need to get z value from depth buffer? - //float z; - //glReadPixels(mousePosition.x, mousePosition.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z); - //http://www.bfilipek.com/2012/06/select-mouse-opengl.html - - Vector3 nearPoint = { mousePosition.x, invertedMouseY, 0.0f }; - Vector3 farPoint = { mousePosition.x, invertedMouseY, 1.0f }; - - nearPoint = rlglUnproject(nearPoint, proj, view); - farPoint = rlglUnproject(farPoint, proj, view); // TODO: it seems it doesn't work... - + + // Calculate normalized device coordinates + // NOTE: y value is negative + float x = (2.0f*mousePosition.x)/(float)GetScreenWidth() - 1.0f; + float y = 1.0f - (2.0f*mousePosition.y)/(float)GetScreenHeight(); + float z = 1.0f; + + // Store values in a vector + Vector3 deviceCoords = {x, y, z}; + + // Device debug message + TraceLog(INFO, "device(%f, %f, %f)", deviceCoords.x, deviceCoords.y, deviceCoords.z); + + // Calculate projection matrix (from perspective instead of frustum + Matrix matProj = MatrixPerspective(45.0f, (float)((float)GetScreenWidth() / (float)GetScreenHeight()), 0.01f, 1000.0f); + + // Calculate view matrix from camera look at + Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); + + // Do I need to transpose it? It seems that yes... + // NOTE: matrix order is maybe incorrect... In OpenGL to get world position from + // camera view it just needs to get inverted, but here we need to transpose it too. + // For example, if you get view matrix, transpose and inverted and you transform it + // to a vector, you will get its 3d world position coordinates (camera.position). + // If you don't transpose, final position will be wrong. + MatrixTranspose(&matView); + + // Calculate unproject matrix (multiply projection matrix and view matrix) and invert it + Matrix matProjView = MatrixMultiply(matProj, matView); + MatrixInvert(&matProjView); + + // Calculate far and near points + Quaternion near = { deviceCoords.x, deviceCoords.y, 0, 1}; + Quaternion far = { deviceCoords.x, deviceCoords.y, 1, 1}; + + // Multiply points by unproject matrix + QuaternionTransform(&near, matProjView); + QuaternionTransform(&far, matProjView); + + // Calculate normalized world points in vectors + Vector3 nearPoint = {near.x / near.w, near.y / near.w, near.z / near.w}; + Vector3 farPoint = {far.x / far.w, far.y / far.w, far.z / far.w}; + + // Calculate normalized direction vector Vector3 direction = VectorSubtract(farPoint, nearPoint); VectorNormalize(&direction); - - ray.position = nearPoint; + + // Apply calculated vectors to ray + ray.position = camera.position; ray.direction = direction; - + return ray; } +// Returns the screen space position from a 3d world space position +Vector2 WorldToScreen(Vector3 position, Camera camera) +{ + // Calculate projection matrix (from perspective instead of frustum + Matrix matProj = MatrixPerspective(45.0f, (float)((float)GetScreenWidth() / (float)GetScreenHeight()), 0.01f, 1000.0f); + + // Calculate view matrix from camera look at (and transpose it) + Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); + MatrixTranspose(&matView); + + // Convert world position vector to quaternion + Quaternion worldPos = { position.x, position.y, position.z, 1.0f }; + + // Transform world position to view + QuaternionTransform(&worldPos, matView); + + // Transform result to projection (clip space position) + QuaternionTransform(&worldPos, matProj); + + // Calculate normalized device coordinates (inverted y) + Vector3 ndcPos = { worldPos.x / worldPos.w, -worldPos.y / worldPos.w, worldPos.z / worldPos.z }; + + // Calculate 2d screen position vector + Vector2 screenPosition = { (ndcPos.x + 1.0f)/2.0f*(float)GetScreenWidth(), (ndcPos.y + 1.0f)/2.0f*(float)GetScreenHeight() }; + + return screenPosition; +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions //---------------------------------------------------------------------------------- @@ -1023,6 +1177,35 @@ Vector2 GetTouchPosition(void) return position; } + +// Detect if a button has been pressed once +bool IsButtonPressed(int button) +{ + bool pressed = false; + + if ((currentButtonState[button] != previousButtonState[button]) && (currentButtonState[button] == 0)) pressed = true; + else pressed = false; + + return pressed; +} + +// Detect if a button is being pressed (button held down) +bool IsButtonDown(int button) +{ + if (currentButtonState[button] == 0) return true; + else return false; +} + +// Detect if a button has been released once +bool IsButtonReleased(int button) +{ + bool released = false; + + if ((currentButtonState[button] != previousButtonState[button]) && (currentButtonState[button] == 1)) released = true; + else released = false; + + return released; +} #endif //---------------------------------------------------------------------------------- @@ -1097,7 +1280,7 @@ static void InitDisplay(int width, int height) if (fullscreen) { // At this point we need to manage render size vs screen size - // NOTE: This function use and modify global module variables: screenWidth/screenHeight and renderWidth/renderHeight and downscaleView + // NOTE: This function uses and modifies global module variables: screenWidth/screenHeight and renderWidth/renderHeight and downscaleView SetupFramebufferSize(displayWidth, displayHeight); window = glfwCreateWindow(renderWidth, renderHeight, windowTitle, glfwGetPrimaryMonitor(), NULL); @@ -1212,7 +1395,6 @@ static void InitDisplay(int width, int height) }; EGLint numConfigs; - EGLConfig config; // Get an EGL display connection display = eglGetDisplay(EGL_DEFAULT_DISPLAY); @@ -1446,30 +1628,62 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) if (app->window != NULL) { - // Init device display (monitor, LCD, ...) - InitDisplay(screenWidth, screenHeight); - - // Init OpenGL graphics - InitGraphics(); - - // Load default font for convenience - // NOTE: External function (defined in module: text) - LoadDefaultFont(); - - // Init hi-res timer - InitTimer(); - - // raylib logo appearing animation (if enabled) - if (showLogo) + if (contextRebindRequired) { - SetTargetFPS(60); - LogoAnimation(); + // Reset screen scaling to full display size + EGLint displayFormat; + eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &displayFormat); + ANativeWindow_setBuffersGeometry(app->window, renderWidth, renderHeight, displayFormat); + + // Recreate display surface and re-attach OpenGL context + surface = eglCreateWindowSurface(display, config, app->window, NULL); + eglMakeCurrent(display, surface, surface, context); + + contextRebindRequired = false; + } + else + { + // Init device display (monitor, LCD, ...) + InitDisplay(screenWidth, screenHeight); + + // Init OpenGL graphics + InitGraphics(); + + // Load default font for convenience + // NOTE: External function (defined in module: text) + LoadDefaultFont(); + + // TODO: GPU assets reload in case of lost focus (lost context) + // NOTE: This problem has been solved just unbinding and rebinding context from display + /* + if (assetsReloadRequired) + { + for (int i = 0; i < assetsCount; i++) + { + // TODO: Unload old asset if required + + // Load texture again to pointed texture + (*textureAsset + i) = LoadTexture(assetPath[i]); + } + } + */ + + // Init hi-res timer + InitTimer(); + + // raylib logo appearing animation (if enabled) + if (showLogo) + { + SetTargetFPS(60); // Not required on Android + LogoAnimation(); + } } } } break; case APP_CMD_GAINED_FOCUS: { TraceLog(INFO, "APP_CMD_GAINED_FOCUS"); + appEnabled = true; //ResumeMusicStream(); } break; case APP_CMD_PAUSE: @@ -1480,11 +1694,18 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) { //DrawFrame(); TraceLog(INFO, "APP_CMD_LOST_FOCUS"); + appEnabled = false; //PauseMusicStream(); } break; case APP_CMD_TERM_WINDOW: { - // TODO: Do display destruction here? -> Yes but only display, don't free buffers! + // Dettach OpenGL context and destroy display surface + // NOTE 1: Detaching context before destroying display surface avoids losing our resources (textures, shaders, VBOs...) + // NOTE 2: In some cases (too many context loaded), OS could unload context automatically... :( + eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroySurface(display, surface); + + contextRebindRequired = true; TraceLog(INFO, "APP_CMD_TERM_WINDOW"); } break; @@ -1515,6 +1736,71 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) default: break; } } + +// Android: Get input events +static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) +{ + //http://developer.android.com/ndk/reference/index.html + + int type = AInputEvent_getType(event); + + if (type == AINPUT_EVENT_TYPE_MOTION) + { + touchPosition.x = AMotionEvent_getX(event, 0); + touchPosition.y = AMotionEvent_getY(event, 0); + } + else if (type == AINPUT_EVENT_TYPE_KEY) + { + int32_t keycode = AKeyEvent_getKeyCode(event); + //int32_t AKeyEvent_getMetaState(event); + + // Save current button and its state + currentButtonState[keycode] = AKeyEvent_getAction(event); // Down = 0, Up = 1 + + if (keycode == AKEYCODE_POWER) + { + // Let the OS handle input to avoid app stuck. Behaviour: CMD_PAUSE -> CMD_SAVE_STATE -> CMD_STOP -> CMD_CONFIG_CHANGED -> CMD_LOST_FOCUS + // Resuming Behaviour: CMD_START -> CMD_RESUME -> CMD_CONFIG_CHANGED -> CMD_CONFIG_CHANGED -> CMD_GAINED_FOCUS + // It seems like locking mobile, screen size (CMD_CONFIG_CHANGED) is affected. + // NOTE: AndroidManifest.xml must have + // Before that change, activity was calling CMD_TERM_WINDOW and CMD_DESTROY when locking mobile, so that was not a normal behaviour + return 0; + } + else if ((keycode == AKEYCODE_BACK) || (keycode == AKEYCODE_MENU)) + { + // Eat BACK_BUTTON and AKEYCODE_MENU, just do nothing... and don't let to be handled by OS! + return 1; + } + else if ((keycode == AKEYCODE_VOLUME_UP) || (keycode == AKEYCODE_VOLUME_DOWN)) + { + // Set default OS behaviour + return 0; + } + } + + int32_t action = AMotionEvent_getAction(event); + unsigned int flags = action & AMOTION_EVENT_ACTION_MASK; + + GestureEvent gestureEvent; + + // Register touch actions + if (flags == AMOTION_EVENT_ACTION_DOWN) gestureEvent.touchAction = TOUCH_DOWN; + else if (flags == AMOTION_EVENT_ACTION_UP) gestureEvent.touchAction = TOUCH_UP; + else if (flags == AMOTION_EVENT_ACTION_MOVE) gestureEvent.touchAction = TOUCH_MOVE; + + // Register touch points count + gestureEvent.pointCount = AMotionEvent_getPointerCount(event); + + // Register touch points position + // NOTE: Only two points registered + gestureEvent.position[0] = (Vector2){ AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0) }; + gestureEvent.position[1] = (Vector2){ AMotionEvent_getX(event, 1), AMotionEvent_getY(event, 1) }; + + // Gesture data is sent to gestures system for processing + ProcessGestureEvent(gestureEvent); + + return 0; // return 1; +} #endif #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) @@ -1557,7 +1843,7 @@ static void InitTimer(void) previousTime = GetTime(); // Get time as double } -// Get current time measure since InitTimer() +// Get current time measure (in seconds) since InitTimer() static double GetTime(void) { #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) @@ -1565,7 +1851,7 @@ static double GetTime(void) #elif defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); - uint64_t time = ts.tv_sec*1000000000LLU + (uint64_t)ts.tv_nsec; + uint64_t time = (uint64_t)ts.tv_sec*1000000000LLU + (uint64_t)ts.tv_nsec; return (double)(time - baseTime)*1e-9; #endif @@ -1604,9 +1890,8 @@ static bool GetMouseButtonStatus(int button) static void PollInputEvents(void) { #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) - // Touch events reading (requires gestures module) - touchPosition = GetRawTouchPosition(); - + + // TODO: Remove this requirement... UpdateGestures(); #endif @@ -1636,23 +1921,21 @@ static void PollInputEvents(void) glfwPollEvents(); // Register keyboard/mouse events... and window events! #elif defined(PLATFORM_ANDROID) - // TODO: Check virtual keyboard (?) + // Register previous keys states + for (int i = 0; i < 128; i++) previousButtonState[i] = currentButtonState[i]; // Poll Events (registered events) - // TODO: Enable/disable activityMinimized to block activity if minimized - //while ((ident = ALooper_pollAll(activityMinimized ? 0 : -1, NULL, &events,(void**)&source)) >= 0) - while ((ident = ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0) + // NOTE: Activity is paused if not enabled (appEnabled) + while ((ident = ALooper_pollAll(appEnabled ? 0 : -1, NULL, &events,(void**)&source)) >= 0) { // Process this event if (source != NULL) source->process(app, source); - // Check if we are exiting + // NOTE: Never close window, native activity is controlled by the system! if (app->destroyRequested != 0) { - // NOTE: Never close window, native activity is controlled by the system! //TraceLog(INFO, "Closing Window..."); //windowShouldClose = true; - //ANativeActivity_finish(app->activity); } } @@ -1680,7 +1963,7 @@ static void PollInputEvents(void) int key = keysBuffer[i]; - if (keyboardMode == 2) + if (keyboardMode == 2) // scancodes { // NOTE: If (key == 0x1b), depending on next key, it could be a special keymap code! // Up -> 1b 5b 41 / Left -> 1b 5b 44 / Right -> 1b 5b 43 / Down -> 1b 5b 42 @@ -1715,9 +1998,13 @@ static void PollInputEvents(void) // Detect ESC to stop program if ((key == 0x1b) && (numKeysBuffer == 1)) windowShouldClose = true; } - else if (keyboardMode == 1) + else if (keyboardMode == 1) // keycodes (K_MEDIUMRAW mode) { TraceLog(DEBUG, "Pressed key (keycode): 0x%02x", key); + + // NOTE: Each key is 7-bits (high bit in the byte is 0 for down, 1 for up) + + // TODO: Review (or rewrite) this code... not clear... replace by events! int asciiKey = -1; @@ -2026,6 +2313,59 @@ static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const Emscripte return 0; } + +// Web: Get input events +static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData) +{ + /* + for (int i = 0; i < touchEvent->numTouches; i++) + { + long x, y, id; + + if (!touchEvent->touches[i].isChanged) continue; + + id = touchEvent->touches[i].identifier; + x = touchEvent->touches[i].canvasX; + y = touchEvent->touches[i].canvasY; + } + + printf("%s, numTouches: %d %s%s%s%s\n", emscripten_event_type_to_string(eventType), event->numTouches, + event->ctrlKey ? " CTRL" : "", event->shiftKey ? " SHIFT" : "", event->altKey ? " ALT" : "", event->metaKey ? " META" : ""); + + for(int i = 0; i < event->numTouches; ++i) + { + const EmscriptenTouchPoint *t = &event->touches[i]; + + printf(" %ld: screen: (%ld,%ld), client: (%ld,%ld), page: (%ld,%ld), isChanged: %d, onTarget: %d, canvas: (%ld, %ld)\n", + t->identifier, t->screenX, t->screenY, t->clientX, t->clientY, t->pageX, t->pageY, t->isChanged, t->onTarget, t->canvasX, t->canvasY); + } + */ + + GestureEvent gestureEvent; + + // Register touch actions + if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) gestureEvent.touchAction = TOUCH_DOWN; + else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) gestureEvent.touchAction = TOUCH_UP; + else if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) gestureEvent.touchAction = TOUCH_MOVE; + + // Register touch points count + gestureEvent.pointCount = touchEvent->numTouches; + + // Register touch points position + // NOTE: Only two points registered + // TODO: Touch data should be scaled accordingly! + //gestureEvent.position[0] = (Vector2){ touchEvent->touches[0].canvasX, touchEvent->touches[0].canvasY }; + //gestureEvent.position[1] = (Vector2){ touchEvent->touches[1].canvasX, touchEvent->touches[1].canvasY }; + gestureEvent.position[0] = (Vector2){ touchEvent->touches[0].targetX, touchEvent->touches[0].targetY }; + gestureEvent.position[1] = (Vector2){ touchEvent->touches[1].targetX, touchEvent->touches[1].targetY }; + + touchPosition = gestureEvent.position[0]; + + // Gesture data is sent to gestures system for processing + ProcessGestureEvent(gestureEvent); // Process obtained gestures data + + return 1; +} #endif // Plays raylib logo appearing animation diff --git a/src/easings.h b/src/easings.h new file mode 100644 index 000000000..55dce0df8 --- /dev/null +++ b/src/easings.h @@ -0,0 +1,219 @@ +/******************************************************************************************* +* +* raylib Easings - Useful easing functions for values animation +* +* A port of Robert Penner's easing equations to C (http://robertpenner.com/easing/) +* +* Robert Penner License +* --------------------------------------------------------------------------------- +* Open source under the BSD License. +* +* Copyright (c) 2001 Robert Penner. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* +* - Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* - Neither the name of the author nor the names of contributors may be used +* to endorse or promote products derived from this software without specific +* prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +* IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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) 2015 Ramon Santamaria +* +* This software is provided "as-is", without any express or implied warranty. In no event +* will the authors be held liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented +* as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +**********************************************************************************************/ + +#ifndef EASINGS_H +#define EASINGS_H + +#include + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + +// Linear Easing functions +float EaseLinearNone(float t, float b, float c, float d) { return (c*t/d + b); } +float EaseLinearIn(float t, float b, float c, float d) { return (c*t/d + b); } +float EaseLinearOut(float t, float b, float c, float d) { return (c*t/d + b); } +float EaseLinearInOut(float t,float b, float c, float d) { return (c*t/d + b); } + +// Sine Easing functions +float EaseSineIn(float t, float b, float c, float d) { return (-c*cos(t/d*(PI/2)) + c + b); } +float EaseSineOut(float t, float b, float c, float d) { return (c*sin(t/d*(PI/2)) + b); } +float EaseSineInOut(float t, float b, float c, float d) { return (-c/2*(cos(PI*t/d) - 1) + b); } + +// Circular Easing functions +float EaseCircIn(float t, float b, float c, float d) { return (-c*(sqrt(1 - (t/=d)*t) - 1) + b); } +float EaseCircOut(float t, float b, float c, float d) { return (c*sqrt(1 - (t=t/d-1)*t) + b); } +float EaseCircInOut(float t, float b, float c, float d) +{ + if ((t/=d/2) < 1) return (-c/2*(sqrt(1 - t*t) - 1) + b); + return (c/2*(sqrt(1 - t*(t-=2)) + 1) + b); +} + +// Cubic Easing functions +float EaseCubicIn(float t, float b, float c, float d) { return (c*(t/=d)*t*t + b); } +float EaseCubicOut(float t, float b, float c, float d) { return (c*((t=t/d-1)*t*t + 1) + b); } +float EaseCubicInOut(float t, float b, float c, float d) +{ + if ((t/=d/2) < 1) return (c/2*t*t*t + b); + return (c/2*((t-=2)*t*t + 2) + b); +} + +// Quadratic Easing functions +float EaseQuadIn(float t, float b, float c, float d) { return (c*(t/=d)*t + b); } +float EaseQuadOut(float t, float b, float c, float d) { return (-c*(t/=d)*(t-2) + b); } +float EaseQuadInOut(float t, float b, float c, float d) +{ + if ((t/=d/2) < 1) return (((c/2)*(t*t)) + b); + return (-c/2*(((t-2)*(--t)) - 1) + b); +} + +// Exponential Easing functions +float EaseExpoIn(float t, float b, float c, float d) { return (t == 0) ? b : (c*pow(2, 10*(t/d - 1)) + b); } +float EaseExpoOut(float t, float b, float c, float d) { return (t == d) ? (b + c) : (c*(-pow(2, -10*t/d) + 1) + b); } +float EaseExpoInOut(float t, float b, float c, float d) +{ + if (t == 0) return b; + if (t == d) return (b + c); + if ((t/=d/2) < 1) return (c/2*pow(2, 10*(t - 1)) + b); + + return (c/2*(-pow(2, -10*--t) + 2) + b); +} + +// Back Easing functions +float EaseBackIn(float t, float b, float c, float d) +{ + float s = 1.70158f; + float postFix = t/=d; + return (c*(postFix)*t*((s + 1)*t - s) + b); +} + +float EaseBackOut(float t, float b, float c, float d) +{ + float s = 1.70158f; + return (c*((t=t/d-1)*t*((s + 1)*t + s) + 1) + b); +} + +float EaseBackInOut(float t, float b, float c, float d) +{ + float s = 1.70158f; + if ((t/=d/2) < 1) return (c/2*(t*t*(((s*=(1.525f)) + 1)*t - s)) + b); + + float postFix = t-=2; + return (c/2*((postFix)*t*(((s*=(1.525f)) + 1)*t + s) + 2) + b); +} + +// Bounce Easing functions +float EaseBounceIn(float t, float b, float c, float d) { return (c - EaseBounceOut(d-t, 0, c, d) + b); } +float EaseBounceOut(float t, float b, float c, float d) +{ + if ((t/=d) < (1/2.75f)) + { + return (c*(7.5625f*t*t) + b); + } + else if (t < (2/2.75f)) + { + float postFix = t-=(1.5f/2.75f); + return (c*(7.5625f*(postFix)*t + 0.75f) + b); + } + else if (t < (2.5/2.75)) + { + float postFix = t-=(2.25f/2.75f); + return (c*(7.5625f*(postFix)*t + 0.9375f) + b); + } + else + { + float postFix = t-=(2.625f/2.75f); + return (c*(7.5625f*(postFix)*t + 0.984375f) + b); + } +} + +float EaseBounceInOut(float t, float b, float c, float d) +{ + if (t < d/2) return (EaseBounceIn(t*2, 0, c, d)*0.5f + b); + else return (EaseBounceOut(t*2-d, 0, c, d)*0.5f + c*0.5f + b); +} + +// Elastic Easing functions +float EaseElasticIn(float t, float b, float c, float d) +{ + if (t == 0) return b; + if ((t/=d) == 1) return (b + c); + + float p = d*0.3f; + float a = c; + float s = p/4; + float postFix = a*pow(2, 10*(t-=1)); + + return (-(postFix*sin((t*d-s)*(2*PI)/p )) + b); +} + +float EaseElasticOut(float t, float b, float c, float d) +{ + if (t == 0) return b; + if ((t/=d) == 1) return (b + c); + + float p = d*0.3f; + float a = c; + float s = p/4; + + return (a*pow(2,-10*t)*sin((t*d-s)*(2*PI)/p) + c + b); +} + +float EaseElasticInOut(float t, float b, float c, float d) +{ + if (t == 0) return b; + if ((t/=d/2) == 2) return (b + c); + + float p = d*(0.3f*1.5f); + float a = c; + float s = p/4; + + if (t < 1) + { + float postFix = a*pow(2, 10*(t-=1)); + return -0.5f*(postFix*sin((t*d-s)*(2*PI)/p)) + b; + } + + float postFix = a*pow(2, -10*(t-=1)); + + return (postFix*sin((t*d-s)*(2*PI)/p)*0.5f + c + b); +} + +#ifdef __cplusplus +} +#endif + +#endif // EASINGS_H \ No newline at end of file diff --git a/src/gestures.c b/src/gestures.c index 278f48eed..88cdb528d 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -1,3468 +1,456 @@ +/********************************************************************************************** +* +* raylib Gestures System - Gestures Detection and Usage Functions (Android and HTML5) +* +* Copyright (c) 2015 Marc Palau and Ramon Santamaria +* +* This software is provided "as-is", without any express or implied warranty. In no event +* will the authors be held liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as 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 GESTURES_STANDALONE // NOTE: To use the gestures module as standalone lib, just uncomment this line +#if defined(GESTURES_STANDALONE) + #include "gestures.h" +#else + #include "raylib.h" // Required for typedef(s): Vector2, Gestures +#endif - - - - - - - +#include // malloc(), free() +#include // printf(), fprintf() +#include // Used for ... +#include // Defines int32_t, int64_t + +#if defined(_WIN32) + // Functions required to query time on Windows + int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount); + int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency); +#elif defined(__linux) + #include // Used for clock functions +#endif + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#define FORCE_TO_SWIPE 20 +#define TAP_TIMEOUT 300 +//#define MAX_TOUCH_POINTS 4 + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum { + TYPE_MOTIONLESS, + TYPE_DRAG, + TYPE_DUAL_INPUT +} GestureType; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +static GestureType gestureType = TYPE_MOTIONLESS; +static double eventTime = 0; +//static int32_t touchId; // Not used... + +// Tap gesture variables +static Vector2 initialTapPosition = { 0, 0 }; + +// Double Tap gesture variables +static bool doubleTapping = false; +static bool untap = false; // Check if recently done a tap + +// Drag gesture variables +static Vector2 initialDragPosition = { 0, 0 }; +static Vector2 endDragPosition = { 0, 0 }; +static Vector2 lastDragPosition = { 0, 0 }; +static Vector2 dragVector = { 0, 0 }; + +static float magnitude = 0; // Distance traveled dragging +static float angle = 0; // Angle direction of the drag +static float intensity = 0; // How fast we did the drag (pixels per frame) +static int draggingTimeCounter = 0; // Time that have passed while dragging + +// Pinch gesture variables +static Vector2 firstInitialPinchPosition = { 0, 0 }; +static Vector2 secondInitialPinchPosition = { 0, 0 }; +static Vector2 firstEndPinchPosition = { 0, 0 }; +static Vector2 secondEndPinchPosition = { 0, 0 }; +static float pinchDelta = 0; // Pinch delta displacement + +// Detected gestures +static int previousGesture = GESTURE_NONE; +static int currentGesture = GESTURE_NONE; + +// Enabled gestures flags, all gestures enabled by default +static unsigned int enabledGestures = 0b0000011111111111; + +//---------------------------------------------------------------------------------- +// Module specific Functions Declaration +//---------------------------------------------------------------------------------- +static void InitPinchGesture(Vector2 posA, Vector2 posB); +static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude); +static float VectorDistance(Vector2 v1, Vector2 v2); +static float VectorDotProduct(Vector2 v1, Vector2 v2); +static double GetCurrentTime(); + +//---------------------------------------------------------------------------------- +// Module Functions Definition +//---------------------------------------------------------------------------------- + +// Process gesture event and translate it into gestures +void ProcessGestureEvent(GestureEvent event) +{ + // Resets + dragVector = (Vector2){ 0, 0 }; + pinchDelta = 0; + previousGesture = currentGesture; - raylib/gestures.c at develop · raysan5/raylib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - - - - - - - - - - - - -
- -
-
- - -
-
-
- -
- -
- - -
    - -
  • -
    - -
    - - - - Watch - - - - -
    - -
    -
    -
    -
  • - -
  • - -
    - -
    - - -
    -
    - - -
    - -
  • - -
  • -
    - -
    - -
  • -
- -

- - /raylib - - - - - -

- -
-
-
- -
-
-
- - - -
+ switch (gestureType) + { + case TYPE_MOTIONLESS: // Detect TAP, DOUBLE_TAP and HOLD events + { + if (event.touchAction == TOUCH_DOWN) + { + if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]); + else + { + // Set the press position + initialTapPosition = event.position[0]; + + // If too much time have passed, we reset the double tap + if (GetCurrentTime() - eventTime > TAP_TIMEOUT) untap = false; + + // If we are in time, we detect the double tap + if (untap) doubleTapping = true; + + // Update our event time + eventTime = GetCurrentTime(); + + // Set hold + if (doubleTapping) currentGesture = GESTURE_DOUBLETAP; + else currentGesture = GESTURE_TAP; + } + } + else if (event.touchAction == TOUCH_UP) + { + currentGesture = GESTURE_NONE; + + // Detect that we are tapping instead of holding + if (GetCurrentTime() - eventTime < TAP_TIMEOUT) + { + if (doubleTapping) untap = false; + else untap = true; + } -
-

HTTPS clone URL

-
- - - - -
-
+ // Tap finished + doubleTapping = false; - -
-

SSH clone URL

-
- - - - -
-
+ // Update our event time + eventTime = GetCurrentTime(); + } + // Begin dragging + else if (event.touchAction == TOUCH_MOVE) + { + if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]); + else + { + // Set the drag starting position + initialDragPosition = initialTapPosition; + endDragPosition = initialDragPosition; + + // Initialize drag + draggingTimeCounter = 0; + gestureType = TYPE_DRAG; + currentGesture = GESTURE_NONE; + } + } + } break; + case TYPE_DRAG: // Detect DRAG and SWIPE events + { + // end of the drag + if (event.touchAction == TOUCH_UP) + { + // Return Swipe if we have enough sensitivity + if (intensity > FORCE_TO_SWIPE) + { + if (angle < 30 || angle > 330) currentGesture = GESTURE_SWIPE_RIGHT; // Right + else if (angle > 60 && angle < 120) currentGesture = GESTURE_SWIPE_UP; // Up + else if (angle > 150 && angle < 210) currentGesture = GESTURE_SWIPE_LEFT; // Left + else if (angle > 240 && angle < 300) currentGesture = GESTURE_SWIPE_DOWN; // Down + } + + magnitude = 0; + angle = 0; + intensity = 0; + + gestureType = TYPE_MOTIONLESS; + } + // Update while we are dragging + else if (event.touchAction == TOUCH_MOVE) + { + if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]); + else + { + lastDragPosition = endDragPosition; + endDragPosition = event.position[0]; + + //endDragPosition.x = AMotionEvent_getX(event, 0); + //endDragPosition.y = AMotionEvent_getY(event, 0); + + // Calculate attributes + dragVector = (Vector2){ endDragPosition.x - lastDragPosition.x, endDragPosition.y - lastDragPosition.y }; + magnitude = sqrt(pow(endDragPosition.x - initialDragPosition.x, 2) + pow(endDragPosition.y - initialDragPosition.y, 2)); + angle = CalculateAngle(initialDragPosition, endDragPosition, magnitude); + intensity = magnitude / (float)draggingTimeCounter; + + currentGesture = GESTURE_DRAG; + draggingTimeCounter++; + } + } + } break; + case TYPE_DUAL_INPUT: + { + if (event.touchAction == TOUCH_UP) + { + if (event.pointCount == 1) + { + // Set the drag starting position + initialTapPosition = event.position[0]; + } + gestureType = TYPE_MOTIONLESS; + } + else if (event.touchAction == TOUCH_MOVE) + { + // Adapt the ending position of the inputs + firstEndPinchPosition = event.position[0]; + secondEndPinchPosition = event.position[1]; + + // If there is no more than two inputs + if (event.pointCount == 2) + { + // Calculate distances + float initialDistance = VectorDistance(firstInitialPinchPosition, secondInitialPinchPosition); + float endDistance = VectorDistance(firstEndPinchPosition, secondEndPinchPosition); - -
-

Subversion checkout URL

-
- - - - -
-
+ // Calculate Vectors + Vector2 firstTouchVector = { firstEndPinchPosition.x - firstInitialPinchPosition.x, firstEndPinchPosition.y - firstInitialPinchPosition.y }; + Vector2 secondTouchVector = { secondEndPinchPosition.x - secondInitialPinchPosition.x, secondEndPinchPosition.y - secondInitialPinchPosition.y }; + // Detect the pinch gesture + if (VectorDotProduct(firstTouchVector, secondTouchVector) < -0.5) pinchDelta = initialDistance - endDistance; + else pinchDelta = 0; + + // Pinch gesture resolution + if (pinchDelta != 0) + { + if (pinchDelta > 0) currentGesture = GESTURE_PINCH_IN; + else currentGesture = GESTURE_PINCH_OUT; + } + } + else + { + // Set the drag starting position + initialTapPosition = event.position[0]; + + gestureType = TYPE_MOTIONLESS; + } + + // Readapt the initial position of the inputs + firstInitialPinchPosition = firstEndPinchPosition; + secondInitialPinchPosition = secondEndPinchPosition; + } + } break; + } +} +// Check if a gesture have been detected +bool IsGestureDetected(void) +{ + if (currentGesture != GESTURE_NONE) return true; + else return false; +} -
You can clone with -
,
, or
. - - - -
- - - Clone in Desktop - +// Check gesture type +int GetGestureType(void) +{ + // Get current gesture only if enabled + return (enabledGestures & currentGesture); +} - - - Download ZIP - -
-
-
+void SetGesturesEnabled(unsigned int gestureFlags) +{ + enabledGestures = enabledGestures | gestureFlags; +} - +// Get drag intensity (pixels per frame) +float GetGestureDragIntensity(void) +{ + return intensity; +} - +// Get drag angle +// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise +float GetGestureDragAngle(void) +{ + return angle; +} - +// Get drag vector (between initial and final position) +Vector2 GetGestureDragVector(void) +{ + return dragVector; +} -
+// Hold time measured in frames +int GetGestureHoldDuration(void) +{ + return 0; +} + +// Get magnitude between two pinch points +float GetGesturePinchDelta(void) +{ + return pinchDelta; +} + +// Get angle beween two pinch points +// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise +float GetGesturePinchAngle(void) +{ + return 0; +} + +// Update gestures detected (must be called every frame) +void UpdateGestures(void) +{ + // NOTE: Gestures are processed through system callbacks on touch events -
- - - -
- -
- - - - -
- - -
- - -
- Fetching contributors… -
- -
- - Cannot retrieve contributors at this time -
-
-
-
-
- -
- Raw - Blame - History -
- - - - - -
- -
- -
- -
- 651 lines (535 sloc) - - 22.4 KB -
-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/**********************************************************************************************
*
* raylib Gestures System - Gestures Detection and Usage Functions (Android and HTML5)
*
* Copyright (c) 2015 Marc Palau and Ramon Santamaria
*
* This software is provided "as-is", without any express or implied warranty. In no event
* will the authors be held liable for any damages arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose, including commercial
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not claim that you
* wrote the original software. If you use this software in a product, an acknowledgment
* in the product documentation would be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as 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 GESTURES_STANDALONE // NOTE: To use the gestures module as standalone lib, just uncomment this line
-
#if defined(GESTURES_STANDALONE)
#include "gestures.h"
#else
#include "raylib.h" // Required for typedef(s): Vector2, Gestures
#endif
-
#include <stdlib.h> // malloc(), free()
#include <stdio.h> // printf(), fprintf()
#include <math.h> // Used for ...
#include <stdint.h> // Defines int32_t, int64_t
-
#if defined(_WIN32)
//#define WIN32_LEAN_AND_MEAN
//#include <Windows.h> // ISSUE: Rectangle redeclared, CloseWindow/ShowCursor conflicting types
int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount);
int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency);
#elif defined(__linux)
#include <time.h> // Used for clock functions
#endif
-
#if defined(PLATFORM_ANDROID)
#include <jni.h> // Java native interface
#include <android/sensor.h> // Android sensors functions
#include <android/window.h> // Defines AWINDOW_FLAG_FULLSCREEN and others
#endif
-
#if defined(PLATFORM_WEB)
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
#endif
-
//----------------------------------------------------------------------------------
// Defines and Macros
//----------------------------------------------------------------------------------
#define FORCE_TO_SWIPE 20
#define TAP_TIMEOUT 300
#define MAX_TOUCH_POINTS 4
-
//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef enum {
TYPE_MOTIONLESS,
TYPE_DRAG,
TYPE_DUAL_INPUT
} GestureType;
-
typedef enum {
UP,
DOWN,
MOVE
} ActionType;
-
typedef struct {
ActionType action;
int pointCount;
int pointerId[MAX_TOUCH_POINTS];
Vector2 position[MAX_TOUCH_POINTS];
} GestureEvent;
-
-
//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
static GestureType gestureType = TYPE_MOTIONLESS;
static double eventTime = 0;
//static int32_t touchId; // Not used...
-
// Tap gesture variables
static Vector2 initialTapPosition = { 0, 0 };
-
// Double Tap gesture variables
static bool doubleTapping = false;
static bool untap = false; // Check if recently done a tap
-
// Drag gesture variables
static Vector2 initialDragPosition = { 0, 0 };
static Vector2 endDragPosition = { 0, 0 };
static Vector2 lastDragPosition = { 0, 0 };
static Vector2 dragVector = { 0, 0 };
-
static float magnitude = 0; // Distance traveled dragging
static float angle = 0; // Angle direction of the drag
static float intensity = 0; // How fast we did the drag (pixels per frame)
static int draggingTimeCounter = 0; // Time that have passed while dragging
-
// Pinch gesture variables
static Vector2 firstInitialPinchPosition = { 0, 0 };
static Vector2 secondInitialPinchPosition = { 0, 0 };
static Vector2 firstEndPinchPosition = { 0, 0 };
static Vector2 secondEndPinchPosition = { 0, 0 };
static float pinchDelta = 0; // Pinch delta displacement
-
// Detected gestures
static int previousGesture = GESTURE_NONE;
static int currentGesture = GESTURE_NONE;
-
static unsigned int enabledGestures = 0; // TODO: Currently not in use...
-
static Vector2 rawTouchPosition;
-
//----------------------------------------------------------------------------------
// Module specific Functions Declaration
//----------------------------------------------------------------------------------
static void ProcessMotionEvent(GestureEvent event);
-
static void InitPinchGesture(Vector2 posA, Vector2 posB);
static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, float magnitude);
static float VectorDistance(Vector2 v1, Vector2 v2);
static float VectorDotProduct(Vector2 v1, Vector2 v2);
static double GetCurrentTime();
-
#if defined(PLATFORM_WEB)
static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData);
#endif
-
#if defined(PLATFORM_ANDROID)
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event);
#endif
-
//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
-
// Get touch position (could require further processing depending on display size)
Vector2 GetRawTouchPosition(void)
{
return rawTouchPosition;
}
-
// Check if a gesture have been detected
bool IsGestureDetected(void)
{
if (currentGesture != GESTURE_NONE) return true;
else return false;
}
-
// Check gesture type
int GetGestureType(void)
{
return currentGesture;
}
-
void SetGesturesEnabled(unsigned int gestureFlags)
{
enabledGestures = gestureFlags;
}
-
// Get drag intensity (pixels per frame)
float GetGestureDragIntensity(void)
{
return intensity;
}
-
// Get drag angle
// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
float GetGestureDragAngle(void)
{
return angle;
}
-
// Get drag vector (between initial and final position)
Vector2 GetGestureDragVector(void)
{
return dragVector;
}
-
// Hold time measured in frames
int GetGestureHoldDuration(void)
{
return 0;
}
-
// Get magnitude between two pinch points
float GetGesturePinchDelta(void)
{
return pinchDelta;
}
-
// Get angle beween two pinch points
// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise
float GetGesturePinchAngle(void)
{
return 0;
}
-
#if defined(PLATFORM_WEB)
// Init gestures system (web)
void InitGesturesSystem(void)
{
// Init gestures system web (emscripten)
// NOTE: Some code examples
//emscripten_set_touchstart_callback(0, NULL, 1, Emscripten_HandleTouch);
//emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch);
emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenInputCallback);
emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenInputCallback);
emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenInputCallback);
emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenInputCallback);
}
#elif defined(PLATFORM_ANDROID)
// Init gestures system (android)
void InitGesturesSystem(struct android_app *app)
{
app->onInputEvent = AndroidInputCallback;
// TODO: Receive frameBuffer data: displayWidth/displayHeight, renderWidth/renderHeight, screenWidth/screenHeight
}
#endif
-
// Update gestures detected (must be called every frame)
void UpdateGestures(void)
{
// NOTE: Gestures are processed through system callbacks on touch events
if ((previousGesture == GESTURE_TAP) && (currentGesture == GESTURE_TAP)) currentGesture = GESTURE_HOLD;
else if (currentGesture != GESTURE_HOLD) currentGesture = GESTURE_NONE;
}
-
//----------------------------------------------------------------------------------
// Module specific Functions Definition
//----------------------------------------------------------------------------------
static void ProcessMotionEvent(GestureEvent event)
{
// Resets
dragVector = (Vector2){ 0, 0 };
pinchDelta = 0;
previousGesture = currentGesture;
switch (gestureType)
{
case TYPE_MOTIONLESS: // Detect TAP, DOUBLE_TAP and HOLD events
{
if (event.action == DOWN)
{
if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
else
{
// Set the press position
initialTapPosition = event.position[0];
// If too much time have passed, we reset the double tap
if (GetCurrentTime() - eventTime > TAP_TIMEOUT) untap = false;
// If we are in time, we detect the double tap
if (untap) doubleTapping = true;
// Update our event time
eventTime = GetCurrentTime();
// Set hold
if (doubleTapping) currentGesture = GESTURE_DOUBLETAP;
else currentGesture = GESTURE_TAP;
}
}
else if (event.action == UP)
{
currentGesture = GESTURE_NONE;
-
// Detect that we are tapping instead of holding
if (GetCurrentTime() - eventTime < TAP_TIMEOUT)
{
if (doubleTapping) untap = false;
else untap = true;
}
// Tap finished
doubleTapping = false;
-
// Update our event time
eventTime = GetCurrentTime();
}
// Begin dragging
else if (event.action == MOVE)
{
if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
else
{
// Set the drag starting position
initialDragPosition = initialTapPosition;
endDragPosition = initialDragPosition;
// Initialize drag
draggingTimeCounter = 0;
gestureType = TYPE_DRAG;
currentGesture = GESTURE_NONE;
}
}
} break;
case TYPE_DRAG: // Detect DRAG and SWIPE events
{
// end of the drag
if (event.action == UP)
{
// Return Swipe if we have enough sensitivity
if (intensity > FORCE_TO_SWIPE)
{
if (angle < 30 || angle > 330) currentGesture = GESTURE_SWIPE_RIGHT; // Right
else if (angle > 60 && angle < 120) currentGesture = GESTURE_SWIPE_UP; // Up
else if (angle > 150 && angle < 210) currentGesture = GESTURE_SWIPE_LEFT; // Left
else if (angle > 240 && angle < 300) currentGesture = GESTURE_SWIPE_DOWN; // Down
}
magnitude = 0;
angle = 0;
intensity = 0;
gestureType = TYPE_MOTIONLESS;
}
// Update while we are dragging
else if (event.action == MOVE)
{
if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]);
else
{
lastDragPosition = endDragPosition;
endDragPosition = rawTouchPosition;
//endDragPosition.x = AMotionEvent_getX(event, 0);
//endDragPosition.y = AMotionEvent_getY(event, 0);
// Calculate attributes
dragVector = (Vector2){ endDragPosition.x - lastDragPosition.x, endDragPosition.y - lastDragPosition.y };
magnitude = sqrt(pow(endDragPosition.x - initialDragPosition.x, 2) + pow(endDragPosition.y - initialDragPosition.y, 2));
angle = CalculateAngle(initialDragPosition, endDragPosition, magnitude);
intensity = magnitude / (float)draggingTimeCounter;
currentGesture = GESTURE_DRAG;
draggingTimeCounter++;
}
}
} break;
case TYPE_DUAL_INPUT:
{
if (event.action == UP)
{
if (event.pointCount == 1)
{
// Set the drag starting position
initialTapPosition = event.position[0];
}
gestureType = TYPE_MOTIONLESS;
}
else if (event.action == MOVE)
{
// Adapt the ending position of the inputs
firstEndPinchPosition = event.position[0];
secondEndPinchPosition = event.position[1];
// If there is no more than two inputs
if (event.pointCount == 2)
{
// Calculate distances
float initialDistance = VectorDistance(firstInitialPinchPosition, secondInitialPinchPosition);
float endDistance = VectorDistance(firstEndPinchPosition, secondEndPinchPosition);
-
// Calculate Vectors
Vector2 firstTouchVector = { firstEndPinchPosition.x - firstInitialPinchPosition.x, firstEndPinchPosition.y - firstInitialPinchPosition.y };
Vector2 secondTouchVector = { secondEndPinchPosition.x - secondInitialPinchPosition.x, secondEndPinchPosition.y - secondInitialPinchPosition.y };
-
// Detect the pinch gesture
if (VectorDotProduct(firstTouchVector, secondTouchVector) < -0.5) pinchDelta = initialDistance - endDistance;
else pinchDelta = 0;
// Pinch gesture resolution
if (pinchDelta != 0)
{
if (pinchDelta > 0) currentGesture = GESTURE_PINCH_IN;
else currentGesture = GESTURE_PINCH_OUT;
}
}
else
{
// Set the drag starting position
initialTapPosition = event.position[0];
gestureType = TYPE_MOTIONLESS;
}
// Readapt the initial position of the inputs
firstInitialPinchPosition = firstEndPinchPosition;
secondInitialPinchPosition = secondEndPinchPosition;
}
} break;
}
//--------------------------------------------------------------------
}
-
static float CalculateAngle(Vector2 initialPosition, Vector2 finalPosition, float magnitude)
{
float angle;
// Calculate arcsinus of the movement
angle = asin((finalPosition.y - initialPosition.y)/magnitude);
angle *= RAD2DEG;
// Calculate angle depending on the sector
if ((finalPosition.x - initialPosition.x) >= 0)
{
// Sector 4
if ((finalPosition.y - initialPosition.y) >= 0)
{
angle *= -1;
angle += 360;
}
// Sector 1
else angle *= -1;
}
else
{
// Sector 3
if ((finalPosition.y - initialPosition.y) >= 0) angle += 180;
// Sector 2
else
{
angle *= -1;
angle = 180 - angle;
}
}
return angle;
}
-
static void InitPinchGesture(Vector2 posA, Vector2 posB)
{
initialDragPosition = (Vector2){ 0, 0 };
endDragPosition = (Vector2){ 0, 0 };
lastDragPosition = (Vector2){ 0, 0 };
-
// Initialize positions
firstInitialPinchPosition = posA;
secondInitialPinchPosition = posB;
firstEndPinchPosition = firstInitialPinchPosition;
secondEndPinchPosition = secondInitialPinchPosition;
// Resets
magnitude = 0;
angle = 0;
intensity = 0;
-
gestureType = TYPE_DUAL_INPUT;
}
-
static float VectorDistance(Vector2 v1, Vector2 v2)
{
float result;
-
float dx = v2.x - v1.x;
float dy = v2.y - v1.y;
-
result = sqrt(dx*dx + dy*dy);
-
return result;
}
-
static float VectorDotProduct(Vector2 v1, Vector2 v2)
{
float result;
-
float v1Module = sqrt(v1.x*v1.x + v1.y*v1.y);
float v2Module = sqrt(v2.x*v2.x + v2.y*v2.y);
Vector2 v1Normalized = { v1.x / v1Module, v1.y / v1Module };
Vector2 v2Normalized = { v2.x / v2Module, v2.y / v2Module };
result = v1Normalized.x*v2Normalized.x + v1Normalized.y*v2Normalized.y;
-
return result;
}
-
static double GetCurrentTime()
{
double time = 0;
#if defined(_WIN32)
/*
// NOTE: Requires Windows.h
FILETIME tm;
GetSystemTimePreciseAsFileTime(&tm);
ULONGLONG nowTime = ((ULONGLONG)tm.dwHighDateTime << 32) | (ULONGLONG)tm.dwLowDateTime; // Time provided in 100-nanosecond intervals
time = ((double)nowTime/10000000.0); // time in seconds
*/
/*
double pcFreq = 0.0;
__int64 counterStart = 0; // In C99 defined a standard 64-bit integer type named int64_t and unsigned version uint64_t in stdint.h.
//int64_t or uint64_t is type defined as long long or unsigned long long in C99's stdint.h.
//LARGE_INTEGER li; // Represents a 64-bit signed integer value
//li.QuadPart // A signed 64-bit integer
unsigned long long int li; // __int64, same as long long
if(!QueryPerformanceFrequency(&li)) return 0;
pcFreq = (double)(li)/1000.0;
QueryPerformanceCounter(&li);
counterStart = li;
unsigned long long int tm;
QueryPerformanceCounter(&tm);
time = (double)(tm - counterStart)/pcFreq;
*/
unsigned long long int tm, tf;
time = (double)(QueryPerformanceCounter(&tm)/QueryPerformanceFrequency(&tf)); // time in seconds
#endif
-
#if defined(__linux)
// NOTE: Only for Linux-based systems
struct timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
uint64_t nowTime = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec; // Time provided in nanoseconds
time = ((double)nowTime/1000000.0); // time in miliseconds
#endif
-
return time;
}
-
#if defined(PLATFORM_ANDROID)
// Android: Get input events
static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event)
{
int type = AInputEvent_getType(event);
-
if (type == AINPUT_EVENT_TYPE_MOTION)
{
rawTouchPosition.x = AMotionEvent_getX(event, 0);
rawTouchPosition.y = AMotionEvent_getY(event, 0);
}
else if (type == AINPUT_EVENT_TYPE_KEY)
{
//int32_t key = AKeyEvent_getKeyCode(event);
//int32_t AKeyEvent_getMetaState(event);
//int32_t code = AKeyEvent_getKeyCode((const AInputEvent *)event);
// If we are in active mode, we eat the back button and move into pause mode.
// If we are already in pause mode, we allow the back button to be handled by the OS, which means we'll be shut down.
/*
if ((code == AKEYCODE_BACK) && mActiveMode)
{
setActiveMode(false);
return 1;
}
*/
}
int32_t action = AMotionEvent_getAction(event);
unsigned int flags = action & AMOTION_EVENT_ACTION_MASK;
GestureEvent gestureEvent;
// Action
if (flags == AMOTION_EVENT_ACTION_DOWN) gestureEvent.action = DOWN;
else if (flags == AMOTION_EVENT_ACTION_UP) gestureEvent.action = UP;
else if (flags == AMOTION_EVENT_ACTION_MOVE) gestureEvent.action = MOVE;
// Points
gestureEvent.pointCount = AMotionEvent_getPointerCount(event);
// Position
gestureEvent.position[0] = (Vector2){ AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0) };
gestureEvent.position[1] = (Vector2){ AMotionEvent_getX(event, 1), AMotionEvent_getY(event, 1) };
ProcessMotionEvent(gestureEvent);
-
return 0; // return 1;
}
#endif
-
#if defined(PLATFORM_WEB)
// Web: Get input events
static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
{
/*
for (int i = 0; i < touchEvent->numTouches; i++)
{
long x, y, id;
if (!touchEvent->touches[i].isChanged) continue;
id = touchEvent->touches[i].identifier;
x = touchEvent->touches[i].canvasX;
y = touchEvent->touches[i].canvasY;
}
printf("%s, numTouches: %d %s%s%s%s\n", emscripten_event_type_to_string(eventType), event->numTouches,
event->ctrlKey ? " CTRL" : "", event->shiftKey ? " SHIFT" : "", event->altKey ? " ALT" : "", event->metaKey ? " META" : "");
for(int i = 0; i < event->numTouches; ++i)
{
const EmscriptenTouchPoint *t = &event->touches[i];
printf(" %ld: screen: (%ld,%ld), client: (%ld,%ld), page: (%ld,%ld), isChanged: %d, onTarget: %d, canvas: (%ld, %ld)\n",
t->identifier, t->screenX, t->screenY, t->clientX, t->clientY, t->pageX, t->pageY, t->isChanged, t->onTarget, t->canvasX, t->canvasY);
}
*/
GestureEvent gestureEvent;
// Action
if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) gestureEvent.action = DOWN;
else if (eventType == EMSCRIPTEN_EVENT_TOUCHEND) gestureEvent.action = UP;
else if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) gestureEvent.action = MOVE;
// Points
gestureEvent.pointCount = touchEvent->numTouches;
// Position
//gestureEvent.position[0] = (Vector2){ touchEvent->touches[0].canvasX, touchEvent->touches[0].canvasY };
//gestureEvent.position[1] = (Vector2){ touchEvent->touches[1].canvasX, touchEvent->touches[1].canvasY };
gestureEvent.position[0] = (Vector2){ touchEvent->touches[0].targetX, touchEvent->touches[0].targetY };
gestureEvent.position[1] = (Vector2){ touchEvent->touches[1].targetX, touchEvent->touches[1].targetY };
printf("EVENT DETECTED!\n");
rawTouchPosition = gestureEvent.position[0];
ProcessMotionEvent(gestureEvent);
-
return 1;
}
#endif
- -
- -
- -Jump to Line - - -
-
- -
-
- - -
- -
- -
- + if ((previousGesture == GESTURE_TAP) && (currentGesture == GESTURE_TAP)) currentGesture = GESTURE_HOLD; + else if (currentGesture != GESTURE_HOLD) currentGesture = GESTURE_NONE; +} +//---------------------------------------------------------------------------------- +// Module specific Functions Definition +//---------------------------------------------------------------------------------- +static float CalculateAngle(Vector2 initialPosition, Vector2 finalPosition, float magnitude) +{ + float angle; + // Calculate arcsinus of the movement + angle = asin((finalPosition.y - initialPosition.y)/magnitude); + angle *= RAD2DEG; + // Calculate angle depending on the sector + if ((finalPosition.x - initialPosition.x) >= 0) + { + // Sector 4 + if ((finalPosition.y - initialPosition.y) >= 0) + { + angle *= -1; + angle += 360; + } + // Sector 1 + else angle *= -1; + } + else + { + // Sector 3 + if ((finalPosition.y - initialPosition.y) >= 0) angle += 180; + // Sector 2 + else + { + angle *= -1; + angle = 180 - angle; + } + } + return angle; +} -
- - - Something went wrong with that request. Please try again. -
+static void InitPinchGesture(Vector2 posA, Vector2 posB) +{ + initialDragPosition = (Vector2){ 0, 0 }; + endDragPosition = (Vector2){ 0, 0 }; + lastDragPosition = (Vector2){ 0, 0 }; + // Initialize positions + firstInitialPinchPosition = posA; + secondInitialPinchPosition = posB; + + firstEndPinchPosition = firstInitialPinchPosition; + secondEndPinchPosition = secondInitialPinchPosition; + + // Resets + magnitude = 0; + angle = 0; + intensity = 0; - - - - - - - + gestureType = TYPE_DUAL_INPUT; +} +static float VectorDistance(Vector2 v1, Vector2 v2) +{ + float result; + + float dx = v2.x - v1.x; + float dy = v2.y - v1.y; + + result = sqrt(dx*dx + dy*dy); + + return result; +} + +static float VectorDotProduct(Vector2 v1, Vector2 v2) +{ + float result; + + float v1Module = sqrt(v1.x*v1.x + v1.y*v1.y); + float v2Module = sqrt(v2.x*v2.x + v2.y*v2.y); + + Vector2 v1Normalized = { v1.x / v1Module, v1.y / v1Module }; + Vector2 v2Normalized = { v2.x / v2Module, v2.y / v2Module }; + + result = v1Normalized.x*v2Normalized.x + v1Normalized.y*v2Normalized.y; + + return result; +} + +static double GetCurrentTime() +{ + double time = 0; + +#if defined(_WIN32) + unsigned long long int clockFrequency, currentTime; + + QueryPerformanceFrequency(&clockFrequency); + QueryPerformanceCounter(¤tTime); + + time = (double)currentTime/clockFrequency*1000.0f; // time in miliseconds +#endif + +#if defined(__linux) + // NOTE: Only for Linux-based systems + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + uint64_t nowTime = (uint64_t)now.tv_sec*1000000000LLU + (uint64_t)now.tv_nsec; // Time provided in nanoseconds + + time = ((double)nowTime/1000000.0); // time in miliseconds +#endif + + return time; +} diff --git a/src/gestures.h b/src/gestures.h index 896f30281..b5cf2767c 100644 --- a/src/gestures.h +++ b/src/gestures.h @@ -67,6 +67,17 @@ typedef enum { GESTURE_PINCH_OUT = 1024 } Gestures; +typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction; + +// Gesture events +// NOTE: MAX_TOUCH_POINTS fixed to 4 +typedef struct { + int touchAction; + int pointCount; + int pointerId[4]; + Vector2 position[4]; +} GestureEvent; + #ifdef __cplusplus extern "C" { // Prevents name mangling of functions #endif @@ -79,19 +90,11 @@ extern "C" { // Prevents name mangling of functions //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- -int GetTouchX(void); // Returns touch position X (relative to screen size) -int GetTouchY(void); // Returns touch position Y (relative to screen size) -Vector2 GetTouchPosition(void); // Returns touch position XY (relative to screen size) - -#if defined(PLATFORM_WEB) -void InitGesturesSystem(void); // Init gestures system (web) -#elif defined(PLATFORM_ANDROID) -void InitGesturesSystem(struct android_app *app); // Init gestures system (android) -#endif void UpdateGestures(void); // Update gestures detected (must be called every frame) bool IsGestureDetected(void); // Check if a gesture have been detected int GetGestureType(void); // Get latest detected gesture void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags +void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures float GetGestureDragIntensity(void); // Get gesture drag intensity float GetGestureDragAngle(void); // Get gesture drag angle diff --git a/src/makefile b/src/makefile index 3cb237e6c..70fbca7cc 100644 --- a/src/makefile +++ b/src/makefile @@ -1,1551 +1,181 @@ - - - - - - - - - - - - - raylib/makefile at develop · raysan5/raylib - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Skip to content - - - - - - - - - - - - - - -
- -
-
- - -
-
-
- -
- -
- - -
    - -
  • -
    - -
    - - - - Watch - - - - -
    - -
    -
    -
    -
  • - -
  • - -
    - -
    - - -
    -
    - - -
    - -
  • - -
  • -
    - -
    - -
  • -
- -

- - /raylib - - - - - -

- -
-
-
- -
-
-
- - - -
- -
-

HTTPS clone URL

-
- - - - -
-
- - -
-

SSH clone URL

-
- - - - -
-
- - -
-

Subversion checkout URL

-
- - - - -
-
- - - -
You can clone with -
,
, or
. - - - -
- - - Clone in Desktop - - - - - Download ZIP - -
-
-
- - - - - - - -
- -
- - - -
- -
- - - - -
- - -
- - -
- Fetching contributors… -
- -
- - Cannot retrieve contributors at this time -
-
-
-
-
- -
- Raw - Blame - History -
- - - - - -
- -
- -
- -
- 182 lines (156 sloc) - - 5.78 KB -
-
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#**************************************************************************************************
#
# raylib makefile for desktop platforms, Raspberry Pi and HTML5 (emscripten)
#
# Copyright (c) 2014 Ramon Santamaria (@raysan5)
#
# This software is provided "as-is", without any express or implied warranty. In no event
# will the authors be held liable for any damages arising from the use of this software.
#
# Permission is granted to anyone to use this software for any purpose, including commercial
# applications, and to alter it and redistribute it freely, subject to the following restrictions:
#
# 1. The origin of this software must not be misrepresented; you must not claim that you
# wrote the original software. If you use this software in a product, an acknowledgment
# in the product documentation would be appreciated but is not required.
#
# 2. Altered source versions must be plainly marked as 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 raylib platform to compile for
# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB
PLATFORM ?= PLATFORM_DESKTOP
-
# determine PLATFORM_OS in case PLATFORM_DESKTOP selected
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
# No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows
ifeq ($(OS),Windows_NT)
PLATFORM_OS=WINDOWS
else
UNAMEOS:=$(shell uname)
ifeq ($(UNAMEOS),Linux)
PLATFORM_OS=LINUX
else
ifeq ($(UNAMEOS),Darwin)
PLATFORM_OS=OSX
endif
endif
endif
endif
-
# define raylib graphics api depending on selected platform
ifeq ($(PLATFORM),PLATFORM_RPI)
# define raylib graphics api to use (on RPI, OpenGL ES 2.0 must be used)
GRAPHICS = GRAPHICS_API_OPENGL_ES2
else
# define raylib graphics api to use (OpenGL 1.1 by default)
GRAPHICS ?= GRAPHICS_API_OPENGL_11
#GRAPHICS = GRAPHICS_API_OPENGL_33 # Uncomment to use OpenGL 3.3
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
GRAPHICS = GRAPHICS_API_OPENGL_ES2
endif
-
# NOTE: makefiles targets require tab indentation
-
# define compiler: gcc for C program, define as g++ for C++
ifeq ($(PLATFORM),PLATFORM_WEB)
# define emscripten compiler
CC = emcc
else
# define default gcc compiler
CC = gcc
endif
-
# define compiler flags:
# -O1 defines optimization level
# -Wall turns on most, but not all, compiler warnings
# -std=c99 defines C language mode (standard C from 1999 revision)
# -std=gnu99 defines C language mode (GNU C from 1999 revision)
# -fgnu89-inline declaring inline functions support (GCC optimized, faster)
CFLAGS = -O1 -Wall -std=gnu99 -fgnu89-inline
-
#CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes
-
# define any directories containing required header files
ifeq ($(PLATFORM),PLATFORM_RPI)
INCLUDES = -I. -I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/linux -I/opt/vc/include/interface/vcos/pthreads
else
INCLUDES = -I. -I../src
# external libraries headers
# GLFW3
INCLUDES += -I../external/glfw3/include
# GLEW
INCLUDES += -I../external/glew/include
# OpenAL Soft
INCLUDES += -I../external/openal_soft/include
endif
-
# define all object files required
OBJS = core.o rlgl.o raymath.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o stb_vorbis.o
-
# typing 'make' will invoke the first target entry in the file,
# in this case, the 'default' target entry is raylib
default: raylib
-
# compile raylib library
raylib: $(OBJS)
ifeq ($(PLATFORM),PLATFORM_WEB)
emcc -O1 $(OBJS) -o libraylib.bc
else
ar rcs libraylib.a $(OBJS)
endif
-
# compile core module
# emcc core.c -o core.bc -DPLATFORM_DESKTOP
core.o: core.c
$(CC) -c core.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS)
-
# compile rlgl module
rlgl.o: rlgl.c
$(CC) -c rlgl.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS)
-
# compile raymath module
raymath.o: raymath.c
$(CC) -c raymath.c $(CFLAGS) $(INCLUDES)
-
# compile shapes module
shapes.o: shapes.c
$(CC) -c shapes.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS)
-
# compile textures module
textures.o: textures.c
$(CC) -c textures.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS)
-
# compile text module
text.o: text.c
$(CC) -c text.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS)
-
# compile models module
models.o: models.c
$(CC) -c models.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS)
-
# compile audio module
audio.o: audio.c
$(CC) -c audio.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
# compile stb_vorbis library
stb_vorbis.o: stb_vorbis.c
$(CC) -c stb_vorbis.c -O1 $(INCLUDES) -D$(PLATFORM)
-
# compile utils module
utils.o: utils.c
$(CC) -c utils.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
-
# compile camera module
camera.o: camera.c
$(CC) -c camera.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
-
# compile gestures module
gestures.o: gestures.c
$(CC) -c gestures.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM)
-
# clean everything
clean:
ifeq ($(PLATFORM),PLATFORM_DESKTOP)
ifeq ($(PLATFORM_OS),OSX)
rm -f *.o libraylib.a
else
ifeq ($(PLATFORM_OS),LINUX)
find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f
else
del *.o libraylib.a
endif
endif
endif
ifeq ($(PLATFORM),PLATFORM_RPI)
rm -f *.o libraylib.a
endif
ifeq ($(PLATFORM),PLATFORM_WEB)
del *.o libraylib.bc
endif
@echo Cleaning done
-
# instead of defining every module one by one, we can define a pattern
# this pattern below will automatically compile every module defined on $(OBJS)
#%.o : %.c
# $(CC) -c $< $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS)
- -
- -
- -Jump to Line - - -
-
- -
-
- - -
- -
- -
- - - - - - - -
- - - Something went wrong with that request. Please try again. -
- - - - - - - - - - +#************************************************************************************************** +# +# raylib makefile for desktop platforms, Raspberry Pi and HTML5 (emscripten) +# +# Copyright (c) 2014 Ramon Santamaria (@raysan5) +# +# This software is provided "as-is", without any express or implied warranty. In no event +# will the authors be held liable for any damages arising from the use of this software. +# +# Permission is granted to anyone to use this software for any purpose, including commercial +# applications, and to alter it and redistribute it freely, subject to the following restrictions: +# +# 1. The origin of this software must not be misrepresented; you must not claim that you +# wrote the original software. If you use this software in a product, an acknowledgment +# in the product documentation would be appreciated but is not required. +# +# 2. Altered source versions must be plainly marked as 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 raylib platform to compile for +# possible platforms: PLATFORM_DESKTOP PLATFORM_RPI PLATFORM_WEB +PLATFORM ?= PLATFORM_DESKTOP + +# determine PLATFORM_OS in case PLATFORM_DESKTOP selected +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + # No uname.exe on MinGW!, but OS=Windows_NT on Windows! ifeq ($(UNAME),Msys) -> Windows + ifeq ($(OS),Windows_NT) + PLATFORM_OS=WINDOWS + else + UNAMEOS:=$(shell uname) + ifeq ($(UNAMEOS),Linux) + PLATFORM_OS=LINUX + else + ifeq ($(UNAMEOS),Darwin) + PLATFORM_OS=OSX + endif + endif + endif +endif + +# define raylib graphics api depending on selected platform +ifeq ($(PLATFORM),PLATFORM_RPI) + # define raylib graphics api to use (on RPI, OpenGL ES 2.0 must be used) + GRAPHICS = GRAPHICS_API_OPENGL_ES2 +else + # define raylib graphics api to use (OpenGL 1.1 by default) + GRAPHICS ?= GRAPHICS_API_OPENGL_11 + #GRAPHICS = GRAPHICS_API_OPENGL_33 # Uncomment to use OpenGL 3.3 +endif +ifeq ($(PLATFORM),PLATFORM_WEB) + GRAPHICS = GRAPHICS_API_OPENGL_ES2 +endif + +# NOTE: makefiles targets require tab indentation + +# define compiler: gcc for C program, define as g++ for C++ +ifeq ($(PLATFORM),PLATFORM_WEB) + # define emscripten compiler + CC = emcc +else + # define default gcc compiler + CC = gcc +endif + +# define compiler flags: +# -O1 defines optimization level +# -Wall turns on most, but not all, compiler warnings +# -std=c99 defines C language mode (standard C from 1999 revision) +# -std=gnu99 defines C language mode (GNU C from 1999 revision) +# -fgnu89-inline declaring inline functions support (GCC optimized, faster) +CFLAGS = -O1 -Wall -std=gnu99 -fgnu89-inline + +#CFLAGSEXTRA = -Wextra -Wmissing-prototypes -Wstrict-prototypes + +# define any directories containing required header files +ifeq ($(PLATFORM),PLATFORM_RPI) + INCLUDES = -I. -I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/linux -I/opt/vc/include/interface/vcos/pthreads +else + INCLUDES = -I. -I../src +# external libraries headers +# GLFW3 + INCLUDES += -I../external/glfw3/include +# GLEW + INCLUDES += -I../external/glew/include +# OpenAL Soft + INCLUDES += -I../external/openal_soft/include +endif + +# define all object files required +OBJS = core.o rlgl.o raymath.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o stb_vorbis.o + +# typing 'make' will invoke the first target entry in the file, +# in this case, the 'default' target entry is raylib +default: raylib + +# compile raylib library +raylib: $(OBJS) +ifeq ($(PLATFORM),PLATFORM_WEB) + emcc -O1 $(OBJS) -o libraylib.bc +else + ar rcs libraylib.a $(OBJS) +endif + +# compile core module +# emcc core.c -o core.bc -DPLATFORM_DESKTOP +core.o: core.c + $(CC) -c core.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) + +# compile rlgl module +rlgl.o: rlgl.c + $(CC) -c rlgl.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) + +# compile raymath module +raymath.o: raymath.c + $(CC) -c raymath.c $(CFLAGS) $(INCLUDES) + +# compile shapes module +shapes.o: shapes.c + $(CC) -c shapes.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) + +# compile textures module +textures.o: textures.c + $(CC) -c textures.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) + +# compile text module +text.o: text.c + $(CC) -c text.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) + +# compile models module +models.o: models.c + $(CC) -c models.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) + +# compile audio module +audio.o: audio.c + $(CC) -c audio.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile stb_vorbis library +stb_vorbis.o: stb_vorbis.c + $(CC) -c stb_vorbis.c -O1 $(INCLUDES) -D$(PLATFORM) + +# compile utils module +utils.o: utils.c + $(CC) -c utils.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile camera module +camera.o: camera.c + $(CC) -c camera.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# compile gestures module +gestures.o: gestures.c + $(CC) -c gestures.c $(CFLAGS) $(INCLUDES) -D$(PLATFORM) + +# clean everything +clean: +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + ifeq ($(PLATFORM_OS),OSX) + rm -f *.o libraylib.a + else + ifeq ($(PLATFORM_OS),LINUX) + find -type f -executable | xargs file -i | grep -E 'x-object|x-archive|x-sharedlib|x-executable' | rev | cut -d ':' -f 2- | rev | xargs rm -f + else + del *.o libraylib.a + endif + endif +endif +ifeq ($(PLATFORM),PLATFORM_RPI) + rm -f *.o libraylib.a +endif +ifeq ($(PLATFORM),PLATFORM_WEB) + del *.o libraylib.bc +endif + @echo Cleaning done + +# instead of defining every module one by one, we can define a pattern +# this pattern below will automatically compile every module defined on $(OBJS) +#%.o : %.c +# $(CC) -c $< $(CFLAGS) $(INCLUDES) -D$(PLATFORM) -D$(GRAPHICS) diff --git a/src/models.c b/src/models.c index f7e39863c..06044820a 100644 --- a/src/models.c +++ b/src/models.c @@ -56,7 +56,7 @@ extern unsigned int whiteTexture; // Module specific Functions Declaration //---------------------------------------------------------------------------------- static float GetHeightValue(Color pixel); -static VertexData LoadOBJ(const char *fileName); +static Mesh LoadOBJ(const char *fileName); //---------------------------------------------------------------------------------- // Module Functions Definition @@ -64,7 +64,7 @@ static VertexData LoadOBJ(const char *fileName); // Draw cube // NOTE: Cube position is the center position -void DrawCube(Vector3 position, float width, float height, float lenght, Color color) +void DrawCube(Vector3 position, float width, float height, float length, Color color) { float x = 0.0f; float y = 0.0f; @@ -81,58 +81,58 @@ void DrawCube(Vector3 position, float width, float height, float lenght, Color c rlColor4ub(color.r, color.g, color.b, color.a); // Front Face ----------------------------------------------------- - rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left - rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right - rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left + rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left - rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Right - rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left - rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right + rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right // Back Face ------------------------------------------------------ - rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Left - rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left - rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right + rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left + rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right - rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right - rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right - rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left + rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right + rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left // Top Face ------------------------------------------------------- - rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left - rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Bottom Left - rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Bottom Right + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left + rlVertex3f(x-width/2, y+height/2, z+length/2); // Bottom Left + rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right - rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right - rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left - rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Bottom Right + rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left + rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right // Bottom Face ---------------------------------------------------- - rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Top Left - rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right - rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left + rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right + rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left - rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Top Right - rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right - rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Top Left + rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Right + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right + rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left // Right face ----------------------------------------------------- - rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right - rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right - rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Left + rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right + rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right + rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left - rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Left - rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right - rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Left + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Left + rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right + rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left // Left Face ------------------------------------------------------ - rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Right - rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left - rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Right + rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Right - rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left - rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left - rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Right + rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left + rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right rlEnd(); rlPopMatrix(); } @@ -144,7 +144,7 @@ void DrawCubeV(Vector3 position, Vector3 size, Color color) } // Draw cube wires -void DrawCubeWires(Vector3 position, float width, float height, float lenght, Color color) +void DrawCubeWires(Vector3 position, float width, float height, float length, Color color) { float x = 0.0f; float y = 0.0f; @@ -160,62 +160,62 @@ void DrawCubeWires(Vector3 position, float width, float height, float lenght, Co // Front Face ----------------------------------------------------- // Bottom Line - rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left - rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right + rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right // Left Line - rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right - rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Right + rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right + rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right // Top Line - rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Right - rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left + rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left // Right Line - rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left - rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left + rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left // Back Face ------------------------------------------------------ // Bottom Line - rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Left - rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right + rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left + rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right // Left Line - rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right - rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right + rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right + rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right // Top Line - rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right - rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left + rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left // Right Line - rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left - rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Left + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left + rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left // Top Face ------------------------------------------------------- // Left Line - rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left Front - rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left Back + rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left Front + rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left Back // Right Line - rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Right Front - rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right Back + rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right Front + rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right Back // Bottom Face --------------------------------------------------- // Left Line - rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Top Left Front - rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Top Left Back + rlVertex3f(x-width/2, y-height/2, z+length/2); // Top Left Front + rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Left Back // Right Line - rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Top Right Front - rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Top Right Back + rlVertex3f(x+width/2, y-height/2, z+length/2); // Top Right Front + rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Right Back rlEnd(); rlPopMatrix(); } // Draw cube // NOTE: Cube position is the center position -void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float lenght, Color color) +void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float height, float length, Color color) { float x = position.x; float y = position.y; @@ -233,40 +233,40 @@ void DrawCubeTexture(Texture2D texture, Vector3 position, float width, float hei rlColor4ub(color.r, color.g, color.b, color.a); // Front Face rlNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Towards Viewer - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Left Of The Texture and Quad - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Right Of The Texture and Quad - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Right Of The Texture and Quad - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Left Of The Texture and Quad + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Left Of The Texture and Quad + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Right Of The Texture and Quad + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Right Of The Texture and Quad + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Left Of The Texture and Quad // Back Face rlNormal3f( 0.0f, 0.0f,-1.0f); // Normal Pointing Away From Viewer - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Right Of The Texture and Quad - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Right Of The Texture and Quad - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Left Of The Texture and Quad - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Left Of The Texture and Quad + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Right Of The Texture and Quad + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Right Of The Texture and Quad + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Left Of The Texture and Quad + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Left Of The Texture and Quad // Top Face rlNormal3f( 0.0f, 1.0f, 0.0f); // Normal Pointing Up - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left Of The Texture and Quad - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Bottom Left Of The Texture and Quad - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Bottom Right Of The Texture and Quad - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right Of The Texture and Quad + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left Of The Texture and Quad + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y+height/2, z+length/2); // Bottom Left Of The Texture and Quad + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y+height/2, z+length/2); // Bottom Right Of The Texture and Quad + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right Of The Texture and Quad // Bottom Face rlNormal3f( 0.0f,-1.0f, 0.0f); // Normal Pointing Down - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Top Right Of The Texture and Quad - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Top Left Of The Texture and Quad - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Left Of The Texture and Quad - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Right Of The Texture and Quad + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y-height/2, z-length/2); // Top Right Of The Texture and Quad + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y-height/2, z-length/2); // Top Left Of The Texture and Quad + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Left Of The Texture and Quad + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Right Of The Texture and Quad // Right face rlNormal3f( 1.0f, 0.0f, 0.0f); // Normal Pointing Right - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z-lenght/2); // Bottom Right Of The Texture and Quad - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-lenght/2); // Top Right Of The Texture and Quad - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z+lenght/2); // Top Left Of The Texture and Quad - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+lenght/2); // Bottom Left Of The Texture and Quad + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z-length/2); // Bottom Right Of The Texture and Quad + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z-length/2); // Top Right Of The Texture and Quad + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x+width/2, y+height/2, z+length/2); // Top Left Of The Texture and Quad + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x+width/2, y-height/2, z+length/2); // Bottom Left Of The Texture and Quad // Left Face rlNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left - rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z-lenght/2); // Bottom Left Of The Texture and Quad - rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+lenght/2); // Bottom Right Of The Texture and Quad - rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z+lenght/2); // Top Right Of The Texture and Quad - rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-lenght/2); // Top Left Of The Texture and Quad + rlTexCoord2f(0.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z-length/2); // Bottom Left Of The Texture and Quad + rlTexCoord2f(1.0f, 0.0f); rlVertex3f(x-width/2, y-height/2, z+length/2); // Bottom Right Of The Texture and Quad + rlTexCoord2f(1.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z+length/2); // Top Right Of The Texture and Quad + rlTexCoord2f(0.0f, 1.0f); rlVertex3f(x-width/2, y+height/2, z-length/2); // Top Left Of The Texture and Quad rlEnd(); //rlPopMatrix(); @@ -534,12 +534,12 @@ void DrawGrid(int slices, float spacing) void DrawGizmo(Vector3 position) { // NOTE: RGB = XYZ - float lenght = 1.0f; + float length = 1.0f; rlPushMatrix(); rlTranslatef(position.x, position.y, position.z); //rlRotatef(rotation, 0, 1, 0); - rlScalef(lenght, lenght, lenght); + rlScalef(length, length, length); rlBegin(RL_LINES); rlColor3f(1.0f, 0.0f, 0.0f); rlVertex3f(0.0f, 0.0f, 0.0f); @@ -558,40 +558,44 @@ void DrawGizmo(Vector3 position) Model LoadModel(const char *fileName) { Model model; - VertexData vData = { 0 }; + Mesh mesh = { 0 }; // NOTE: Initialize default data for model in case loading fails, maybe a cube? - if (strcmp(GetExtension(fileName),"obj") == 0) vData = LoadOBJ(fileName); + if (strcmp(GetExtension(fileName),"obj") == 0) mesh = LoadOBJ(fileName); else TraceLog(WARNING, "[%s] Model extension not recognized, it can't be loaded", fileName); - // NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct + // NOTE: At this point we have all vertex, texcoord, normal data for the model in mesh struct - if (vData.vertexCount == 0) + if (mesh.vertexCount == 0) { TraceLog(WARNING, "Model could not be loaded"); } else { // NOTE: model properties (transform, texture, shader) are initialized inside rlglLoadModel() - model = rlglLoadModel(vData); // Upload vertex data to GPU + model = rlglLoadModel(mesh); // Upload vertex data to GPU // Now that vertex data is uploaded to GPU, we can free arrays - // NOTE: We don't need CPU vertex data on OpenGL 3.3 or ES2 + // NOTE 1: We don't need CPU vertex data on OpenGL 3.3 or ES2... for static meshes... + // NOTE 2: ...but we could keep CPU vertex data in case we need to update the mesh + + /* if (rlGetVersion() != OPENGL_11) { - free(vData.vertices); - free(vData.texcoords); - free(vData.normals); - free(vData.colors); + free(mesh.vertices); + free(mesh.texcoords); + free(mesh.normals); + free(mesh.colors); } + */ } return model; } // Load a 3d model (from vertex data) -Model LoadModelEx(VertexData data) +Model LoadModelEx(Mesh data) { Model model; @@ -606,7 +610,7 @@ Model LoadModelEx(VertexData data) // Load a heightmap image as a 3d model Model LoadHeightmap(Image heightmap, float maxHeight) { - VertexData vData; + Mesh mesh; int mapX = heightmap.width; int mapZ = heightmap.height; @@ -617,12 +621,12 @@ Model LoadHeightmap(Image heightmap, float maxHeight) // TODO: Consider resolution when generating model data? int numTriangles = (mapX-1)*(mapZ-1)*2; // One quad every four pixels - vData.vertexCount = numTriangles*3; + mesh.vertexCount = numTriangles*3; - vData.vertices = (float *)malloc(vData.vertexCount*3*sizeof(float)); - vData.normals = (float *)malloc(vData.vertexCount*3*sizeof(float)); - vData.texcoords = (float *)malloc(vData.vertexCount*2*sizeof(float)); - vData.colors = (unsigned char *)malloc(vData.vertexCount*4*sizeof(unsigned char)); // Not used... + mesh.vertices = (float *)malloc(mesh.vertexCount*3*sizeof(float)); + mesh.normals = (float *)malloc(mesh.vertexCount*3*sizeof(float)); + mesh.texcoords = (float *)malloc(mesh.vertexCount*2*sizeof(float)); + mesh.colors = (unsigned char *)malloc(mesh.vertexCount*4*sizeof(unsigned char)); // Not used... int vCounter = 0; // Used to count vertices float by float int tcCounter = 0; // Used to count texcoords float by float @@ -640,51 +644,51 @@ Model LoadHeightmap(Image heightmap, float maxHeight) //---------------------------------------------------------- // one triangle - 3 vertex - vData.vertices[vCounter] = x; - vData.vertices[vCounter + 1] = GetHeightValue(heightmapPixels[x + z*mapX])*scaleFactor; - vData.vertices[vCounter + 2] = z; + mesh.vertices[vCounter] = x; + mesh.vertices[vCounter + 1] = GetHeightValue(heightmapPixels[x + z*mapX])*scaleFactor; + mesh.vertices[vCounter + 2] = z; - vData.vertices[vCounter + 3] = x; - vData.vertices[vCounter + 4] = GetHeightValue(heightmapPixels[x + (z+1)*mapX])*scaleFactor; - vData.vertices[vCounter + 5] = z+1; + mesh.vertices[vCounter + 3] = x; + mesh.vertices[vCounter + 4] = GetHeightValue(heightmapPixels[x + (z+1)*mapX])*scaleFactor; + mesh.vertices[vCounter + 5] = z+1; - vData.vertices[vCounter + 6] = x+1; - vData.vertices[vCounter + 7] = GetHeightValue(heightmapPixels[(x+1) + z*mapX])*scaleFactor; - vData.vertices[vCounter + 8] = z; + mesh.vertices[vCounter + 6] = x+1; + mesh.vertices[vCounter + 7] = GetHeightValue(heightmapPixels[(x+1) + z*mapX])*scaleFactor; + mesh.vertices[vCounter + 8] = z; // another triangle - 3 vertex - vData.vertices[vCounter + 9] = vData.vertices[vCounter + 6]; - vData.vertices[vCounter + 10] = vData.vertices[vCounter + 7]; - vData.vertices[vCounter + 11] = vData.vertices[vCounter + 8]; + mesh.vertices[vCounter + 9] = mesh.vertices[vCounter + 6]; + mesh.vertices[vCounter + 10] = mesh.vertices[vCounter + 7]; + mesh.vertices[vCounter + 11] = mesh.vertices[vCounter + 8]; - vData.vertices[vCounter + 12] = vData.vertices[vCounter + 3]; - vData.vertices[vCounter + 13] = vData.vertices[vCounter + 4]; - vData.vertices[vCounter + 14] = vData.vertices[vCounter + 5]; + mesh.vertices[vCounter + 12] = mesh.vertices[vCounter + 3]; + mesh.vertices[vCounter + 13] = mesh.vertices[vCounter + 4]; + mesh.vertices[vCounter + 14] = mesh.vertices[vCounter + 5]; - vData.vertices[vCounter + 15] = x+1; - vData.vertices[vCounter + 16] = GetHeightValue(heightmapPixels[(x+1) + (z+1)*mapX])*scaleFactor; - vData.vertices[vCounter + 17] = z+1; + mesh.vertices[vCounter + 15] = x+1; + mesh.vertices[vCounter + 16] = GetHeightValue(heightmapPixels[(x+1) + (z+1)*mapX])*scaleFactor; + mesh.vertices[vCounter + 17] = z+1; vCounter += 18; // 6 vertex, 18 floats // Fill texcoords array with data //-------------------------------------------------------------- - vData.texcoords[tcCounter] = (float)x / (mapX-1); - vData.texcoords[tcCounter + 1] = (float)z / (mapZ-1); + mesh.texcoords[tcCounter] = (float)x / (mapX-1); + mesh.texcoords[tcCounter + 1] = (float)z / (mapZ-1); - vData.texcoords[tcCounter + 2] = (float)x / (mapX-1); - vData.texcoords[tcCounter + 3] = (float)(z+1) / (mapZ-1); + mesh.texcoords[tcCounter + 2] = (float)x / (mapX-1); + mesh.texcoords[tcCounter + 3] = (float)(z+1) / (mapZ-1); - vData.texcoords[tcCounter + 4] = (float)(x+1) / (mapX-1); - vData.texcoords[tcCounter + 5] = (float)z / (mapZ-1); + mesh.texcoords[tcCounter + 4] = (float)(x+1) / (mapX-1); + mesh.texcoords[tcCounter + 5] = (float)z / (mapZ-1); - vData.texcoords[tcCounter + 6] = vData.texcoords[tcCounter + 4]; - vData.texcoords[tcCounter + 7] = vData.texcoords[tcCounter + 5]; + mesh.texcoords[tcCounter + 6] = mesh.texcoords[tcCounter + 4]; + mesh.texcoords[tcCounter + 7] = mesh.texcoords[tcCounter + 5]; - vData.texcoords[tcCounter + 8] = vData.texcoords[tcCounter + 2]; - vData.texcoords[tcCounter + 9] = vData.texcoords[tcCounter + 3]; + mesh.texcoords[tcCounter + 8] = mesh.texcoords[tcCounter + 2]; + mesh.texcoords[tcCounter + 9] = mesh.texcoords[tcCounter + 3]; - vData.texcoords[tcCounter + 10] = (float)(x+1) / (mapX-1); - vData.texcoords[tcCounter + 11] = (float)(z+1) / (mapZ-1); + mesh.texcoords[tcCounter + 10] = (float)(x+1) / (mapX-1); + mesh.texcoords[tcCounter + 11] = (float)(z+1) / (mapZ-1); tcCounter += 12; // 6 texcoords, 12 floats // Fill normals array with data @@ -692,9 +696,9 @@ Model LoadHeightmap(Image heightmap, float maxHeight) // NOTE: Current Model implementation doe not use normals! for (int i = 0; i < 18; i += 3) { - vData.normals[nCounter + i] = 0.0f; - vData.normals[nCounter + i + 1] = 1.0f; - vData.normals[nCounter + i + 2] = 0.0f; + mesh.normals[nCounter + i] = 0.0f; + mesh.normals[nCounter + i + 1] = 1.0f; + mesh.normals[nCounter + i + 2] = 0.0f; } // TODO: Calculate normals in an efficient way @@ -709,20 +713,20 @@ Model LoadHeightmap(Image heightmap, float maxHeight) // Fill color data // NOTE: Not used any more... just one plain color defined at DrawModel() - for (int i = 0; i < (4*vData.vertexCount); i++) vData.colors[i] = 255; + for (int i = 0; i < (4*mesh.vertexCount); i++) mesh.colors[i] = 255; - // NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct + // NOTE: At this point we have all vertex, texcoord, normal data for the model in mesh struct - Model model = rlglLoadModel(vData); + Model model = rlglLoadModel(mesh); // Now that vertex data is uploaded to GPU, we can free arrays // NOTE: We don't need CPU vertex data on OpenGL 3.3 or ES2 if (rlGetVersion() != OPENGL_11) { - free(vData.vertices); - free(vData.texcoords); - free(vData.normals); - free(vData.colors); + free(mesh.vertices); + free(mesh.texcoords); + free(mesh.normals); + free(mesh.colors); } return model; @@ -731,14 +735,14 @@ Model LoadHeightmap(Image heightmap, float maxHeight) // Load a map image as a 3d model (cubes based) Model LoadCubicmap(Image cubicmap) { - VertexData vData; + Mesh mesh; Color *cubicmapPixels = GetImageData(cubicmap); // Map cube size will be 1.0 float mapCubeSide = 1.0f; - int mapWidth = cubicmap.width * (int)mapCubeSide; - int mapHeight = cubicmap.height * (int)mapCubeSide; + int mapWidth = cubicmap.width*(int)mapCubeSide; + int mapHeight = cubicmap.height*(int)mapCubeSide; // NOTE: Max possible number of triangles numCubes * (12 triangles by cube) int maxTriangles = cubicmap.width*cubicmap.height*12; @@ -749,11 +753,11 @@ Model LoadCubicmap(Image cubicmap) float w = mapCubeSide; float h = mapCubeSide; - float h2 = mapCubeSide * 1.5; // TODO: Review walls height... + float h2 = mapCubeSide*1.5f; // TODO: Review walls height... - Vector3 *mapVertices = (Vector3 *)malloc(maxTriangles * 3 * sizeof(Vector3)); - Vector2 *mapTexcoords = (Vector2 *)malloc(maxTriangles * 3 * sizeof(Vector2)); - Vector3 *mapNormals = (Vector3 *)malloc(maxTriangles * 3 * sizeof(Vector3)); + Vector3 *mapVertices = (Vector3 *)malloc(maxTriangles*3*sizeof(Vector3)); + Vector2 *mapTexcoords = (Vector2 *)malloc(maxTriangles*3*sizeof(Vector2)); + Vector3 *mapNormals = (Vector3 *)malloc(maxTriangles*3*sizeof(Vector3)); // Define the 6 normals of the cube, we will combine them accordingly later... Vector3 n1 = { 1.0f, 0.0f, 0.0f }; @@ -771,12 +775,12 @@ Model LoadCubicmap(Image cubicmap) float height; } RectangleF; - RectangleF rightTexUV = { 0, 0, 0.5, 0.5 }; - RectangleF leftTexUV = { 0.5, 0, 0.5, 0.5 }; - RectangleF frontTexUV = { 0, 0, 0.5, 0.5 }; - RectangleF backTexUV = { 0.5, 0, 0.5, 0.5 }; - RectangleF topTexUV = { 0, 0.5, 0.5, 0.5 }; - RectangleF bottomTexUV = { 0.5, 0.5, 0.5, 0.5 }; + RectangleF rightTexUV = { 0.0f, 0.0f, 0.5f, 0.5f }; + RectangleF leftTexUV = { 0.5f, 0.0f, 0.5f, 0.5f }; + RectangleF frontTexUV = { 0.0f, 0.0f, 0.5f, 0.5f }; + RectangleF backTexUV = { 0.5f, 0.0f, 0.5f, 0.5f }; + RectangleF topTexUV = { 0.0f, 0.5f, 0.5f, 0.5f }; + RectangleF bottomTexUV = { 0.5f, 0.5f, 0.5f, 0.5f }; for (int z = 0; z < mapHeight; z += mapCubeSide) { @@ -1037,25 +1041,25 @@ Model LoadCubicmap(Image cubicmap) } // Move data from mapVertices temp arays to vertices float array - vData.vertexCount = vCounter; + mesh.vertexCount = vCounter; - vData.vertices = (float *)malloc(vData.vertexCount*3*sizeof(float)); - vData.normals = (float *)malloc(vData.vertexCount*3*sizeof(float)); - vData.texcoords = (float *)malloc(vData.vertexCount*2*sizeof(float)); - vData.colors = (unsigned char *)malloc(vData.vertexCount*4*sizeof(unsigned char)); // Not used... + mesh.vertices = (float *)malloc(mesh.vertexCount*3*sizeof(float)); + mesh.normals = (float *)malloc(mesh.vertexCount*3*sizeof(float)); + mesh.texcoords = (float *)malloc(mesh.vertexCount*2*sizeof(float)); + mesh.colors = (unsigned char *)malloc(mesh.vertexCount*4*sizeof(unsigned char)); // Not used... // Fill color data // NOTE: Not used any more... just one plain color defined at DrawModel() - for (int i = 0; i < (4*vData.vertexCount); i++) vData.colors[i] = 255; + for (int i = 0; i < (4*mesh.vertexCount); i++) mesh.colors[i] = 255; int fCounter = 0; // Move vertices data for (int i = 0; i < vCounter; i++) { - vData.vertices[fCounter] = mapVertices[i].x; - vData.vertices[fCounter + 1] = mapVertices[i].y; - vData.vertices[fCounter + 2] = mapVertices[i].z; + mesh.vertices[fCounter] = mapVertices[i].x; + mesh.vertices[fCounter + 1] = mapVertices[i].y; + mesh.vertices[fCounter + 2] = mapVertices[i].z; fCounter += 3; } @@ -1064,9 +1068,9 @@ Model LoadCubicmap(Image cubicmap) // Move normals data for (int i = 0; i < nCounter; i++) { - vData.normals[fCounter] = mapNormals[i].x; - vData.normals[fCounter + 1] = mapNormals[i].y; - vData.normals[fCounter + 2] = mapNormals[i].z; + mesh.normals[fCounter] = mapNormals[i].x; + mesh.normals[fCounter + 1] = mapNormals[i].y; + mesh.normals[fCounter + 2] = mapNormals[i].z; fCounter += 3; } @@ -1075,8 +1079,8 @@ Model LoadCubicmap(Image cubicmap) // Move texcoords data for (int i = 0; i < tcCounter; i++) { - vData.texcoords[fCounter] = mapTexcoords[i].x; - vData.texcoords[fCounter + 1] = mapTexcoords[i].y; + mesh.texcoords[fCounter] = mapTexcoords[i].x; + mesh.texcoords[fCounter + 1] = mapTexcoords[i].y; fCounter += 2; } @@ -1086,18 +1090,18 @@ Model LoadCubicmap(Image cubicmap) free(cubicmapPixels); - // NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct + // NOTE: At this point we have all vertex, texcoord, normal data for the model in mesh struct - Model model = rlglLoadModel(vData); + Model model = rlglLoadModel(mesh); // Now that vertex data is uploaded to GPU, we can free arrays // NOTE: We don't need CPU vertex data on OpenGL 3.3 or ES2 if (rlGetVersion() != OPENGL_11) { - free(vData.vertices); - free(vData.texcoords); - free(vData.normals); - free(vData.colors); + free(mesh.vertices); + free(mesh.texcoords); + free(mesh.normals); + free(mesh.colors); } return model; @@ -1143,7 +1147,7 @@ void SetModelTexture(Model *model, Texture2D texture) void DrawModel(Model model, Vector3 position, float scale, Color tint) { Vector3 vScale = { scale, scale, scale }; - Vector3 rotationAxis = { 0, 0, 0 }; + Vector3 rotationAxis = { 0.0f, 0.0f, 0.0f }; DrawModelEx(model, position, 0.0f, rotationAxis, vScale, tint); } @@ -1159,11 +1163,18 @@ void DrawModelEx(Model model, Vector3 position, float rotationAngle, Vector3 rot void DrawModelWires(Model model, Vector3 position, float scale, Color color) { Vector3 vScale = { scale, scale, scale }; - Vector3 rotationAxis = { 0, 0, 0 }; + Vector3 rotationAxis = { 0.0f, 0.0f, 0.0f }; rlglDrawModel(model, position, 0.0f, rotationAxis, vScale, color, true); } +// Draw a model wires (with texture if set) with extended parameters +void DrawModelWiresEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint) +{ + // NOTE: Rotation must be provided in degrees, it's converted to radians inside rlglDrawModel() + rlglDrawModel(model, position, rotationAngle, rotationAxis, scale, tint, true); +} + // Draw a billboard void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint) { @@ -1177,7 +1188,7 @@ void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, //Vector3 up = { viewMatrix.m1, viewMatrix.m5, viewMatrix.m9 }; // NOTE: Billboard locked to axis-Y - Vector3 up = { 0, 1, 0 }; + Vector3 up = { 0.0f, 1.0f, 0.0f }; /* a-------b | | @@ -1325,9 +1336,65 @@ bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSph return collision; } +// Detect collision between ray and sphere +bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius) +{ + bool collision = false; + + // TODO: implement collision... + + return collision; +} + +// Detect collision between ray and bounding box +bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox) +{ + bool collision = false; + + float t[8]; + t[0] = (minBBox.x - ray.position.x)/ray.direction.x; + t[1] = (maxBBox.x - ray.position.x)/ray.direction.x; + t[2] = (minBBox.y - ray.position.y)/ray.direction.y; + t[3] = (maxBBox.y - ray.position.y)/ray.direction.y; + t[4] = (minBBox.z - ray.position.z)/ray.direction.z; + t[5] = (maxBBox.z - ray.position.z)/ray.direction.z; + t[6] = fmax(fmax(fmin(t[0], t[1]), fmin(t[2], t[3])), fmin(t[4], t[5])); + t[7] = fmin(fmin(fmax(t[0], t[1]), fmax(t[2], t[3])), fmax(t[4], t[5])); + + collision = !(t[7] < 0 || t[6] > t[7]); + + return collision; +} + // TODO: Useful function to check collision area? //BoundingBox GetCollisionArea(BoundingBox box1, BoundingBox box2) +// Calculate mesh bounding box limits +BoundingBox CalculateBoundingBox(Mesh mesh) +{ + // Get min and max vertex to construct bounds (AABB) + Vector3 minVertex = mesh.vertices[0]; + Vector3 maxVertex = mesh.vertices[0]; + + for (int i = 1; i < mesh.vertexCount; i++) + { + // TODO: Compare min and max with previous vertex + //minVertex = Vector3.Min(minVertex, mesh.vertices[i]); + //maxVertex = Vector3.Max(maxVertex, mesh.vertices[i]); + } + + // NOTE: For OBB, transform mesh by model transform matrix + //minVertex = VectorTransform(meshMin, mesh.transform); + //maxVertex = VectorTransform(meshMax, mesh.transform); + + // Create the bounding box + BoundingBox box; + box.min = minVertex; + box.max = maxVertex; + + return box; +} + // Detect and resolve cubicmap collisions // NOTE: player position (or camera) is modified inside this function Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius) @@ -1335,7 +1402,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p Color *cubicmapPixels = GetImageData(cubicmap); // Detect the cell where the player is located - Vector3 impactDirection = { 0, 0, 0 }; + Vector3 impactDirection = { 0.0f, 0.0f, 0.0f }; int locationCellX = 0; int locationCellY = 0; @@ -1358,7 +1425,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p { playerPosition->x = locationCellX + mapPosition.x - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); playerPosition->z = locationCellY + mapPosition.z - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3) { 1, 0, 1}; + impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; } } } @@ -1374,7 +1441,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p { playerPosition->x = locationCellX + mapPosition.x - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); playerPosition->z = locationCellY + mapPosition.z + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3) { 1, 0, 1}; + impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; } } } @@ -1390,7 +1457,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p { playerPosition->x = locationCellX + mapPosition.x + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); playerPosition->z = locationCellY + mapPosition.z - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3) { 1, 0, 1}; + impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; } } } @@ -1406,7 +1473,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p { playerPosition->x = locationCellX + mapPosition.x + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); playerPosition->z = locationCellY + mapPosition.z + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3) { 1, 0, 1}; + impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; } } } @@ -1421,7 +1488,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p if ((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius) { playerPosition->x = locationCellX + mapPosition.x - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3) { 1, 0, 0}; + impactDirection = (Vector3){ 1.0f, 0.0f, 0.0f }; } } } @@ -1433,7 +1500,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p if ((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius) { playerPosition->x = locationCellX + mapPosition.x + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3) { 1, 0, 0}; + impactDirection = (Vector3){ 1.0f, 0.0f, 0.0f }; } } } @@ -1445,7 +1512,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p if ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius) { playerPosition->z = locationCellY + mapPosition.z - (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3) { 0, 0, 1}; + impactDirection = (Vector3){ 0.0f, 0.0f, 1.0f }; } } } @@ -1457,7 +1524,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p if ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius) { playerPosition->z = locationCellY + mapPosition.z + (CUBIC_MAP_HALF_BLOCK_SIZE - radius); - impactDirection = (Vector3) { 0, 0, 1}; + impactDirection = (Vector3){ 0.0f, 0.0f, 1.0f }; } } } @@ -1481,7 +1548,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius / 3) && ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius / 3)) { - impactDirection = (Vector3) { 1, 0, 1}; + impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; } } } @@ -1504,7 +1571,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX < radius / 3) && ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius / 3)) { - impactDirection = (Vector3) { 1, 0, 1}; + impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; } } } @@ -1527,7 +1594,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius / 3) && ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY < radius / 3)) { - impactDirection = (Vector3) { 1, 0, 1}; + impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; } } } @@ -1550,7 +1617,7 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p if (((playerPosition->x - mapPosition.x + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellX > 1 - radius / 3) && ((playerPosition->z - mapPosition.z + CUBIC_MAP_HALF_BLOCK_SIZE) - locationCellY > 1 - radius / 3)) { - impactDirection = (Vector3) { 1, 0, 1}; + impactDirection = (Vector3){ 1.0f, 0.0f, 1.0f }; } } } @@ -1560,13 +1627,13 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p // Floor collision if (playerPosition->y <= radius) { - playerPosition->y = radius + 0.01; + playerPosition->y = radius + 0.01f; impactDirection = (Vector3) { impactDirection.x, 1, impactDirection.z}; } // Roof collision - else if (playerPosition->y >= 1.5 - radius) + else if (playerPosition->y >= (1.5f - radius)) { - playerPosition->y = (1.5 - radius) - 0.01; + playerPosition->y = (1.5f - radius) - 0.01f; impactDirection = (Vector3) { impactDirection.x, 1, impactDirection.z}; } @@ -1586,9 +1653,9 @@ static float GetHeightValue(Color pixel) } // Load OBJ mesh data -static VertexData LoadOBJ(const char *fileName) +static Mesh LoadOBJ(const char *fileName) { - VertexData vData = { 0 }; + Mesh mesh = { 0 }; char dataType; char comments[200]; @@ -1605,7 +1672,7 @@ static VertexData LoadOBJ(const char *fileName) if (objFile == NULL) { TraceLog(WARNING, "[%s] OBJ file could not be opened", fileName); - return vData; + return mesh; } // First reading pass: Get numVertex, numNormals, numTexCoords, numTriangles @@ -1716,15 +1783,15 @@ static VertexData LoadOBJ(const char *fileName) } // At this point all vertex data (v, vt, vn) has been gathered on midVertices, midTexCoords, midNormals - // Now we can organize that data into our VertexData struct + // Now we can organize that data into our Mesh struct - vData.vertexCount = numTriangles*3; + mesh.vertexCount = numTriangles*3; // Additional arrays to store vertex data as floats - vData.vertices = (float *)malloc(vData.vertexCount*3*sizeof(float)); - vData.texcoords = (float *)malloc(vData.vertexCount*2*sizeof(float)); - vData.normals = (float *)malloc(vData.vertexCount*3*sizeof(float)); - vData.colors = (unsigned char *)malloc(vData.vertexCount*4*sizeof(unsigned char)); + mesh.vertices = (float *)malloc(mesh.vertexCount*3*sizeof(float)); + mesh.texcoords = (float *)malloc(mesh.vertexCount*2*sizeof(float)); + mesh.normals = (float *)malloc(mesh.vertexCount*3*sizeof(float)); + mesh.colors = (unsigned char *)malloc(mesh.vertexCount*4*sizeof(unsigned char)); int vCounter = 0; // Used to count vertices float by float int tcCounter = 0; // Used to count texcoords float by float @@ -1752,32 +1819,32 @@ static VertexData LoadOBJ(const char *fileName) else if (numNormals == 0) fscanf(objFile, "%i/%i %i/%i %i/%i", &vNum[0], &vtNum[0], &vNum[1], &vtNum[1], &vNum[2], &vtNum[2]); else fscanf(objFile, "%i/%i/%i %i/%i/%i %i/%i/%i", &vNum[0], &vtNum[0], &vnNum[0], &vNum[1], &vtNum[1], &vnNum[1], &vNum[2], &vtNum[2], &vnNum[2]); - vData.vertices[vCounter] = midVertices[vNum[0]-1].x; - vData.vertices[vCounter + 1] = midVertices[vNum[0]-1].y; - vData.vertices[vCounter + 2] = midVertices[vNum[0]-1].z; + mesh.vertices[vCounter] = midVertices[vNum[0]-1].x; + mesh.vertices[vCounter + 1] = midVertices[vNum[0]-1].y; + mesh.vertices[vCounter + 2] = midVertices[vNum[0]-1].z; vCounter += 3; - vData.vertices[vCounter] = midVertices[vNum[1]-1].x; - vData.vertices[vCounter + 1] = midVertices[vNum[1]-1].y; - vData.vertices[vCounter + 2] = midVertices[vNum[1]-1].z; + mesh.vertices[vCounter] = midVertices[vNum[1]-1].x; + mesh.vertices[vCounter + 1] = midVertices[vNum[1]-1].y; + mesh.vertices[vCounter + 2] = midVertices[vNum[1]-1].z; vCounter += 3; - vData.vertices[vCounter] = midVertices[vNum[2]-1].x; - vData.vertices[vCounter + 1] = midVertices[vNum[2]-1].y; - vData.vertices[vCounter + 2] = midVertices[vNum[2]-1].z; + mesh.vertices[vCounter] = midVertices[vNum[2]-1].x; + mesh.vertices[vCounter + 1] = midVertices[vNum[2]-1].y; + mesh.vertices[vCounter + 2] = midVertices[vNum[2]-1].z; vCounter += 3; if (numNormals > 0) { - vData.normals[nCounter] = midNormals[vnNum[0]-1].x; - vData.normals[nCounter + 1] = midNormals[vnNum[0]-1].y; - vData.normals[nCounter + 2] = midNormals[vnNum[0]-1].z; + mesh.normals[nCounter] = midNormals[vnNum[0]-1].x; + mesh.normals[nCounter + 1] = midNormals[vnNum[0]-1].y; + mesh.normals[nCounter + 2] = midNormals[vnNum[0]-1].z; nCounter += 3; - vData.normals[nCounter] = midNormals[vnNum[1]-1].x; - vData.normals[nCounter + 1] = midNormals[vnNum[1]-1].y; - vData.normals[nCounter + 2] = midNormals[vnNum[1]-1].z; + mesh.normals[nCounter] = midNormals[vnNum[1]-1].x; + mesh.normals[nCounter + 1] = midNormals[vnNum[1]-1].y; + mesh.normals[nCounter + 2] = midNormals[vnNum[1]-1].z; nCounter += 3; - vData.normals[nCounter] = midNormals[vnNum[2]-1].x; - vData.normals[nCounter + 1] = midNormals[vnNum[2]-1].y; - vData.normals[nCounter + 2] = midNormals[vnNum[2]-1].z; + mesh.normals[nCounter] = midNormals[vnNum[2]-1].x; + mesh.normals[nCounter + 1] = midNormals[vnNum[2]-1].y; + mesh.normals[nCounter + 2] = midNormals[vnNum[2]-1].z; nCounter += 3; } else @@ -1786,17 +1853,17 @@ static VertexData LoadOBJ(const char *fileName) Vector3 norm = VectorCrossProduct(VectorSubtract(midVertices[vNum[1]-1], midVertices[vNum[0]-1]), VectorSubtract(midVertices[vNum[2]-1], midVertices[vNum[0]-1])); VectorNormalize(&norm); - vData.normals[nCounter] = norm.x; - vData.normals[nCounter + 1] = norm.y; - vData.normals[nCounter + 2] = norm.z; + mesh.normals[nCounter] = norm.x; + mesh.normals[nCounter + 1] = norm.y; + mesh.normals[nCounter + 2] = norm.z; nCounter += 3; - vData.normals[nCounter] = norm.x; - vData.normals[nCounter + 1] = norm.y; - vData.normals[nCounter + 2] = norm.z; + mesh.normals[nCounter] = norm.x; + mesh.normals[nCounter + 1] = norm.y; + mesh.normals[nCounter + 2] = norm.z; nCounter += 3; - vData.normals[nCounter] = norm.x; - vData.normals[nCounter + 1] = norm.y; - vData.normals[nCounter + 2] = norm.z; + mesh.normals[nCounter] = norm.x; + mesh.normals[nCounter + 1] = norm.y; + mesh.normals[nCounter + 2] = norm.z; nCounter += 3; } @@ -1804,14 +1871,14 @@ static VertexData LoadOBJ(const char *fileName) { // NOTE: If using negative texture coordinates with a texture filter of GL_CLAMP_TO_EDGE doesn't work! // NOTE: Texture coordinates are Y flipped upside-down - vData.texcoords[tcCounter] = midTexCoords[vtNum[0]-1].x; - vData.texcoords[tcCounter + 1] = 1.0f - midTexCoords[vtNum[0]-1].y; + mesh.texcoords[tcCounter] = midTexCoords[vtNum[0]-1].x; + mesh.texcoords[tcCounter + 1] = 1.0f - midTexCoords[vtNum[0]-1].y; tcCounter += 2; - vData.texcoords[tcCounter] = midTexCoords[vtNum[1]-1].x; - vData.texcoords[tcCounter + 1] = 1.0f - midTexCoords[vtNum[1]-1].y; + mesh.texcoords[tcCounter] = midTexCoords[vtNum[1]-1].x; + mesh.texcoords[tcCounter + 1] = 1.0f - midTexCoords[vtNum[1]-1].y; tcCounter += 2; - vData.texcoords[tcCounter] = midTexCoords[vtNum[2]-1].x; - vData.texcoords[tcCounter + 1] = 1.0f - midTexCoords[vtNum[2]-1].y; + mesh.texcoords[tcCounter] = midTexCoords[vtNum[2]-1].x; + mesh.texcoords[tcCounter + 1] = 1.0f - midTexCoords[vtNum[2]-1].y; tcCounter += 2; } } break; @@ -1822,19 +1889,19 @@ static VertexData LoadOBJ(const char *fileName) fclose(objFile); // Security check, just in case no normals or no texcoords defined in OBJ - if (numTexCoords == 0) for (int i = 0; i < (2*vData.vertexCount); i++) vData.texcoords[i] = 0.0f; + if (numTexCoords == 0) for (int i = 0; i < (2*mesh.vertexCount); i++) mesh.texcoords[i] = 0.0f; // NOTE: We set all vertex colors to white // NOTE: Not used any more... just one plain color defined at DrawModel() - for (int i = 0; i < (4*vData.vertexCount); i++) vData.colors[i] = 255; + for (int i = 0; i < (4*mesh.vertexCount); i++) mesh.colors[i] = 255; // Now we can free temp mid* arrays free(midVertices); free(midNormals); free(midTexCoords); - // NOTE: At this point we have all vertex, texcoord, normal data for the model in vData struct + // NOTE: At this point we have all vertex, texcoord, normal data for the model in mesh struct TraceLog(INFO, "[%s] Model loaded successfully in RAM (CPU)", fileName); - return vData; + return mesh; } diff --git a/src/physac.c b/src/physac.c new file mode 100644 index 000000000..6e3b6e61c --- /dev/null +++ b/src/physac.c @@ -0,0 +1,342 @@ +/********************************************************************************************** +* +* [physac] raylib physics engine module - Basic functions to apply physics to 2D objects +* +* Copyright (c) 2015 Victor Fisac and Ramon Santamaria +* +* This software is provided "as-is", without any express or implied warranty. In no event +* will the authors be held liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as 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 PHYSAC_STANDALONE // NOTE: To use the physics module as standalone lib, just uncomment this line + +#if defined(PHYSAC_STANDALONE) + #include "physac.h" +#else + #include "raylib.h" +#endif + +#include +#include + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#define MAX_ELEMENTS 1024 // Stored rigidbodies and colliders array length +#define DECIMAL_FIX 0.26f // Decimal margin for collision checks (avoid rigidbodies shake) + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +static Physics physics; +static Collider colliders[MAX_ELEMENTS]; +static Rigidbody rigidbodies[MAX_ELEMENTS]; +static bool collisionChecker = false; + +//---------------------------------------------------------------------------------- +// Module specific Functions Declarations +//---------------------------------------------------------------------------------- +static float Vector2Length(Vector2 vector); +static float Vector2LengthPoints(Vector2 a, Vector2 b); +static Vector2 Vector2Normalize(Vector2 vector); + +//---------------------------------------------------------------------------------- +// Module Functions Definitions +//---------------------------------------------------------------------------------- +void InitPhysics(void) +{ + for (int i = 0; i < MAX_ELEMENTS; i++) + { + rigidbodies[i].enabled = false; + rigidbodies[i].mass = 0.0f; + rigidbodies[i].velocity = (Vector2){0, 0}; + rigidbodies[i].acceleration = (Vector2){0, 0}; + rigidbodies[i].isGrounded = false; + rigidbodies[i].isContact = false; + rigidbodies[i].friction = 0.0f; + + colliders[i].enabled = false; + colliders[i].bounds = (Rectangle){0, 0, 0, 0}; + colliders[i].radius = 0; + } +} + +void SetPhysics(Physics settings) +{ + physics = settings; + + // To get good results, gravity needs to be 1:10 from original parameter + physics.gravity = (Vector2){physics.gravity.x / 10, physics.gravity.y / 10}; +} + +void AddCollider(int index, Collider collider) +{ + colliders[index] = collider; +} + +void AddRigidbody(int index, Rigidbody rigidbody) +{ + rigidbodies[index] = rigidbody; +} + +void ApplyPhysics(int index, Vector2 *position) +{ + if (rigidbodies[index].enabled) + { + // Apply friction to acceleration + if (rigidbodies[index].acceleration.x > DECIMAL_FIX) + { + rigidbodies[index].acceleration.x -= rigidbodies[index].friction; + } + else if (rigidbodies[index].acceleration.x < -DECIMAL_FIX) + { + rigidbodies[index].acceleration.x += rigidbodies[index].friction; + } + else + { + rigidbodies[index].acceleration.x = 0; + } + + if (rigidbodies[index].acceleration.y > DECIMAL_FIX / 2) + { + rigidbodies[index].acceleration.y -= rigidbodies[index].friction; + } + else if (rigidbodies[index].acceleration.y < -DECIMAL_FIX / 2) + { + rigidbodies[index].acceleration.y += rigidbodies[index].friction; + } + else + { + rigidbodies[index].acceleration.y = 0; + } + + // Apply friction to velocity + if (rigidbodies[index].isGrounded) + { + if (rigidbodies[index].velocity.x > DECIMAL_FIX) + { + rigidbodies[index].velocity.x -= rigidbodies[index].friction; + } + else if (rigidbodies[index].velocity.x < -DECIMAL_FIX) + { + rigidbodies[index].velocity.x += rigidbodies[index].friction; + } + else + { + rigidbodies[index].velocity.x = 0; + } + } + + if (rigidbodies[index].velocity.y > DECIMAL_FIX / 2) + { + rigidbodies[index].velocity.y -= rigidbodies[index].friction; + } + else if (rigidbodies[index].velocity.y < -DECIMAL_FIX / 2) + { + rigidbodies[index].velocity.y += rigidbodies[index].friction; + } + else + { + rigidbodies[index].velocity.y = 0; + } + + // Apply gravity + rigidbodies[index].velocity.y += physics.gravity.y; + rigidbodies[index].velocity.x += physics.gravity.x; + + // Apply acceleration + rigidbodies[index].velocity.y += rigidbodies[index].acceleration.y; + rigidbodies[index].velocity.x += rigidbodies[index].acceleration.x; + + // Update position vector + position->x += rigidbodies[index].velocity.x; + position->y -= rigidbodies[index].velocity.y; + + // Update collider bounds + colliders[index].bounds.x = position->x; + colliders[index].bounds.y = position->y; + + // Check collision with other colliders + collisionChecker = false; + rigidbodies[index].isContact = false; + for (int j = 0; j < MAX_ELEMENTS; j++) + { + if (index != j) + { + if (colliders[index].enabled && colliders[j].enabled) + { + if (colliders[index].type == RectangleCollider) + { + if (colliders[j].type == RectangleCollider) + { + if (CheckCollisionRecs(colliders[index].bounds, colliders[j].bounds)) + { + collisionChecker = true; + + if ((colliders[index].bounds.y + colliders[index].bounds.height <= colliders[j].bounds.y) == false) + { + rigidbodies[index].isContact = true; + } + } + } + else + { + if (CheckCollisionCircleRec((Vector2){colliders[j].bounds.x, colliders[j].bounds.y}, colliders[j].radius, colliders[index].bounds)) + { + collisionChecker = true; + } + } + } + else + { + if (colliders[j].type == RectangleCollider) + { + if (CheckCollisionCircleRec((Vector2){colliders[index].bounds.x, colliders[index].bounds.y}, colliders[index].radius, colliders[j].bounds)) + { + collisionChecker = true; + } + } + else + { + if (CheckCollisionCircles((Vector2){colliders[j].bounds.x, colliders[j].bounds.y}, colliders[j].radius, (Vector2){colliders[index].bounds.x, colliders[index].bounds.y}, colliders[index].radius)) + { + collisionChecker = true; + } + } + } + } + } + } + + // Update grounded rigidbody state + rigidbodies[index].isGrounded = collisionChecker; + + // Set grounded state if needed (fix overlap and set y velocity) + if (collisionChecker && rigidbodies[index].velocity.y != 0) + { + position->y += rigidbodies[index].velocity.y; + rigidbodies[index].velocity.y = -rigidbodies[index].velocity.y * rigidbodies[index].bounciness; + } + + if (rigidbodies[index].isContact) + { + position->x -= rigidbodies[index].velocity.x; + rigidbodies[index].velocity.x = rigidbodies[index].velocity.x; + } + } +} + +void SetRigidbodyEnabled(int index, bool state) +{ + rigidbodies[index].enabled = state; +} + +void SetRigidbodyVelocity(int index, Vector2 velocity) +{ + rigidbodies[index].velocity.x = velocity.x; + rigidbodies[index].velocity.y = velocity.y; +} + +void SetRigidbodyAcceleration(int index, Vector2 acceleration) +{ + rigidbodies[index].acceleration.x = acceleration.x; + rigidbodies[index].acceleration.y = acceleration.y; +} + +void AddRigidbodyForce(int index, Vector2 force) +{ + rigidbodies[index].acceleration.x = force.x / rigidbodies[index].mass; + rigidbodies[index].acceleration.y = force.y / rigidbodies[index].mass; +} + +void AddForceAtPosition(Vector2 position, float intensity, float radius) +{ + for(int i = 0; i < MAX_ELEMENTS; i++) + { + if(rigidbodies[i].enabled) + { + // Get position from its collider + Vector2 pos = {colliders[i].bounds.x, colliders[i].bounds.y}; + + // Get distance between rigidbody position and target position + float distance = Vector2LengthPoints(position, pos); + + if(distance <= radius) + { + // Calculate force based on direction + Vector2 force = {colliders[i].bounds.x - position.x, colliders[i].bounds.y - position.y}; + + // Normalize the direction vector + force = Vector2Normalize(force); + + // Invert y value + force.y *= -1; + + // Apply intensity and distance + force = (Vector2){force.x * intensity / distance, force.y * intensity / distance}; + + // Add calculated force to the rigidbodies + AddRigidbodyForce(i, force); + } + } + } +} + +void SetColliderEnabled(int index, bool state) +{ + colliders[index].enabled = state; +} + +Collider GetCollider(int index) +{ + return colliders[index]; +} + +Rigidbody GetRigidbody(int index) +{ + return rigidbodies[index]; +} + +//---------------------------------------------------------------------------------- +// Module specific Functions Definitions +//---------------------------------------------------------------------------------- +static float Vector2Length(Vector2 vector) +{ + return sqrt((vector.x * vector.x) + (vector.y * vector.y)); +} + +static float Vector2LengthPoints(Vector2 a, Vector2 b) +{ + Vector2 vector = {b.x - a.x, b.y - a.y}; + return sqrt((vector.x * vector.x) + (vector.y * vector.y)); +} + +static Vector2 Vector2Normalize(Vector2 vector) +{ + float length = Vector2Length(vector); + + if(length != 0) + { + return (Vector2){vector.x / length, vector.y / length}; + } + + return (Vector2){0, 0}; +} diff --git a/src/physac.h b/src/physac.h new file mode 100644 index 000000000..558673ef3 --- /dev/null +++ b/src/physac.h @@ -0,0 +1,101 @@ +/********************************************************************************************** +* +* [physac] raylib physics engine module - Basic functions to apply physics to 2D objects +* +* Copyright (c) 2015 Victor Fisac and Ramon Santamaria +* +* This software is provided "as-is", without any express or implied warranty. In no event +* will the authors be held liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented +* as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +**********************************************************************************************/ + +#ifndef PHYSAC_H +#define PHYSAC_H + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +typedef enum { RectangleCollider, CircleCollider } ColliderType; + +// Physics struct +typedef struct Physics { + bool enabled; + bool debug; // Should be used by programmer for testing purposes + Vector2 gravity; +} Physics; + +// Transform struct +typedef struct Transform { + Vector2 position; + float rotation; + Vector2 scale; +} Transform; + +// Rigidbody struct +typedef struct Rigidbody { + bool enabled; + float mass; + Vector2 acceleration; + Vector2 velocity; + bool isGrounded; + bool isContact; // Avoid freeze player when touching floor + bool applyGravity; + float friction; // 0.0f to 1.0f + float bounciness; // 0.0f to 1.0f +} Rigidbody; + +// Collider struct +typedef struct Collider { + bool enabled; + ColliderType type; + Rectangle bounds; // Just used for RectangleCollider type + int radius; // Just used for CircleCollider type +} Collider; + +#ifdef __cplusplus +extern "C" { // Prevents name mangling of functions +#endif + +//---------------------------------------------------------------------------------- +// Module Functions Declarations +//---------------------------------------------------------------------------------- +void InitPhysics(void); // Initialize all internal physics values +void SetPhysics(Physics settings); // Set physics settings values using Physics data type to overwrite internal physics settings + +void AddRigidbody(int index, Rigidbody rigidbody); // Initialize a new rigidbody with parameters to internal index slot +void AddCollider(int index, Collider collider); // Initialize a new Collider with parameters to internal index slot + +void ApplyPhysics(int index, Vector2 *position); // Apply physics to internal rigidbody, physics calculations are applied to position pointer parameter +void SetRigidbodyEnabled(int index, bool state); // Set enabled state to a defined rigidbody +void SetRigidbodyVelocity(int index, Vector2 velocity); // Set velocity of rigidbody (without considering of mass value) +void SetRigidbodyAcceleration(int index, Vector2 acceleration); // Set acceleration of rigidbody (without considering of mass value) +void AddRigidbodyForce(int index, Vector2 force); // Set rigidbody force (considering mass value) +void AddForceAtPosition(Vector2 position, float intensity, float radius); // Add a force to all enabled rigidbodies at a position + +void SetColliderEnabled(int index, bool state); // Set enabled state to a defined collider + +Rigidbody GetRigidbody(int index); // Returns the internal rigidbody data defined by index parameter +Collider GetCollider(int index); // Returns the internal collider data defined by index parameter + +#ifdef __cplusplus +} +#endif + +#endif // PHYSAC_H diff --git a/src/raygui.c b/src/raygui.c index 8e9a3387c..2c68c96f7 100644 --- a/src/raygui.c +++ b/src/raygui.c @@ -255,7 +255,7 @@ bool GuiToggleButton(Rectangle bounds, const char *text, bool toggle) // Update control //-------------------------------------------------------------------- - if (toggleButton.width < textWidth) toggleButton.width = textWidth + style[TOGGLE_TEXT_PADDING]; + if (toggleButton.width < textWidth) toggleButton.width = textWidth + style[TOGGLE_TEXT_PADDING]; if (toggleButton.height < textHeight) toggleButton.height = textHeight + style[TOGGLE_TEXT_PADDING]/2; if (CheckCollisionPointRec(mousePoint, toggleButton)) { @@ -320,7 +320,7 @@ int GuiComboBox(Rectangle bounds, int comboNum, char **comboText, int comboActiv { ComboBoxState comboBoxState = COMBOBOX_UNACTIVE; Rectangle comboBoxButton = bounds; - Rectangle click = { bounds.x + bounds.width + style[COMBOBOX_PADDING], bounds.y, style[COMBOBOX_BUTTON_WIDTH], bounds.height }; + Rectangle click = { bounds.x + bounds.width + style[COMBOBOX_PADDING], bounds.y, style[COMBOBOX_BUTTON_WIDTH], style[COMBOBOX_BUTTON_HEIGHT] }; Vector2 mousePoint = GetMousePosition(); int textHeight = GetDefaultFont().size; @@ -691,7 +691,7 @@ int GuiSpinner(Rectangle bounds, int value, int minValue, int maxValue) } else if (!CheckCollisionPointRec(mousePoint, labelBoxBound)) buttonSide = 0; - if(IsMouseButtonUp(MOUSE_LEFT_BUTTON)) + if (IsMouseButtonUp(MOUSE_LEFT_BUTTON)) { valueSpeed = false; framesCounter = 0; @@ -710,13 +710,13 @@ int GuiSpinner(Rectangle bounds, int value, int minValue, int maxValue) DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR])); DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR])); - DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); - DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); + DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); + DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); DrawRectangleRec(labelBoxBound, GetColor(style[SPINNER_LABEL_BORDER_COLOR])); DrawRectangle(labelBoxBound.x + 1, labelBoxBound.y + 1, labelBoxBound.width - 2, labelBoxBound.height - 2, GetColor(style[SPINNER_LABEL_INSIDE_COLOR])); - DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_TEXT_COLOR])); + DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_TEXT_COLOR])); } break; case SPINNER_HOVER: { @@ -728,8 +728,8 @@ int GuiSpinner(Rectangle bounds, int value, int minValue, int maxValue) DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR])); DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR])); - DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_SYMBOL_COLOR])); - DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); + DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_SYMBOL_COLOR])); + DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); } else if (buttonSide == 2) { @@ -739,14 +739,14 @@ int GuiSpinner(Rectangle bounds, int value, int minValue, int maxValue) DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_HOVER_BUTTON_BORDER_COLOR])); DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_HOVER_BUTTON_INSIDE_COLOR])); - DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); - DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_SYMBOL_COLOR])); + DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); + DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_SYMBOL_COLOR])); } DrawRectangleRec(labelBoxBound, GetColor(style[SPINNER_LABEL_BORDER_COLOR])); DrawRectangle(labelBoxBound.x + 1, labelBoxBound.y + 1, labelBoxBound.width - 2, labelBoxBound.height - 2, GetColor(style[SPINNER_LABEL_INSIDE_COLOR])); - DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_TEXT_COLOR])); + DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_HOVER_TEXT_COLOR])); } break; case SPINNER_PRESSED: { @@ -758,9 +758,9 @@ int GuiSpinner(Rectangle bounds, int value, int minValue, int maxValue) DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR])); DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_DEFAULT_BUTTON_INSIDE_COLOR])); - DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_SYMBOL_COLOR])); - DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); - } + DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_SYMBOL_COLOR])); + DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); + } else if (buttonSide == 2) { DrawRectangleRec(leftButtonBound, GetColor(style[SPINNER_DEFAULT_BUTTON_BORDER_COLOR])); @@ -769,16 +769,18 @@ int GuiSpinner(Rectangle bounds, int value, int minValue, int maxValue) DrawRectangleRec(rightButtonBound, GetColor(style[SPINNER_PRESSED_BUTTON_BORDER_COLOR])); DrawRectangle(rightButtonBound.x + 2, rightButtonBound.y + 2, rightButtonBound.width - 4, rightButtonBound.height - 4, GetColor(style[SPINNER_PRESSED_BUTTON_INSIDE_COLOR])); - DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); - DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_SYMBOL_COLOR])); - } + DrawText(FormatText("-"), leftButtonBound.x + (leftButtonBound.width/2 - (MeasureText(FormatText("+"), style[GLOBAL_TEXT_FONTSIZE]))/2), leftButtonBound.y + (leftButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_DEFAULT_SYMBOL_COLOR])); + DrawText(FormatText("+"), rightButtonBound.x + (rightButtonBound.width/2 - (MeasureText(FormatText("-"), style[GLOBAL_TEXT_FONTSIZE]))/2), rightButtonBound.y + (rightButtonBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_SYMBOL_COLOR])); + } + DrawRectangleRec(labelBoxBound, GetColor(style[SPINNER_LABEL_BORDER_COLOR])); DrawRectangle(labelBoxBound.x + 1, labelBoxBound.y + 1, labelBoxBound.width - 2, labelBoxBound.height - 2, GetColor(style[SPINNER_LABEL_INSIDE_COLOR])); - DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - textHeight/2), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_TEXT_COLOR])); + DrawText(FormatText("%i", value), labelBoxBound.x + (labelBoxBound.width/2 - textWidth/2), labelBoxBound.y + (labelBoxBound.height/2 - (style[GLOBAL_TEXT_FONTSIZE]/2)), style[GLOBAL_TEXT_FONTSIZE], GetColor(style[SPINNER_PRESSED_TEXT_COLOR])); } break; default: break; } + return value; } @@ -843,12 +845,12 @@ char *GuiTextBox(Rectangle bounds, char *text) { if (text[i] == '\0') break; - DrawText(FormatText("%c", text[i]), initPos, bounds.y + 5, style[TEXTBOX_TEXT_FONTSIZE], GetColor(style[TEXTBOX_TEXT_COLOR])); + DrawText(FormatText("%c", text[i]), initPos, bounds.y + style[TEXTBOX_TEXT_FONTSIZE], style[TEXTBOX_TEXT_FONTSIZE], GetColor(style[TEXTBOX_TEXT_COLOR])); initPos += ((GetDefaultFont().charRecs[(int)text[i] - 32].width + 2)); } - if ((framesCounter/20)%2 && CheckCollisionPointRec(mousePoint, bounds)) DrawLine(initPos + 2, bounds.y, initPos + 2, bounds.y + 10 + 10, GetColor(style[TEXTBOX_LINE_COLOR])); + if ((framesCounter/20)%2 && CheckCollisionPointRec(mousePoint, bounds)) DrawLine(initPos + 2, bounds.y + 5, initPos + 2, bounds.y + 10 + 15, GetColor(style[TEXTBOX_LINE_COLOR])); //-------------------------------------------------------------------- return text; diff --git a/src/raylib.h b/src/raylib.h index d86554517..16311df85 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib 1.3.0 (www.raylib.com) +* raylib 1.4.0 (www.raylib.com) * * A simple and easy-to-use library to learn videogames programming * @@ -70,7 +70,7 @@ #endif #if defined(PLATFORM_ANDROID) - #include // Defines android_app struct + typedef struct android_app; // Define android_app struct (android_native_app_glue.h) #endif //---------------------------------------------------------------------------------- @@ -186,6 +186,12 @@ // TODO: Review Xbox360 USB Controller Buttons +// Android Physic Buttons +#define ANDROID_BACK 4 +#define ANDROID_MENU 82 +#define ANDROID_VOLUME_UP 24 +#define ANDROID_VOLUME_DOWN 25 + // Some Basic Colors // NOTE: Custom raylib color palette for amazing visuals on WHITE background #define LIGHTGRAY (Color){ 200, 200, 200, 255 } // Light Gray @@ -291,6 +297,8 @@ typedef struct SpriteFont { int numChars; // Number of characters int *charValues; // Characters values array Rectangle *charRecs; // Characters rectangles within the texture + Vector2 *charOffsets; // Characters offsets (on drawing) + int *charAdvanceX; // Characters x advance (on drawing) } SpriteFont; // Camera type, defines a camera position/orientation in 3d space @@ -300,17 +308,27 @@ typedef struct Camera { Vector3 up; } Camera; +// Bounding box type +typedef struct BoundingBox { + Vector3 min; + Vector3 max; +} BoundingBox; + // Vertex data definning a mesh -// NOTE: If using OpenGL 1.1, data loaded in CPU; if OpenGL 3.3+ data loaded in GPU (vaoId) -typedef struct VertexData { - int vertexCount; - float *vertices; // 3 components per vertex - float *texcoords; // 2 components per vertex - float *normals; // 3 components per vertex - unsigned char *colors; // 4 components per vertex - unsigned int vaoId; - unsigned int vboId[4]; -} VertexData; +typedef struct Mesh { + int vertexCount; // num vertices + float *vertices; // vertex position (XYZ - 3 components per vertex) + float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) + float *texcoords2; // vertex second texture coordinates (useful for lightmaps) + float *normals; // vertex normals (XYZ - 3 components per vertex) + float *tangents; // vertex tangents (XYZ - 3 components per vertex) + unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) + + BoundingBox bounds; // mesh limits defined by min and max points + + unsigned int vaoId; // OpenGL Vertex Array Object id + unsigned int vboId[6]; // OpenGL Vertex Buffer Objects id (6 types of vertex data) +} Mesh; // Shader type (generic shader) typedef struct Shader { @@ -328,8 +346,10 @@ typedef struct Shader { int colorLoc; // Color attibute location point (vertex shader) // Uniforms - int projectionLoc; // Projection matrix uniform location point (vertex shader) - int modelviewLoc; // ModeView matrix uniform location point (vertex shader) + int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) + + int modelLoc; // Model transformation matrix uniform location point (vertex shader) + int viewLoc; // View transformation matrix uniform location point (vertex shader) int tintColorLoc; // Color uniform location point (fragment shader) int mapDiffuseLoc; // Diffuse map texture uniform location point (fragment shader) @@ -339,7 +359,7 @@ typedef struct Shader { // 3d Model type typedef struct Model { - VertexData mesh; + Mesh mesh; Matrix transform; Texture2D texture; // Only for OpenGL 1.1, on newer versions this should be in the shader Shader shader; @@ -366,6 +386,26 @@ typedef struct Wave { short channels; } Wave; +// Light type +typedef struct Light { + Vector3 position; + Vector3 direction; + float intensity; + float specIntensity; + Color diffuse; + Color ambient; + Color specular; +} Light; + +// Material type +typedef struct Material { + Color diffuse; + Color ambient; + Color specular; + float glossiness; + float normalDepth; +} Material; + // Texture formats // NOTE: Support depends on OpenGL version and platform typedef enum { @@ -408,9 +448,58 @@ typedef enum { GESTURE_PINCH_OUT = 1024 } Gestures; +typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction; + +// Gesture events +// NOTE: MAX_TOUCH_POINTS fixed to 4 +typedef struct { + int touchAction; + int pointCount; + int pointerId[4]; + Vector2 position[4]; +} GestureEvent; + // Camera system modes typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode; +// Collider types +typedef enum { RectangleCollider, CircleCollider } ColliderType; + +// Physics struct +typedef struct Physics { + bool enabled; + bool debug; // Should be used by programmer for testing purposes + Vector2 gravity; +} Physics; + +// Transform struct +typedef struct Transform { + Vector2 position; + float rotation; + Vector2 scale; +} Transform; + +// Rigidbody struct +typedef struct Rigidbody { + bool enabled; + float mass; + Vector2 acceleration; + Vector2 velocity; + bool isGrounded; + bool isContact; // Avoid freeze player when touching floor + bool applyGravity; + float friction; // 0.0f to 1.0f + float bounciness; // 0.0f to 1.0f +} Rigidbody; + +// Collider struct +typedef struct Collider { + bool enabled; + ColliderType type; + Rectangle bounds; // Just used for RectangleCollider type + int radius; // Just used for CircleCollider type +} Collider; + #ifdef __cplusplus extern "C" { // Prevents name mangling of functions #endif @@ -442,12 +531,14 @@ int GetScreenHeight(void); // Get current scree void ClearBackground(Color color); // Sets Background Color void BeginDrawing(void); // Setup drawing canvas to start drawing +void BeginDrawingEx(int blendMode, Shader shader, Matrix transform); // Setup drawing canvas with extended parameters void EndDrawing(void); // End canvas drawing and Swap Buffers (Double Buffering) void Begin3dMode(Camera cam); // Initializes 3D mode for drawing (Camera setup) void End3dMode(void); // Ends 3D mode and returns to default 2D orthographic mode -Ray GetMouseRay(Vector2 mousePosition, Camera camera); // TODO: Returns a ray trace from mouse position +Ray GetMouseRay(Vector2 mousePosition, Camera camera); // Returns a ray trace from mouse position +Vector2 WorldToScreen(Vector3 position, Camera camera); // Returns the screen space position from a 3d world space position void SetTargetFPS(int fps); // Set target FPS (maximum) float GetFPS(void); // Returns current FPS @@ -455,6 +546,9 @@ float GetFrameTime(void); // Returns time in s Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value int GetHexValue(Color color); // Returns hexadecimal value for a Color +float *ColorToFloat(Color color); // Converts Color to float array and normalizes +float *VectorToFloat(Vector3 vec); // Converts Vector3 to float array (defined in raymath module) +float *MatrixToVector(Matrix mat); // Converts Matrix to float array (defined in raymath module) int GetRandomValue(int min, int max); // Returns a random value between min and max (both included) Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f @@ -466,6 +560,9 @@ bool IsFileDropped(void); // Check if a file h char **GetDroppedFiles(int *count); // Retrieve dropped files into window void ClearDroppedFiles(void); // Clear dropped files paths buffer +void StorageSaveValue(int position, int value); // Storage save integer value (to defined position) +int StorageLoadValue(int position); // Storage load integer value (from defined position) + //------------------------------------------------------------------------------------ // Input Handling Functions (Module: core) //------------------------------------------------------------------------------------ @@ -504,20 +601,18 @@ bool IsGamepadButtonUp(int gamepad, int button); // Detect if a gamepad b int GetTouchX(void); // Returns touch position X (relative to screen size) int GetTouchY(void); // Returns touch position Y (relative to screen size) Vector2 GetTouchPosition(void); // Returns touch position XY (relative to screen size) +bool IsButtonPressed(int button); // Detect if an android physic button has been pressed +bool IsButtonDown(int button); // Detect if an android physic button is being pressed +bool IsButtonReleased(int button); // Detect if an android physic button has been released //------------------------------------------------------------------------------------ // Gestures and Touch Handling Functions (Module: gestures) //------------------------------------------------------------------------------------ -Vector2 GetRawTouchPosition(void); // Gewt touch position (raw) -#if defined(PLATFORM_WEB) -void InitGesturesSystem(void); // Init gestures system (web) -#elif defined(PLATFORM_ANDROID) -void InitGesturesSystem(struct android_app *app); // Init gestures system (android) -#endif void UpdateGestures(void); // Update gestures detected (must be called every frame) bool IsGestureDetected(void); // Check if a gesture have been detected int GetGestureType(void); // Get latest detected gesture void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags +void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures float GetGestureDragIntensity(void); // Get gesture drag intensity float GetGestureDragAngle(void); // Get gesture drag angle @@ -593,6 +688,7 @@ Color *GetImageData(Image image); Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two) void ImageFormat(Image *image, int newFormat); // Convert image data to desired format +void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering) Image ImageCopy(Image image); // Create an image duplicate (useful for transformations) void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle void ImageResize(Image *image, int newWidth, int newHeight); // Resize and image (bilinear filtering) @@ -631,6 +727,7 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int void DrawFPS(int posX, int posY); // Shows current FPS on top-left corner const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed' +const char *SubText(const char *text, int position, int length); // Get a piece of a text string //------------------------------------------------------------------------------------ // Basic 3d Shapes Drawing Functions (Module: models) @@ -655,7 +752,7 @@ void DrawGizmo(Vector3 position); // Model 3d Loading and Drawing Functions (Module: models) //------------------------------------------------------------------------------------ Model LoadModel(const char *fileName); // Load a 3d model (.OBJ) -Model LoadModelEx(VertexData data); // Load a 3d model (from vertex data) +Model LoadModelEx(Mesh data); // Load a 3d model (from vertex data) //Model LoadModelFromRES(const char *rresName, int resId); // TODO: Load a 3d model from rRES file (raylib Resource) Model LoadHeightmap(Image heightmap, float maxHeight); // Load a heightmap image as a 3d model Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based) @@ -665,6 +762,7 @@ void SetModelTexture(Model *model, Texture2D texture); void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) void DrawModelEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint); // Draw a model with extended parameters void DrawModelWires(Model model, Vector3 position, float scale, Color color); // Draw a model wires (with texture if set) +void DrawModelWiresEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec @@ -672,6 +770,7 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB); // Detect collision between two spheres bool CheckCollisionBoxes(Vector3 minBBox1, Vector3 maxBBox1, Vector3 minBBox2, Vector3 maxBBox2); // Detect collision between two boxes bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSphere, float radiusSphere); // Detect collision between box and sphere +bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox); // Detect collision between ray and box Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *playerPosition, float radius); // Detect collision of player radius with cubicmap // NOTE: Return the normal vector of the impacted surface @@ -698,6 +797,27 @@ void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textur void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied) +//---------------------------------------------------------------------------------- +// Physics System Functions (engine-module: physics) +//---------------------------------------------------------------------------------- +void InitPhysics(void); // Initialize all internal physics values +void SetPhysics(Physics settings); // Set physics settings values using Physics data type to overwrite internal physics settings + +void AddRigidbody(int index, Rigidbody rigidbody); // Initialize a new rigidbody with parameters to internal index slot +void AddCollider(int index, Collider collider); // Initialize a new Collider with parameters to internal index slot + +void ApplyPhysics(int index, Vector2 *position); // Apply physics to internal rigidbody, physics calculations are applied to position pointer parameter +void SetRigidbodyEnabled(int index, bool state); // Set enabled state to a defined rigidbody +void SetRigidbodyVelocity(int index, Vector2 velocity); // Set velocity of rigidbody (without considering of mass value) +void SetRigidbodyAcceleration(int index, Vector2 acceleration); // Set acceleration of rigidbody (without considering of mass value) +void AddRigidbodyForce(int index, Vector2 force); // Set rigidbody force (considering mass value) +void AddForceAtPosition(Vector2 position, float intensity, float radius); // Add a force to all enabled rigidbodies at a position + +void SetColliderEnabled(int index, bool state); // Set enabled state to a defined collider + +Rigidbody GetRigidbody(int index); // Returns the internal rigidbody data defined by index parameter +Collider GetCollider(int index); // Returns the internal collider data defined by index parameter + //------------------------------------------------------------------------------------ // Audio Loading and Playing Functions (Module: audio) //------------------------------------------------------------------------------------ diff --git a/src/raymath.c b/src/raymath.c index b1f90bb84..5feef59db 100644 --- a/src/raymath.c +++ b/src/raymath.c @@ -43,6 +43,18 @@ // Module Functions Definition - Vector3 math //---------------------------------------------------------------------------------- +// Converts Vector3 to float array +float *VectorToFloat(Vector3 vec) +{ + static float buffer[3]; + + buffer[0] = vec.x; + buffer[1] = vec.y; + buffer[2] = vec.z; + + return buffer; +} + // Add two vectors Vector3 VectorAdd(Vector3 v1, Vector3 v2) { @@ -225,29 +237,32 @@ Vector3 VectorZero(void) // Module Functions Definition - Matrix math //---------------------------------------------------------------------------------- -// Returns an OpenGL-ready vector (glMultMatrixf) -float *GetMatrixVector(Matrix mat) +// Converts Matrix to float array +// NOTE: Returned vector is a transposed version of the Matrix struct, +// it should be this way because, despite raymath use OpenGL column-major convention, +// Matrix struct memory alignment and variables naming are not coherent +float *MatrixToFloat(Matrix mat) { - static float vector[16]; + static float buffer[16]; - vector[0] = mat.m0; - vector[1] = mat.m4; - vector[2] = mat.m8; - vector[3] = mat.m12; - vector[4] = mat.m1; - vector[5] = mat.m5; - vector[6] = mat.m9; - vector[7] = mat.m13; - vector[8] = mat.m2; - vector[9] = mat.m6; - vector[10] = mat.m10; - vector[11] = mat.m14; - vector[12] = mat.m3; - vector[13] = mat.m7; - vector[14] = mat.m11; - vector[15] = mat.m15; + buffer[0] = mat.m0; + buffer[1] = mat.m4; + buffer[2] = mat.m8; + buffer[3] = mat.m12; + buffer[4] = mat.m1; + buffer[5] = mat.m5; + buffer[6] = mat.m9; + buffer[7] = mat.m13; + buffer[8] = mat.m2; + buffer[9] = mat.m6; + buffer[10] = mat.m10; + buffer[11] = mat.m14; + buffer[12] = mat.m3; + buffer[13] = mat.m7; + buffer[14] = mat.m11; + buffer[15] = mat.m15; - return vector; + return buffer; } // Compute matrix determinant @@ -598,33 +613,22 @@ Matrix MatrixMultiply(Matrix left, Matrix right) { Matrix result; - // Cache the matrix values (speed optimization) - float a00 = left.m0, a01 = left.m1, a02 = left.m2, a03 = left.m3; - float a10 = left.m4, a11 = left.m5, a12 = left.m6, a13 = left.m7; - float a20 = left.m8, a21 = left.m9, a22 = left.m10, a23 = left.m11; - float a30 = left.m12, a31 = left.m13, a32 = left.m14, a33 = left.m15; - - float b00 = right.m0, b01 = right.m1, b02 = right.m2, b03 = right.m3; - float b10 = right.m4, b11 = right.m5, b12 = right.m6, b13 = right.m7; - float b20 = right.m8, b21 = right.m9, b22 = right.m10, b23 = right.m11; - float b30 = right.m12, b31 = right.m13, b32 = right.m14, b33 = right.m15; - - result.m0 = b00*a00 + b01*a10 + b02*a20 + b03*a30; - result.m1 = b00*a01 + b01*a11 + b02*a21 + b03*a31; - result.m2 = b00*a02 + b01*a12 + b02*a22 + b03*a32; - result.m3 = b00*a03 + b01*a13 + b02*a23 + b03*a33; - result.m4 = b10*a00 + b11*a10 + b12*a20 + b13*a30; - result.m5 = b10*a01 + b11*a11 + b12*a21 + b13*a31; - result.m6 = b10*a02 + b11*a12 + b12*a22 + b13*a32; - result.m7 = b10*a03 + b11*a13 + b12*a23 + b13*a33; - result.m8 = b20*a00 + b21*a10 + b22*a20 + b23*a30; - result.m9 = b20*a01 + b21*a11 + b22*a21 + b23*a31; - result.m10 = b20*a02 + b21*a12 + b22*a22 + b23*a32; - result.m11 = b20*a03 + b21*a13 + b22*a23 + b23*a33; - result.m12 = b30*a00 + b31*a10 + b32*a20 + b33*a30; - result.m13 = b30*a01 + b31*a11 + b32*a21 + b33*a31; - result.m14 = b30*a02 + b31*a12 + b32*a22 + b33*a32; - result.m15 = b30*a03 + b31*a13 + b32*a23 + b33*a33; + result.m0 = right.m0*left.m0 + right.m1*left.m4 + right.m2*left.m8 + right.m3*left.m12; + result.m1 = right.m0*left.m1 + right.m1*left.m5 + right.m2*left.m9 + right.m3*left.m13; + result.m2 = right.m0*left.m2 + right.m1*left.m6 + right.m2*left.m10 + right.m3*left.m14; + result.m3 = right.m0*left.m3 + right.m1*left.m7 + right.m2*left.m11 + right.m3*left.m15; + result.m4 = right.m4*left.m0 + right.m5*left.m4 + right.m6*left.m8 + right.m7*left.m12; + result.m5 = right.m4*left.m1 + right.m5*left.m5 + right.m6*left.m9 + right.m7*left.m13; + result.m6 = right.m4*left.m2 + right.m5*left.m6 + right.m6*left.m10 + right.m7*left.m14; + result.m7 = right.m4*left.m3 + right.m5*left.m7 + right.m6*left.m11 + right.m7*left.m15; + result.m8 = right.m8*left.m0 + right.m9*left.m4 + right.m10*left.m8 + right.m11*left.m12; + result.m9 = right.m8*left.m1 + right.m9*left.m5 + right.m10*left.m9 + right.m11*left.m13; + result.m10 = right.m8*left.m2 + right.m9*left.m6 + right.m10*left.m10 + right.m11*left.m14; + result.m11 = right.m8*left.m3 + right.m9*left.m7 + right.m10*left.m11 + right.m11*left.m15; + result.m12 = right.m12*left.m0 + right.m13*left.m4 + right.m14*left.m8 + right.m15*left.m12; + result.m13 = right.m12*left.m1 + right.m13*left.m5 + right.m14*left.m9 + right.m15*left.m13; + result.m14 = right.m12*left.m2 + right.m13*left.m6 + right.m14*left.m10 + right.m15*left.m14; + result.m15 = right.m12*left.m3 + right.m13*left.m7 + right.m14*left.m11 + right.m15*left.m15; return result; } diff --git a/src/raymath.h b/src/raymath.h index e140b74ca..507bf52fa 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -79,6 +79,7 @@ extern "C" { // Prevents name mangling of functions //------------------------------------------------------------------------------------ // Functions Declaration to work with Vector3 //------------------------------------------------------------------------------------ +float *VectorToFloat(Vector3 vec); // Converts Vector3 to float array Vector3 VectorAdd(Vector3 v1, Vector3 v2); // Add two vectors Vector3 VectorSubtract(Vector3 v1, Vector3 v2); // Substract two vectors Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2); // Calculate two vectors cross product @@ -97,7 +98,7 @@ Vector3 VectorZero(void); // Return a Vector3 init //------------------------------------------------------------------------------------ // Functions Declaration to work with Matrix //------------------------------------------------------------------------------------ -float *GetMatrixVector(Matrix mat); // Returns an OpenGL-ready vector (glMultMatrixf) +float *MatrixToFloat(Matrix mat); // Converts Matrix to float array float MatrixDeterminant(Matrix mat); // Compute matrix determinant float MatrixTrace(Matrix mat); // Returns the trace of the matrix (sum of the values along the diagonal) void MatrixTranspose(Matrix *mat); // Transposes provided matrix diff --git a/src/rlgl.c b/src/rlgl.c index 3862ac74d..ca08e1a2c 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -397,33 +397,33 @@ void rlLoadIdentity(void) // Multiply the current matrix by a translation matrix void rlTranslatef(float x, float y, float z) { - Matrix mat = MatrixTranslate(x, y, z); - MatrixTranspose(&mat); + Matrix matTranslation = MatrixTranslate(x, y, z); + MatrixTranspose(&matTranslation); - *currentMatrix = MatrixMultiply(*currentMatrix, mat); + *currentMatrix = MatrixMultiply(*currentMatrix, matTranslation); } // Multiply the current matrix by a rotation matrix void rlRotatef(float angleDeg, float x, float y, float z) { - Matrix rotation = MatrixIdentity(); + Matrix matRotation = MatrixIdentity(); Vector3 axis = (Vector3){ x, y, z }; VectorNormalize(&axis); - rotation = MatrixRotate(angleDeg*DEG2RAD, axis); + matRotation = MatrixRotate(angleDeg*DEG2RAD, axis); - MatrixTranspose(&rotation); + MatrixTranspose(&matRotation); - *currentMatrix = MatrixMultiply(*currentMatrix, rotation); + *currentMatrix = MatrixMultiply(*currentMatrix, matRotation); } // Multiply the current matrix by a scaling matrix void rlScalef(float x, float y, float z) { - Matrix mat = MatrixScale(x, y, z); - MatrixTranspose(&mat); + Matrix matScale = MatrixScale(x, y, z); + MatrixTranspose(&matScale); - *currentMatrix = MatrixMultiply(*currentMatrix, mat); + *currentMatrix = MatrixMultiply(*currentMatrix, matScale); } // Multiply the current matrix by another matrix @@ -821,10 +821,10 @@ void rlDeleteBuffers(unsigned int id) void rlClearColor(byte r, byte g, byte b, byte a) { // Color values clamp to 0.0f(0) and 1.0f(255) - float cr = (float)r / 255; - float cg = (float)g / 255; - float cb = (float)b / 255; - float ca = (float)a / 255; + float cr = (float)r/255; + float cg = (float)g/255; + float cb = (float)b/255; + float ca = (float)a/255; glClearColor(cr, cg, cb, ca); } @@ -1094,32 +1094,34 @@ void rlglInit(void) // Modifies global variables: postproFbo, postproQuad void rlglInitPostpro(void) { +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) postproFbo = rlglLoadFBO(screenWidth, screenHeight); if (postproFbo.id > 0) { // Create a simple quad model to render fbo texture - VertexData quadData; + Mesh quad; - quadData.vertexCount = 6; + quad.vertexCount = 6; - float w = screenWidth; - float h = screenHeight; + float w = (float)screenWidth; + float h = (float)screenHeight; - float quadPositions[6*3] = { w, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, h, 0.0, 0, h, 0.0, w, h, 0.0, w, 0.0, 0.0 }; - float quadTexcoords[6*2] = { 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 }; - float quadNormals[6*3] = { 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0 }; + float quadPositions[6*3] = { w, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, h, 0.0f, 0.0f, h, 0.0f, w, h, 0.0f, w, 0.0f, 0.0f }; + float quadTexcoords[6*2] = { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f }; + float quadNormals[6*3] = { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f }; unsigned char quadColors[6*4] = { 255 }; - quadData.vertices = quadPositions; - quadData.texcoords = quadTexcoords; - quadData.normals = quadNormals; - quadData.colors = quadColors; + quad.vertices = quadPositions; + quad.texcoords = quadTexcoords; + quad.normals = quadNormals; + quad.colors = quadColors; - postproQuad = rlglLoadModel(quadData); + postproQuad = rlglLoadModel(quad); // NOTE: postproFbo.colorTextureId must be assigned to postproQuad model shader } +#endif } // Load a framebuffer object @@ -1195,11 +1197,13 @@ FBO rlglLoadFBO(int width, int height) // Unload framebuffer object void rlglUnloadFBO(FBO fbo) { +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glDeleteFramebuffers(1, &fbo.id); glDeleteTextures(1, &fbo.colorTextureId); glDeleteTextures(1, &fbo.depthTextureId); TraceLog(INFO, "[FBO ID %i] Unloaded framebuffer object successfully", fbo.id); +#endif } // Vertex Buffer Object deinitialization (memory free) @@ -1291,13 +1295,42 @@ void rlglDraw(void) if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0)) { glUseProgram(currentShader.id); + + Matrix matMVP = MatrixMultiply(modelview, projection); // Create modelview-projection matrix - glUniformMatrix4fv(currentShader.projectionLoc, 1, false, GetMatrixVector(projection)); - glUniformMatrix4fv(currentShader.modelviewLoc, 1, false, GetMatrixVector(modelview)); + glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP)); glUniform1i(currentShader.mapDiffuseLoc, 0); } - // NOTE: We draw in this order: triangle shapes, textured quads and lines + // NOTE: We draw in this order: lines, triangles, quads + + if (lines.vCounter > 0) + { + glBindTexture(GL_TEXTURE_2D, whiteTexture); + + if (vaoSupported) + { + glBindVertexArray(vaoLines); + } + else + { + glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[0]); + glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); + glEnableVertexAttribArray(currentShader.vertexLoc); + + if (currentShader.colorLoc != -1) + { + glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]); + glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); + glEnableVertexAttribArray(currentShader.colorLoc); + } + } + + glDrawArrays(GL_LINES, 0, lines.vCounter); + + if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindTexture(GL_TEXTURE_2D, 0); + } if (triangles.vCounter > 0) { @@ -1390,34 +1423,6 @@ void rlglDraw(void) glBindTexture(GL_TEXTURE_2D, 0); // Unbind textures } - if (lines.vCounter > 0) - { - glBindTexture(GL_TEXTURE_2D, whiteTexture); - - if (vaoSupported) - { - glBindVertexArray(vaoLines); - } - else - { - glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[0]); - glVertexAttribPointer(currentShader.vertexLoc, 3, GL_FLOAT, 0, 0, 0); - glEnableVertexAttribArray(currentShader.vertexLoc); - - if (currentShader.colorLoc != -1) - { - glBindBuffer(GL_ARRAY_BUFFER, linesBuffer[1]); - glVertexAttribPointer(currentShader.colorLoc, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, 0); - glEnableVertexAttribArray(currentShader.colorLoc); - } - } - - glDrawArrays(GL_LINES, 0, lines.vCounter); - - if (!vaoSupported) glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindTexture(GL_TEXTURE_2D, 0); - } - if (vaoSupported) glBindVertexArray(0); // Unbind VAO glUseProgram(0); // Unbind shader program @@ -1496,24 +1501,34 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glUseProgram(model.shader.id); - - // Apply transformation provided in model.transform matrix - Matrix modelviewworld = MatrixMultiply(model.transform, modelview); // World-space transformation - - // Apply transformations provided in function + + // At this point the modelview matrix just contains the view matrix (camera) + // That's because Begin3dMode() sets it an no model-drawing function modifies it, all use rlPushMatrix() and rlPopMatrix() + Matrix matView = modelview; // View matrix (camera) + Matrix matProjection = projection; // Projection matrix (perspective) + + // Calculate transformation matrix from function parameters // Get transform matrix (rotation -> scale -> translation) - Matrix rotation = MatrixRotate(rotationAngle*DEG2RAD, rotationAxis); + Matrix matRotation = MatrixRotate(rotationAngle*DEG2RAD, rotationAxis); Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); - Matrix translation = MatrixTranslate(position.x, position.y, position.z); + Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); + Matrix matTransform = MatrixMultiply(MatrixMultiply(matRotation, matScale), matTranslation); + + // Combine model internal transformation matrix (model.transform) with matrix generated by function parameters (matTransform) + Matrix matModel = MatrixMultiply(model.transform, matTransform); // Transform to world-space coordinates + + // Calculate model-view matrix combining matModel and matView + Matrix matModelView = MatrixMultiply(matModel, matView); // Transform to camera-space coordinates - Matrix transform = MatrixMultiply(MatrixMultiply(rotation, matScale), translation); // Object-space transformation matrix - modelviewworld = MatrixMultiply(transform, modelview); // World-space transformation + // Calculate model-view-projection matrix (MVP) + Matrix matMVP = MatrixMultiply(matModelView, matProjection); // Transform to screen-space coordinates - // Projection: Screen-space transformation - - // NOTE: Drawing in OpenGL 3.3+, transform is passed to shader - glUniformMatrix4fv(model.shader.projectionLoc, 1, false, GetMatrixVector(projection)); - glUniformMatrix4fv(model.shader.modelviewLoc, 1, false, GetMatrixVector(modelviewworld)); + // NOTE: Drawing in OpenGL 3.3+, matrices are passed to shader + // TODO: Reduce number of matrices passed to shaders, use only matMVP + glUniformMatrix4fv(model.shader.modelLoc, 1, false, MatrixToFloat(matModel)); + glUniformMatrix4fv(model.shader.viewLoc, 1, false, MatrixToFloat(matView)); + + glUniformMatrix4fv(model.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); // Apply color tinting to model // NOTE: Just update one uniform on fragment shader @@ -1652,7 +1667,7 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height) // NOTE: Using global variables: screenWidth, screenHeight Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) { - Vector3 result = { 0, 0, 0 }; // Object coordinates + Vector3 result = { 0.0f, 0.0f, 0.0f }; // Object coordinates //GLint viewport[4]; //glGetIntegerv(GL_VIEWPORT, viewport); // Not available on OpenGL ES 2.0 @@ -1683,11 +1698,11 @@ Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) quat.x = ((source.x - (float)x)/(float)width)*2.0f - 1.0f; quat.y = ((source.y - (float)y)/(float)height)*2.0f - 1.0f; quat.z = source.z*2.0f - 1.0f; - quat.w = 1.0; + quat.w = 1.0f; QuaternionTransform(&quat, modelviewprojection); - if (quat.w != 0.0) + if (quat.w != 0.0f) { quat.x /= quat.w; quat.y /= quat.w; @@ -1913,39 +1928,31 @@ void rlglUpdateTexture(unsigned int id, int width, int height, int format, void } // Generate mipmap data for selected texture -void rlglGenerateMipmaps(unsigned int textureId) +void rlglGenerateMipmaps(Texture2D texture) { - glBindTexture(GL_TEXTURE_2D, textureId); + glBindTexture(GL_TEXTURE_2D, texture.id); // Check if texture is power-of-two (POT) bool texIsPOT = false; - // NOTE: In OpenGL ES 2.0 we have no way to retrieve texture size from id - -#if defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) - int width, height; - - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); - - if (((width > 0) && ((width & (width - 1)) == 0)) && ((height > 0) && ((height & (height - 1)) == 0))) texIsPOT = true; -#endif + if (((texture.width > 0) && ((texture.width & (texture.width - 1)) == 0)) && + ((texture.height > 0) && ((texture.height & (texture.height - 1)) == 0))) texIsPOT = true; if ((texIsPOT) || (npotSupported)) { #if defined(GRAPHICS_API_OPENGL_11) // Compute required mipmaps - void *data = rlglReadTexturePixels(textureId, UNCOMPRESSED_R8G8B8A8); // TODO: Detect internal format + void *data = rlglReadTexturePixels(texture); // NOTE: data size is reallocated to fit mipmaps data - int mipmapCount = GenerateMipmaps(data, width, height); + int mipmapCount = GenerateMipmaps(data, texture.width, texture.height); // TODO: Adjust mipmap size depending on texture format! - int size = width*height*4; + int size = texture.width*texture.height*4; int offset = size; - int mipWidth = width/2; - int mipHeight = height/2; + int mipWidth = texture.width/2; + int mipHeight = texture.height/2; // Load the mipmaps for (int level = 1; level < mipmapCount; level++) @@ -1959,23 +1966,23 @@ void rlglGenerateMipmaps(unsigned int textureId) mipHeight /= 2; } - TraceLog(WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", textureId); + TraceLog(WARNING, "[TEX ID %i] Mipmaps generated manually on CPU side", texture.id); #elif defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glGenerateMipmap(GL_TEXTURE_2D); // Generate mipmaps automatically - TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically", textureId); + TraceLog(INFO, "[TEX ID %i] Mipmaps generated automatically", texture.id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Activate Trilinear filtering for mipmaps (must be available) #endif } - else TraceLog(WARNING, "[TEX ID %i] Mipmaps can not be generated", textureId); + else TraceLog(WARNING, "[TEX ID %i] Mipmaps can not be generated", texture.id); glBindTexture(GL_TEXTURE_2D, 0); } // Load vertex data into a VAO (if supported) and VBO -Model rlglLoadModel(VertexData mesh) +Model rlglLoadModel(Mesh mesh) { Model model; @@ -2164,7 +2171,7 @@ void *rlglReadTexturePixels(Texture2D texture) // Render texture to fbo glBindFramebuffer(GL_FRAMEBUFFER, fbo.id); - glClearColor(0.0, 0.0, 0.0, 0.0); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepthf(1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, width, height); @@ -2182,7 +2189,7 @@ void *rlglReadTexturePixels(Texture2D texture) quad.transform = MatrixIdentity(); quad.shader = simpleShader; - DrawModel(quad, (Vector3){ 0, 0, 0 }, 1.0f, WHITE); + DrawModel(quad, (Vector3){ 0.0f, 0.0f, 0.0f }, 1.0f, WHITE); pixels = (unsigned char *)malloc(texture.width*texture.height*3*sizeof(unsigned char)); @@ -2241,11 +2248,13 @@ Shader LoadShader(char *vsFileName, char *fsFileName) shader.colorLoc = -1; // Get handles to GLSL uniform locations (vertex shader) - shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix"); - shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix"); + shader.mvpLoc = glGetUniformLocation(shader.id, "mvpMatrix"); + + shader.modelLoc = glGetUniformLocation(shader.id, "modelMatrix"); + shader.viewLoc = glGetUniformLocation(shader.id, "viewMatrix"); // Get handles to GLSL uniform locations (fragment shader) - shader.tintColorLoc = glGetUniformLocation(shader.id, "tintColor"); + shader.tintColorLoc = glGetUniformLocation(shader.id, "fragTintColor"); shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0"); shader.mapNormalLoc = -1; // It can be set later shader.mapSpecularLoc = -1; // It can be set later @@ -2730,40 +2739,39 @@ static Shader LoadDefaultShader(void) "in vec2 vertexTexCoord; \n" "in vec4 vertexColor; \n" "out vec2 fragTexCoord; \n" - "out vec4 tintColor; \n" + "out vec4 fragTintColor; \n" #elif defined(GRAPHICS_API_OPENGL_ES2) char vShaderStr[] = "#version 100 \n" "attribute vec3 vertexPosition; \n" "attribute vec2 vertexTexCoord; \n" "attribute vec4 vertexColor; \n" "varying vec2 fragTexCoord; \n" - "varying vec4 tintColor; \n" + "varying vec4 fragTintColor; \n" #endif - "uniform mat4 projectionMatrix; \n" - "uniform mat4 modelviewMatrix; \n" + "uniform mat4 mvpMatrix; \n" "void main() \n" "{ \n" " fragTexCoord = vertexTexCoord; \n" - " tintColor = vertexColor; \n" - " gl_Position = projectionMatrix*modelviewMatrix*vec4(vertexPosition, 1.0); \n" + " fragTintColor = vertexColor; \n" + " gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n" "} \n"; // Fragment shader directly defined, no external file required #if defined(GRAPHICS_API_OPENGL_33) char fShaderStr[] = "#version 330 \n" "in vec2 fragTexCoord; \n" - "in vec4 tintColor; \n" + "in vec4 fragTintColor; \n" #elif defined(GRAPHICS_API_OPENGL_ES2) char fShaderStr[] = "#version 100 \n" "precision mediump float; \n" // precision required for OpenGL ES2 (WebGL) "varying vec2 fragTexCoord; \n" - "varying vec4 tintColor; \n" + "varying vec4 fragTintColor; \n" #endif "uniform sampler2D texture0; \n" "void main() \n" "{ \n" " vec4 texelColor = texture2D(texture0, fragTexCoord); \n" // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0, use texture() instead - " gl_FragColor = texelColor*tintColor; \n" + " gl_FragColor = texelColor*fragTintColor; \n" "} \n"; shader.id = LoadShaderProgram(vShaderStr, fShaderStr); @@ -2780,8 +2788,10 @@ static Shader LoadDefaultShader(void) shader.normalLoc = -1; // Get handles to GLSL uniform locations (vertex shader) - shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix"); - shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix"); + shader.mvpLoc = glGetUniformLocation(shader.id, "mvpMatrix"); + + shader.modelLoc = glGetUniformLocation(shader.id, "modelMatrix"); + shader.viewLoc = glGetUniformLocation(shader.id, "viewMatrix"); // Get handles to GLSL uniform locations (fragment shader) shader.tintColorLoc = -1; @@ -2821,12 +2831,11 @@ static Shader LoadSimpleShader(void) "attribute vec3 vertexNormal; \n" "varying vec2 fragTexCoord; \n" #endif - "uniform mat4 projectionMatrix; \n" - "uniform mat4 modelviewMatrix; \n" + "uniform mat4 mvpMatrix; \n" "void main() \n" "{ \n" " fragTexCoord = vertexTexCoord; \n" - " gl_Position = projectionMatrix*modelviewMatrix*vec4(vertexPosition, 1.0); \n" + " gl_Position = mvpMatrix*vec4(vertexPosition, 1.0); \n" "} \n"; // Fragment shader directly defined, no external file required @@ -2839,11 +2848,11 @@ static Shader LoadSimpleShader(void) "varying vec2 fragTexCoord; \n" #endif "uniform sampler2D texture0; \n" - "uniform vec4 tintColor; \n" + "uniform vec4 fragTintColor; \n" "void main() \n" "{ \n" " vec4 texelColor = texture2D(texture0, fragTexCoord); \n" // NOTE: texture2D() is deprecated on OpenGL 3.3 and ES 3.0, use texture() instead - " gl_FragColor = texelColor*tintColor; \n" + " gl_FragColor = texelColor*fragTintColor; \n" "} \n"; shader.id = LoadShaderProgram(vShaderStr, fShaderStr); @@ -2860,11 +2869,13 @@ static Shader LoadSimpleShader(void) shader.colorLoc = -1; // Get handles to GLSL uniform locations (vertex shader) - shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix"); - shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix"); + shader.mvpLoc = glGetUniformLocation(shader.id, "mvpMatrix"); + + shader.modelLoc = glGetUniformLocation(shader.id, "modelMatrix"); + shader.viewLoc = glGetUniformLocation(shader.id, "viewMatrix"); // Get handles to GLSL uniform locations (fragment shader) - shader.tintColorLoc = glGetUniformLocation(shader.id, "tintColor"); + shader.tintColorLoc = glGetUniformLocation(shader.id, "fragTintColor"); shader.mapDiffuseLoc = glGetUniformLocation(shader.id, "texture0"); shader.mapNormalLoc = -1; // It can be set later shader.mapSpecularLoc = -1; // It can be set later @@ -3228,19 +3239,19 @@ static pixel *GenNextMipmap(pixel *srcData, int srcWidth, int srcHeight) int x2, y2; pixel prow, pcol; - int width = srcWidth / 2; - int height = srcHeight / 2; + int width = srcWidth/2; + int height = srcHeight/2; pixel *mipmap = (pixel *)malloc(width*height*sizeof(pixel)); // Scaling algorithm works perfectly (box-filter) for (int y = 0; y < height; y++) { - y2 = 2 * y; + y2 = 2*y; for (int x = 0; x < width; x++) { - x2 = 2 * x; + x2 = 2*x; prow.r = (srcData[y2*srcWidth + x2].r + srcData[y2*srcWidth + x2 + 1].r)/2; prow.g = (srcData[y2*srcWidth + x2].g + srcData[y2*srcWidth + x2 + 1].g)/2; diff --git a/src/rlgl.h b/src/rlgl.h index 0960fa835..066e03393 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -131,17 +131,22 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; COMPRESSED_ASTC_8x8_RGBA // 2 bpp } TextureFormat; - // VertexData type + // Mesh with vertex data type // NOTE: If using OpenGL 1.1, data loaded in CPU; if OpenGL 3.3+ data loaded in GPU (vaoId) - typedef struct VertexData { - int vertexCount; - float *vertices; // 3 components per vertex - float *texcoords; // 2 components per vertex - float *normals; // 3 components per vertex - unsigned char *colors; - unsigned int vaoId; - unsigned int vboId[4]; - } VertexData; + typedef struct Mesh { + int vertexCount; // num vertices + float *vertices; // vertex position (XYZ - 3 components per vertex) + float *texcoords; // vertex texture coordinates (UV - 2 components per vertex) + float *texcoords2; // vertex second texture coordinates (useful for lightmaps) + float *normals; // vertex normals (XYZ - 3 components per vertex) + float *tangents; // vertex tangents (XYZ - 3 components per vertex) + unsigned char *colors; // vertex colors (RGBA - 4 components per vertex) + + BoundingBox bounds; // mesh limits defined by min and max points + + unsigned int vaoId; // OpenGL Vertex Array Object id + unsigned int vboId[6]; // OpenGL Vertex Buffer Objects id (6 types of vertex data) + } Mesh; // Shader type typedef struct Shader { @@ -159,8 +164,10 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; int colorLoc; // Color attibute location point (vertex shader) // Uniforms - int projectionLoc; // Projection matrix uniform location point (vertex shader) - int modelviewLoc; // ModeView matrix uniform location point (vertex shader) + int mvpLoc; // ModelView-Projection matrix uniform location point (vertex shader) + + int modelLoc; // Model transformation matrix uniform location point (vertex shader) + int viewLoc; // View transformation matrix uniform location point (vertex shader) int tintColorLoc; // Color uniform location point (fragment shader) int mapDiffuseLoc; // Diffuse map texture uniform location point (fragment shader) @@ -177,7 +184,7 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; // 3d Model type typedef struct Model { - VertexData mesh; + Mesh mesh; Matrix transform; Texture2D texture; Shader shader; @@ -244,7 +251,7 @@ void rlglInitGraphics(int offsetX, int offsetY, int width, int height); // Init unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount); // Load texture in GPU void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data); // Update GPU texture with new data -void rlglGenerateMipmaps(unsigned int textureId); // Generate mipmap data for selected texture +void rlglGenerateMipmaps(Texture2D texture); // Generate mipmap data for selected texture // NOTE: There is a set of shader related functions that are available to end user, // to avoid creating function wrappers through core module, they have been directly declared in raylib.h @@ -252,7 +259,7 @@ void rlglGenerateMipmaps(unsigned int textureId); // G void rlglInitPostpro(void); // Initialize postprocessing system void rlglDrawPostpro(void); // Draw with postprocessing shader -Model rlglLoadModel(VertexData mesh); // Upload vertex data into GPU and provided VAO/VBO ids +Model rlglLoadModel(Mesh mesh); // Upload vertex data into GPU and provided VAO/VBO ids void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color color, bool wires); Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates diff --git a/src/shapes.c b/src/shapes.c index 071fa63c0..a47615368 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -391,16 +391,24 @@ bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, floa } // Check collision between circle and rectangle +// NOTE: Reviewed version to take into account corner limit case bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec) { - bool collision = false; + int recCenterX = rec.x + rec.width/2; + int recCenterY = rec.y + rec.height/2; + + float dx = abs(center.x - recCenterX); + float dy = abs(center.y - recCenterY); - float dx = fabs((rec.x + rec.width/2) - center.x); - float dy = fabs((rec.y + rec.height/2) - center.y); + if (dx > (rec.width/2 + radius)) { return false; } + if (dy > (rec.height/2 + radius)) { return false; } - if ((dx <= (rec.width/2 + radius)) && (dy <= (rec.height/2 + radius))) collision = true; + if (dx <= (rec.width/2)) { return true; } + if (dy <= (rec.height/2)) { return true; } - return collision; + float cornerDistanceSq = pow(dx - rec.width/2, 2) + pow(dy - rec.height/2, 2); + + return (cornerDistanceSq <= (radius*radius)); } // Get collision rectangle for two rectangles collision diff --git a/src/stb_truetype.h b/src/stb_truetype.h index ae60212e0..00d22eb6d 100644 --- a/src/stb_truetype.h +++ b/src/stb_truetype.h @@ -1,5 +1,5 @@ -// stb_truetype.h - v1.05 - public domain -// authored from 2009-2014 by Sean Barrett / RAD Game Tools +// stb_truetype.h - v1.08 - public domain +// authored from 2009-2015 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: // parse files @@ -39,49 +39,35 @@ // Omar Cornut // github:aloucks // Peter LaValle +// Sergey Popov +// Giumo X. Clanjor +// Higor Euripedes // // Misc other: // Ryan Gordon // // VERSION HISTORY // +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// variant PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) +// also more precise AA rasterizer, except if shapes overlap +// remove need for STBTT_sort // 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC // 1.04 (2015-04-15) typo in example // 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes -// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ -// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match -// non-oversampled; STBTT_POINT_SIZE for packed case only -// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling -// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) -// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID -// 0.8b (2014-07-07) fix a warning -// 0.8 (2014-05-25) fix a few more warnings -// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back -// 0.6c (2012-07-24) improve documentation -// 0.6b (2012-07-20) fix a few more warnings -// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, -// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty -// 0.5 (2011-12-09) bugfixes: -// subpixel glyph renderer computed wrong bounding box -// first vertex of shape can be off-curve (FreeSans) -// 0.4b (2011-12-03) fixed an error in the font baking example -// 0.4 (2011-12-01) kerning, subpixel rendering (tor) -// bugfixes for: -// codepoint-to-glyph conversion using table fmt=12 -// codepoint-to-glyph conversion using table fmt=4 -// stbtt_GetBakedQuad with non-square texture (Zer) -// updated Hello World! sample to use kerning and subpixel -// fixed some warnings -// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) -// userdata, malloc-from-userdata, non-zero fill (stb) -// 0.2 (2009-03-11) Fix unsigned/signed char warnings -// 0.1 (2009-03-09) First public release +// +// Full history can be found at the end of this file. // // LICENSE // // This software is in the public domain. Where that dedication is not -// recognized, you are granted a perpetual, irrevokable license to copy -// and modify this file as you see fit. +// recognized, you are granted a perpetual, irrevocable license to copy, +// distribute, and modify this file as you see fit. // // USAGE // @@ -102,7 +88,7 @@ // #include "stb_rect_pack.h" -- optional, but you really want it // stbtt_PackBegin() // stbtt_PackSetOversample() -- for improved quality on small fonts -// stbtt_PackFontRanges() +// stbtt_PackFontRanges() -- pack and renders // stbtt_PackEnd() // stbtt_GetPackedQuad() // @@ -120,6 +106,15 @@ // stbtt_GetFontVMetrics() // stbtt_GetCodepointKernAdvance() // +// Starting with version 1.06, the rasterizer was replaced with a new, +// faster and generally-more-precise rasterizer. The new rasterizer more +// accurately measures pixel coverage for anti-aliasing, except in the case +// where multiple shapes overlap, in which case it overestimates the AA pixel +// coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If +// this turns out to be a problem, you can re-enable the old rasterizer with +// #define STBTT_RASTERIZER_VERSION 1 +// which will incur about a 15% speed hit. +// // ADDITIONAL DOCUMENTATION // // Immediately after this block comment are a series of sample programs. @@ -219,7 +214,15 @@ // Baked bitmap interface 70 LOC / // Font name matching & access 150 LOC ---- 150 // C runtime library abstraction 60 LOC ---- 60 - +// +// +// PERFORMANCE MEASUREMENTS FOR 1.06: +// +// 32-bit 64-bit +// Previous release: 8.83 s 7.68 s +// Pool allocations: 7.72 s 6.34 s +// Inline sort : 6.54 s 5.65 s +// New rasterizer : 5.63 s 5.00 s ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -330,7 +333,7 @@ int main(int arg, char **argv) stbtt_fontinfo font; int i,j,ascent,baseline,ch=0; float scale, xpos=2; // leave a little padding in case the character extends left - char *text = "Heljo World!"; + char *text = "Heljo World!"; // intentionally misspelled to show 'lj' brokenness fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); stbtt_InitFont(&font, buffer, 0); @@ -388,12 +391,6 @@ int main(int arg, char **argv) typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; - // #define your own STBTT_sort() to override this to avoid qsort - #ifndef STBTT_sort - #include - #define STBTT_sort(data,num_items,item_size,compare_func) qsort(data,num_items,item_size,compare_func) - #endif - // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h #ifndef STBTT_ifloor #include @@ -511,13 +508,17 @@ typedef struct } stbtt_packedchar; typedef struct stbtt_pack_context stbtt_pack_context; +typedef struct stbtt_fontinfo stbtt_fontinfo; +#ifndef STB_RECT_PACK_VERSION +typedef struct stbrp_rect stbrp_rect; +#endif STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); // Initializes a packing context stored in the passed-in stbtt_pack_context. // Future calls using this context will pack characters into the bitmap passed // in here: a 1-channel bitmap that is weight x height. stride_in_bytes is // the distance from one row to the next (or 0 to mean they are packed tightly -// together). "padding" is // the amount of padding to leave between each +// together). "padding" is the amount of padding to leave between each // character (normally you want '1' for bitmaps you'll use as textures with // bilinear filtering). // @@ -546,28 +547,34 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontd typedef struct { float font_size; - int first_unicode_char_in_range; - int num_chars_in_range; + int first_unicode_codepoint_in_range; // if non-zero, then the chars are continuous, and this is the first codepoint + int *array_of_unicode_codepoints; // if non-zero, then this is an array of unicode codepoints + int num_chars; stbtt_packedchar *chardata_for_range; // output + unsigned char h_oversample, v_oversample; // don't set these, they're used internally } stbtt_pack_range; STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); // Creates character bitmaps from multiple ranges of characters stored in // ranges. This will usually create a better-packed bitmap than multiple -// calls to stbtt_PackFontRange. - +// calls to stbtt_PackFontRange. Note that you can call this multiple +// times within a single PackBegin/PackEnd. STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); // Oversampling a font increases the quality by allowing higher-quality subpixel // positioning, and is especially valuable at smaller text sizes. // // This function sets the amount of oversampling for all following calls to -// stbtt_PackFontRange(s). The default (no oversampling) is achieved by -// h_oversample=1, v_oversample=1. The total number of pixels required is +// stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given +// pack context. The default (no oversampling) is achieved by h_oversample=1 +// and v_oversample=1. The total number of pixels required is // h_oversample*v_oversample larger than the default; for example, 2x2 // oversampling requires 4x the storage of 1x1. For best results, render // oversampled textures with bilinear filtering. Look at the readme in // stb/tests/oversample for information about oversampled fonts +// +// To use with PackFontRangesGather etc., you must set it before calls +// call to PackFontRangesGatherRects. STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display @@ -575,6 +582,19 @@ STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, stbtt_aligned_quad *q, // output: quad to draw int align_to_integer); +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); +// Calling these functions in sequence is roughly equivalent to calling +// stbtt_PackFontRanges(). If you more control over the packing of multiple +// fonts, or if you want to pack custom data into a font texture, take a look +// at the source to of stbtt_PackFontRanges() and create a custom version +// using these functions, e.g. call GatherRects multiple times, +// building up a single array of rects, then call PackRects once, +// then call RenderIntoRects repeatedly. This may result in a +// better packing than calling PackFontRanges multiple times +// (or it may not). + // this is an opaque structure that you shouldn't mess with which holds // all the context needed from PackBegin to PackEnd. struct stbtt_pack_context { @@ -785,7 +805,16 @@ typedef struct unsigned char *pixels; } stbtt__bitmap; -STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata); +// rasterize a shape with quadratic beziers into a bitmap +STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into + float flatness_in_pixels, // allowable error of curve in pixels + stbtt_vertex *vertices, // array of vertices defining shape + int num_verts, // number of vertices in above array + float scale_x, float scale_y, // scale applied to input vertices + float shift_x, float shift_y, // translation applied to input vertices + int x_off, int y_off, // another translation applied to input + int invert, // if non-zero, vertically flip shape + void *userdata); // context for to STBTT_MALLOC ////////////////////////////////////////////////////////////////////////////// // @@ -900,8 +929,16 @@ enum { // languageID for STBTT_PLATFORM_ID_MAC #define STBTT_MAX_OVERSAMPLE 8 #endif +#if STBTT_MAX_OVERSAMPLE > 255 +#error "STBTT_MAX_OVERSAMPLE cannot be > 255" +#endif + typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; +#ifndef STBTT_RASTERIZER_VERSION +#define STBTT_RASTERIZER_VERSION 2 +#endif + ////////////////////////////////////////////////////////////////////////// // // accessors to parse data from file @@ -970,7 +1007,7 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *font_collection, stbtt_int32 n = ttLONG(font_collection+8); if (index >= n) return -1; - return ttULONG(font_collection+12+index*14); + return ttULONG(font_collection+12+index*4); } } return -1; @@ -1550,42 +1587,129 @@ STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codep stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); } +////////////////////////////////////////////////////////////////////////////// +// +// Rasterizer + +typedef struct stbtt__hheap_chunk +{ + struct stbtt__hheap_chunk *next; +} stbtt__hheap_chunk; + +typedef struct stbtt__hheap +{ + struct stbtt__hheap_chunk *head; + void *first_free; + int num_remaining_in_head_chunk; +} stbtt__hheap; + +static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) +{ + if (hh->first_free) { + void *p = hh->first_free; + hh->first_free = * (void **) p; + return p; + } else { + if (hh->num_remaining_in_head_chunk == 0) { + int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); + stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); + if (c == NULL) + return NULL; + c->next = hh->head; + hh->head = c; + hh->num_remaining_in_head_chunk = count; + } + --hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk; + } +} + +static void stbtt__hheap_free(stbtt__hheap *hh, void *p) +{ + *(void **) p = hh->first_free; + hh->first_free = p; +} + +static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) +{ + stbtt__hheap_chunk *c = hh->head; + while (c) { + stbtt__hheap_chunk *n = c->next; + STBTT_free(c, userdata); + c = n; + } +} + typedef struct stbtt__edge { float x0,y0, x1,y1; int invert; } stbtt__edge; + typedef struct stbtt__active_edge { + struct stbtt__active_edge *next; + #if STBTT_RASTERIZER_VERSION==1 int x,dx; float ey; - struct stbtt__active_edge *next; - int valid; + int direction; + #elif STBTT_RASTERIZER_VERSION==2 + float fx,fdx,fdy; + float direction; + float sy; + float ey; + #else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" + #endif } stbtt__active_edge; -#define FIXSHIFT 10 -#define FIX (1 << FIXSHIFT) -#define FIXMASK (FIX-1) +#if STBTT_RASTERIZER_VERSION == 1 +#define STBTT_FIXSHIFT 10 +#define STBTT_FIX (1 << STBTT_FIXSHIFT) +#define STBTT_FIXMASK (STBTT_FIX-1) -static stbtt__active_edge *new_active(stbtt__edge *e, int off_x, float start_point, void *userdata) +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) { - stbtt__active_edge *z = (stbtt__active_edge *) STBTT_malloc(sizeof(*z), userdata); // @TODO: make a pool of these!!! + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); - STBTT_assert(e->y0 <= start_point); if (!z) return z; - // round dx down to avoid going too far + + // round dx down to avoid overshooting if (dxdy < 0) - z->dx = -STBTT_ifloor(FIX * -dxdy); + z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); else - z->dx = STBTT_ifloor(FIX * dxdy); - z->x = STBTT_ifloor(FIX * (e->x0 + dxdy * (start_point - e->y0))); - z->x -= off_x * FIX; + z->dx = STBTT_ifloor(STBTT_FIX * dxdy); + + z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); // use z->dx so when we offset later it's by the same amount + z->x -= off_x * STBTT_FIX; + z->ey = e->y1; z->next = 0; - z->valid = e->invert ? 1 : -1; + z->direction = e->invert ? 1 : -1; return z; } +#elif STBTT_RASTERIZER_VERSION == 2 +static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) +{ + stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); + float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); + //STBTT_assert(e->y0 <= start_point); + if (!z) return z; + z->fdx = dxdy; + z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; + z->fx = e->x0 + dxdy * (start_point - e->y0); + z->fx -= off_x; + z->direction = e->invert ? 1.0f : -1.0f; + z->sy = e->y0; + z->ey = e->y1; + z->next = 0; + return z; +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif +#if STBTT_RASTERIZER_VERSION == 1 // note: this routine clips fills that extend off the edges... ideally this // wouldn't happen, but it could happen if the truetype glyph bounding boxes // are wrong, or if the user supplies a too-small bitmap @@ -1597,26 +1721,26 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac while (e) { if (w == 0) { // if we're currently at zero, we need to record the edge start point - x0 = e->x; w += e->valid; + x0 = e->x; w += e->direction; } else { - int x1 = e->x; w += e->valid; + int x1 = e->x; w += e->direction; // if we went to zero, we need to draw if (w == 0) { - int i = x0 >> FIXSHIFT; - int j = x1 >> FIXSHIFT; + int i = x0 >> STBTT_FIXSHIFT; + int j = x1 >> STBTT_FIXSHIFT; if (i < len && j >= 0) { if (i == j) { // x0,x1 are the same pixel, so compute combined coverage - scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> FIXSHIFT); + scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); } else { if (i >= 0) // add antialiasing for x0 - scanline[i] = scanline[i] + (stbtt_uint8) (((FIX - (x0 & FIXMASK)) * max_weight) >> FIXSHIFT); + scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); else i = -1; // clip if (j < len) // add antialiasing for x1 - scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & FIXMASK) * max_weight) >> FIXSHIFT); + scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); else j = len; // clip @@ -1633,6 +1757,7 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) { + stbtt__hheap hh = { 0, 0, 0 }; stbtt__active_edge *active = NULL; int y,j=0; int max_weight = (255 / vsubsample); // weight per vertical scanline @@ -1660,9 +1785,9 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, stbtt__active_edge * z = *step; if (z->ey <= scan_y) { *step = z->next; // delete from list - STBTT_assert(z->valid); - z->valid = 0; - STBTT_free(z, userdata); + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); } else { z->x += z->dx; // advance to position for current scanline step = &((*step)->next); // advance through list @@ -1691,7 +1816,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, // insert all edges that start before the center of this scanline -- omit ones that also end on this scanline while (e->y0 <= scan_y) { if (e->y1 > scan_y) { - stbtt__active_edge *z = new_active(e, off_x, scan_y, userdata); + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); // find insertion point if (active == NULL) active = z; @@ -1722,24 +1847,392 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, ++j; } - while (active) { - stbtt__active_edge *z = active; - active = active->next; - STBTT_free(z, userdata); - } + stbtt__hheap_cleanup(&hh, userdata); if (scanline != scanline_data) STBTT_free(scanline, userdata); } -static int stbtt__edge_compare(const void *p, const void *q) -{ - stbtt__edge *a = (stbtt__edge *) p; - stbtt__edge *b = (stbtt__edge *) q; +#elif STBTT_RASTERIZER_VERSION == 2 - if (a->y0 < b->y0) return -1; - if (a->y0 > b->y0) return 1; - return 0; +// the edge passed in here does not cross the vertical line at x or the vertical line at x+1 +// (i.e. it has already been clipped to those) +static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) +{ + if (y0 == y1) return; + STBTT_assert(y0 < y1); + STBTT_assert(e->sy <= e->ey); + if (y0 > e->ey) return; + if (y1 < e->sy) return; + if (y0 < e->sy) { + x0 += (x1-x0) * (e->sy - y0) / (y1-y0); + y0 = e->sy; + } + if (y1 > e->ey) { + x1 += (x1-x0) * (e->ey - y1) / (y1-y0); + y1 = e->ey; + } + + if (x0 == x) + STBTT_assert(x1 <= x+1); + else if (x0 == x+1) + STBTT_assert(x1 >= x); + else if (x0 <= x) + STBTT_assert(x1 <= x); + else if (x0 >= x+1) + STBTT_assert(x1 >= x+1); + else + STBTT_assert(x1 >= x && x1 <= x+1); + + if (x0 <= x && x1 <= x) + scanline[x] += e->direction * (y1-y0); + else if (x0 >= x+1 && x1 >= x+1) + ; + else { + STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); + scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); // coverage = 1 - average x position + } +} + +static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) +{ + float y_bottom = y_top+1; + + while (e) { + // brute force every pixel + + // compute intersection points with top & bottom + STBTT_assert(e->ey >= y_top); + + if (e->fdx == 0) { + float x0 = e->fx; + if (x0 < len) { + if (x0 >= 0) { + stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); + stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); + } else { + stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); + } + } + } else { + float x0 = e->fx; + float dx = e->fdx; + float xb = x0 + dx; + float x_top, x_bottom; + float sy0,sy1; + float dy = e->fdy; + STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); + + // compute endpoints of line segment clipped to this scanline (if the + // line segment starts on this scanline. x0 is the intersection of the + // line with y_top, but that may be off the line segment. + if (e->sy > y_top) { + x_top = x0 + dx * (e->sy - y_top); + sy0 = e->sy; + } else { + x_top = x0; + sy0 = y_top; + } + if (e->ey < y_bottom) { + x_bottom = x0 + dx * (e->ey - y_top); + sy1 = e->ey; + } else { + x_bottom = xb; + sy1 = y_bottom; + } + + if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { + // from here on, we don't have to range check x values + + if ((int) x_top == (int) x_bottom) { + float height; + // simple case, only spans one pixel + int x = (int) x_top; + height = sy1 - sy0; + STBTT_assert(x >= 0 && x < len); + scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height; + scanline_fill[x] += e->direction * height; // everything right of this pixel is filled + } else { + int x,x1,x2; + float y_crossing, step, sign, area; + // covers 2+ pixels + if (x_top > x_bottom) { + // flip scanline vertically; signed area is the same + float t; + sy0 = y_bottom - (sy0 - y_top); + sy1 = y_bottom - (sy1 - y_top); + t = sy0, sy0 = sy1, sy1 = t; + t = x_bottom, x_bottom = x_top, x_top = t; + dx = -dx; + dy = -dy; + t = x0, x0 = xb, xb = t; + } + + x1 = (int) x_top; + x2 = (int) x_bottom; + // compute intersection with y axis at x1+1 + y_crossing = (x1+1 - x0) * dy + y_top; + + sign = e->direction; + // area of the rectangle covered from y0..y_crossing + area = sign * (y_crossing-sy0); + // area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) + scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2); + + step = sign * dy; + for (x = x1+1; x < x2; ++x) { + scanline[x] += area + step/2; + area += step; + } + y_crossing += dy * (x2 - (x1+1)); + + STBTT_assert(fabs(area) <= 1.01f); + + scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing); + + scanline_fill[x2] += sign * (sy1-sy0); + } + } else { + // if edge goes outside of box we're drawing, we require + // clipping logic. since this does not match the intended use + // of this library, we use a different, very slow brute + // force implementation + int x; + for (x=0; x < len; ++x) { + // cases: + // + // there can be up to two intersections with the pixel. any intersection + // with left or right edges can be handled by splitting into two (or three) + // regions. intersections with top & bottom do not necessitate case-wise logic. + // + // the old way of doing this found the intersections with the left & right edges, + // then used some simple logic to produce up to three segments in sorted order + // from top-to-bottom. however, this had a problem: if an x edge was epsilon + // across the x border, then the corresponding y position might not be distinct + // from the other y segment, and it might ignored as an empty segment. to avoid + // that, we need to explicitly produce segments based on x positions. + + // rename variables to clear pairs + float y0 = y_top; + float x1 = (float) (x); + float x2 = (float) (x+1); + float x3 = xb; + float y3 = y_bottom; + float y1,y2; + + // x = e->x + e->dx * (y-y_top) + // (y-y_top) = (x - e->x) / e->dx + // y = (x - e->x) / e->dx + y_top + y1 = (x - x0) / dx + y_top; + y2 = (x+1 - x0) / dx + y_top; + + if (x0 < x1 && x3 > x2) { // three segments descending down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x1 && x0 > x2) { // three segments descending down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x1 && x3 > x1) { // two segments across x, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x3 < x1 && x0 > x1) { // two segments across x, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); + stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); + } else if (x0 < x2 && x3 > x2) { // two segments across x+1, down-right + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else if (x3 < x2 && x0 > x2) { // two segments across x+1, down-left + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); + stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); + } else { // one segment + stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); + } + } + } + } + e = e->next; + } +} + +// directly AA rasterize edges w/o supersampling +static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) +{ + stbtt__hheap hh = { 0, 0, 0 }; + stbtt__active_edge *active = NULL; + int y,j=0, i; + float scanline_data[129], *scanline, *scanline2; + + if (result->w > 64) + scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); + else + scanline = scanline_data; + + scanline2 = scanline + result->w; + + y = off_y; + e[n].y0 = (float) (off_y + result->h) + 1; + + while (j < result->h) { + // find center of pixel for this scanline + float scan_y_top = y + 0.0f; + float scan_y_bottom = y + 1.0f; + stbtt__active_edge **step = &active; + + STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); + STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); + + // update all active edges; + // remove all active edges that terminate before the top of this scanline + while (*step) { + stbtt__active_edge * z = *step; + if (z->ey <= scan_y_top) { + *step = z->next; // delete from list + STBTT_assert(z->direction); + z->direction = 0; + stbtt__hheap_free(&hh, z); + } else { + step = &((*step)->next); // advance through list + } + } + + // insert all edges that start before the bottom of this scanline + while (e->y0 <= scan_y_bottom) { + if (e->y0 != e->y1) { + stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); + STBTT_assert(z->ey >= scan_y_top); + // insert at front + z->next = active; + active = z; + } + ++e; + } + + // now process all active edges + if (active) + stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); + + { + float sum = 0; + for (i=0; i < result->w; ++i) { + float k; + int m; + sum += scanline2[i]; + k = scanline[i] + sum; + k = (float) fabs(k)*255 + 0.5f; + m = (int) k; + if (m > 255) m = 255; + result->pixels[j*result->stride + i] = (unsigned char) m; + } + } + // advance all the edges + step = &active; + while (*step) { + stbtt__active_edge *z = *step; + z->fx += z->fdx; // advance to position for current scanline + step = &((*step)->next); // advance through list + } + + ++y; + ++j; + } + + stbtt__hheap_cleanup(&hh, userdata); + + if (scanline != scanline_data) + STBTT_free(scanline, userdata); +} +#else +#error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif + +#define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) + +static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) +{ + int i,j; + for (i=1; i < n; ++i) { + stbtt__edge t = p[i], *a = &t; + j = i; + while (j > 0) { + stbtt__edge *b = &p[j-1]; + int c = STBTT__COMPARE(a,b); + if (!c) break; + p[j] = p[j-1]; + --j; + } + if (i != j) + p[j] = t; + } +} + +static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) +{ + /* threshhold for transitioning to insertion sort */ + while (n > 12) { + stbtt__edge t; + int c01,c12,c,m,i,j; + + /* compute median of three */ + m = n >> 1; + c01 = STBTT__COMPARE(&p[0],&p[m]); + c12 = STBTT__COMPARE(&p[m],&p[n-1]); + /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ + if (c01 != c12) { + /* otherwise, we'll need to swap something else to middle */ + int z; + c = STBTT__COMPARE(&p[0],&p[n-1]); + /* 0>mid && midn => n; 0 0 */ + /* 0n: 0>n => 0; 0 n */ + z = (c == c12) ? 0 : n-1; + t = p[z]; + p[z] = p[m]; + p[m] = t; + } + /* now p[m] is the median-of-three */ + /* swap it to the beginning so it won't move around */ + t = p[0]; + p[0] = p[m]; + p[m] = t; + + /* partition loop */ + i=1; + j=n-1; + for(;;) { + /* handling of equality is crucial here */ + /* for sentinels & efficiency with duplicates */ + for (;;++i) { + if (!STBTT__COMPARE(&p[i], &p[0])) break; + } + for (;;--j) { + if (!STBTT__COMPARE(&p[0], &p[j])) break; + } + /* make sure we haven't crossed */ + if (i >= j) break; + t = p[i]; + p[i] = p[j]; + p[j] = t; + + ++i; + --j; + } + /* recurse on smaller side, iterate on larger */ + if (j < (n-i)) { + stbtt__sort_edges_quicksort(p,j); + p = p+i; + n = n-i; + } else { + stbtt__sort_edges_quicksort(p+i, n-i); + n = j; + } + } +} + +static void stbtt__sort_edges(stbtt__edge *p, int n) +{ + stbtt__sort_edges_quicksort(p, n); + stbtt__sort_edges_ins_sort(p, n); } typedef struct @@ -1752,7 +2245,13 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou float y_scale_inv = invert ? -scale_y : scale_y; stbtt__edge *e; int n,i,j,k,m; +#if STBTT_RASTERIZER_VERSION == 1 int vsubsample = result->h < 8 ? 15 : 5; +#elif STBTT_RASTERIZER_VERSION == 2 + int vsubsample = 1; +#else + #error "Unrecognized value of STBTT_RASTERIZER_VERSION" +#endif // vsubsample should divide 255 evenly; otherwise we won't reach full opacity // now we have to blow out the windings into explicit edge lists @@ -1789,7 +2288,8 @@ static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcou } // now sort the edges by their highest point (should snap to integer, and then by x) - STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); + //STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); + stbtt__sort_edges(e, n); // now, traverse the scanlines and find the intersections on each scanline, use xor winding rule stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); @@ -2106,11 +2606,11 @@ typedef struct unsigned char x; } stbrp_node; -typedef struct +struct stbrp_rect { stbrp_coord x,y; int id,w,h,was_packed; -} stbrp_rect; +}; static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) { @@ -2177,7 +2677,8 @@ STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, in stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); - STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels + if (pixels) + STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels return 1; } @@ -2235,6 +2736,13 @@ static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_i pixels[i] = (unsigned char) (total / 4); } break; + case 5: + for (i=0; i <= safe_w; ++i) { + total += pixels[i] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; + pixels[i] = (unsigned char) (total / 5); + } + break; default: for (i=0; i <= safe_w; ++i) { total += pixels[i] - buffer[i & STBTT__OVER_MASK]; @@ -2289,6 +2797,13 @@ static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_i pixels[i*stride_in_bytes] = (unsigned char) (total / 4); } break; + case 5: + for (i=0; i <= safe_h; ++i) { + total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; + buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; + pixels[i*stride_in_bytes] = (unsigned char) (total / 5); + } + break; default: for (i=0; i <= safe_h; ++i) { total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; @@ -2320,63 +2835,62 @@ static float stbtt__oversample_shift(int oversample) return (float)-(oversample - 1) / (2.0f * (float)oversample); } -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { - stbtt_fontinfo info; - float recip_h = 1.0f / spc->h_oversample; - float recip_v = 1.0f / spc->v_oversample; - float sub_x = stbtt__oversample_shift(spc->h_oversample); - float sub_y = stbtt__oversample_shift(spc->v_oversample); - int i,j,k,n, return_value = 1; - stbrp_context *context = (stbrp_context *) spc->pack_info; - stbrp_rect *rects; + int i,j,k; - // flag all characters as NOT packed - for (i=0; i < num_ranges; ++i) - for (j=0; j < ranges[i].num_chars_in_range; ++j) - ranges[i].chardata_for_range[j].x0 = - ranges[i].chardata_for_range[j].y0 = - ranges[i].chardata_for_range[j].x1 = - ranges[i].chardata_for_range[j].y1 = 0; - - n = 0; - for (i=0; i < num_ranges; ++i) - n += ranges[i].num_chars_in_range; - - rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); - if (rects == NULL) - return 0; - - stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); k=0; for (i=0; i < num_ranges; ++i) { float fh = ranges[i].font_size; - float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh); - for (j=0; j < ranges[i].num_chars_in_range; ++j) { + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + ranges[i].h_oversample = (unsigned char) spc->h_oversample; + ranges[i].v_oversample = (unsigned char) spc->v_oversample; + for (j=0; j < ranges[i].num_chars; ++j) { int x0,y0,x1,y1; - stbtt_GetCodepointBitmapBoxSubpixel(&info, ranges[i].first_unicode_char_in_range + j, - scale * spc->h_oversample, - scale * spc->v_oversample, - 0,0, - &x0,&y0,&x1,&y1); + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); + stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, + scale * spc->h_oversample, + scale * spc->v_oversample, + 0,0, + &x0,&y0,&x1,&y1); rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); ++k; } } - stbrp_pack_rects(context, rects, k); + return k; +} + +// rects array must be big enough to accommodate all characters in the given ranges +STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) +{ + int i,j,k, return_value = 1; + + // save current values + int old_h_over = spc->h_oversample; + int old_v_over = spc->v_oversample; k = 0; for (i=0; i < num_ranges; ++i) { float fh = ranges[i].font_size; - float scale = fh > 0 ? stbtt_ScaleForPixelHeight(&info, fh) : stbtt_ScaleForMappingEmToPixels(&info, -fh); - for (j=0; j < ranges[i].num_chars_in_range; ++j) { + float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); + float recip_h,recip_v,sub_x,sub_y; + spc->h_oversample = ranges[i].h_oversample; + spc->v_oversample = ranges[i].v_oversample; + recip_h = 1.0f / spc->h_oversample; + recip_v = 1.0f / spc->v_oversample; + sub_x = stbtt__oversample_shift(spc->h_oversample); + sub_y = stbtt__oversample_shift(spc->v_oversample); + for (j=0; j < ranges[i].num_chars; ++j) { stbrp_rect *r = &rects[k]; if (r->was_packed) { stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; int advance, lsb, x0,y0,x1,y1; - int glyph = stbtt_FindGlyphIndex(&info, ranges[i].first_unicode_char_in_range + j); + int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; + int glyph = stbtt_FindGlyphIndex(info, codepoint); stbrp_coord pad = (stbrp_coord) spc->padding; // pad on left and top @@ -2384,12 +2898,12 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd r->y += pad; r->w -= pad; r->h -= pad; - stbtt_GetGlyphHMetrics(&info, glyph, &advance, &lsb); - stbtt_GetGlyphBitmapBox(&info, glyph, + stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); + stbtt_GetGlyphBitmapBox(info, glyph, scale * spc->h_oversample, scale * spc->v_oversample, &x0,&y0,&x1,&y1); - stbtt_MakeGlyphBitmapSubpixel(&info, + stbtt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes, r->w - spc->h_oversample+1, r->h - spc->v_oversample+1, @@ -2426,16 +2940,60 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd } } + // restore original values + spc->h_oversample = old_h_over; + spc->v_oversample = old_v_over; + + return return_value; +} + +STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) +{ + stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); +} + +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +{ + stbtt_fontinfo info; + int i,j,n, return_value = 1; + //stbrp_context *context = (stbrp_context *) spc->pack_info; + stbrp_rect *rects; + + // flag all characters as NOT packed + for (i=0; i < num_ranges; ++i) + for (j=0; j < ranges[i].num_chars; ++j) + ranges[i].chardata_for_range[j].x0 = + ranges[i].chardata_for_range[j].y0 = + ranges[i].chardata_for_range[j].x1 = + ranges[i].chardata_for_range[j].y1 = 0; + + n = 0; + for (i=0; i < num_ranges; ++i) + n += ranges[i].num_chars; + + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); + if (rects == NULL) + return 0; + + stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); + + n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); + + stbtt_PackFontRangesPackRects(spc, rects, n); + + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); + STBTT_free(rects, spc->user_allocator_context); return return_value; } STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, - int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) + int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) { stbtt_pack_range range; - range.first_unicode_char_in_range = first_unicode_char_in_range; - range.num_chars_in_range = num_chars_in_range; + range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; + range.array_of_unicode_codepoints = NULL; + range.num_chars = num_chars_in_range; range.chardata_for_range = chardata_for_range; range.font_size = font_size; return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); @@ -2630,3 +3188,48 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const } #endif // STB_TRUETYPE_IMPLEMENTATION + + +// FULL VERSION HISTORY +// +// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges +// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; +// allow PackFontRanges to pack and render in separate phases; +// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); +// fixed an assert() bug in the new rasterizer +// replace assert() with STBTT_assert() in new rasterizer +// 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) +// also more precise AA rasterizer, except if shapes overlap +// remove need for STBTT_sort +// 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC +// 1.04 (2015-04-15) typo in example +// 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes +// 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ +// 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match +// non-oversampled; STBTT_POINT_SIZE for packed case only +// 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling +// 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) +// 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID +// 0.8b (2014-07-07) fix a warning +// 0.8 (2014-05-25) fix a few more warnings +// 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back +// 0.6c (2012-07-24) improve documentation +// 0.6b (2012-07-20) fix a few more warnings +// 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, +// stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty +// 0.5 (2011-12-09) bugfixes: +// subpixel glyph renderer computed wrong bounding box +// first vertex of shape can be off-curve (FreeSans) +// 0.4b (2011-12-03) fixed an error in the font baking example +// 0.4 (2011-12-01) kerning, subpixel rendering (tor) +// bugfixes for: +// codepoint-to-glyph conversion using table fmt=12 +// codepoint-to-glyph conversion using table fmt=4 +// stbtt_GetBakedQuad with non-square texture (Zer) +// updated Hello World! sample to use kerning and subpixel +// fixed some warnings +// 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) +// userdata, malloc-from-userdata, non-zero fill (stb) +// 0.2 (2009-03-11) Fix unsigned/signed char warnings +// 0.1 (2009-03-09) First public release +// diff --git a/src/text.c b/src/text.c index d24ff9725..3755932d0 100644 --- a/src/text.c +++ b/src/text.c @@ -34,16 +34,19 @@ // Following libs are used on LoadTTF() #define STB_TRUETYPE_IMPLEMENTATION -#define STB_RECT_PACK_IMPLEMENTATION -#include "stb_rect_pack.h" #include "stb_truetype.h" +// Rectangle packing functions (not used at the moment) +//#define STB_RECT_PACK_IMPLEMENTATION +//#include "stb_rect_pack.h" + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- #define FONT_FIRST_CHAR 32 #define MAX_FONTCHARS 128 #define MAX_FORMATTEXT_LENGTH 64 +#define MAX_SUBTEXT_LENGTH 64 #define BIT_CHECK(a,b) ((a) & (1<<(b))) @@ -69,6 +72,7 @@ static SpriteFont defaultFont; // Default font provided by raylib static bool PixelIsMagenta(Color p); // Check if a pixel is magenta static int ParseImageData(Image image, int **charValues, Rectangle **charSet); // Parse image pixel data to obtain characters data static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font) +static SpriteFont LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file) static SpriteFont LoadTTF(const char *fileName, int fontSize); // Generate a sprite font image from TTF data (font size required) extern void LoadDefaultFont(void); @@ -184,6 +188,10 @@ extern void LoadDefaultFont(void) defaultFont.charValues = (int *)malloc(defaultFont.numChars*sizeof(int)); defaultFont.charRecs = (Rectangle *)malloc(defaultFont.numChars*sizeof(Rectangle)); // Allocate space for our character rectangle data // This memory should be freed at end! --> Done on CloseWindow() + + defaultFont.charOffsets = (Vector2 *)malloc(defaultFont.numChars*sizeof(Vector2)); + defaultFont.charAdvanceX = (int *)malloc(defaultFont.numChars*sizeof(int)); + int currentLine = 0; int currentPosX = charsDivisor; int testPosX = charsDivisor; @@ -209,6 +217,10 @@ extern void LoadDefaultFont(void) defaultFont.charRecs[i].y = charsDivisor + currentLine*(charsHeight + charsDivisor); } else currentPosX = testPosX; + + // NOTE: On default font character offsets and xAdvance are not required + defaultFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f }; + defaultFont.charAdvanceX[i] = 0; } defaultFont.size = defaultFont.charRecs[0].height; @@ -221,6 +233,8 @@ extern void UnloadDefaultFont(void) UnloadTexture(defaultFont.texture); free(defaultFont.charValues); free(defaultFont.charRecs); + free(defaultFont.charOffsets); + free(defaultFont.charAdvanceX); } // Get the default font, useful to be used with extended parameters @@ -236,7 +250,8 @@ SpriteFont LoadSpriteFont(const char *fileName) // Check file extension if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName); - else if (strcmp(GetExtension(fileName),"ttf") == 0) spriteFont = LoadTTF(fileName, 20); + else if (strcmp(GetExtension(fileName),"ttf") == 0) spriteFont = LoadTTF(fileName, 32); + else if (strcmp(GetExtension(fileName),"fnt") == 0) spriteFont = LoadBMFont(fileName); else { Image image = LoadImage(fileName); @@ -253,6 +268,16 @@ SpriteFont LoadSpriteFont(const char *fileName) spriteFont.numChars = numChars; spriteFont.texture = LoadTextureFromImage(image); // Convert loaded image to OpenGL texture spriteFont.size = spriteFont.charRecs[0].height; + + spriteFont.charOffsets = (Vector2 *)malloc(spriteFont.numChars*sizeof(Vector2)); + spriteFont.charAdvanceX = (int *)malloc(spriteFont.numChars*sizeof(int)); + + for (int i = 0; i < spriteFont.numChars; i++) + { + // NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0) + spriteFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f }; + spriteFont.charAdvanceX[i] = 0; + } } else { @@ -262,6 +287,12 @@ SpriteFont LoadSpriteFont(const char *fileName) UnloadImage(image); } + + if (spriteFont.texture.id == 0) + { + TraceLog(WARNING, "[%s] SpriteFont could not be loaded, using default font", fileName); + spriteFont = GetDefaultFont(); + } return spriteFont; } @@ -269,11 +300,17 @@ SpriteFont LoadSpriteFont(const char *fileName) // Unload SpriteFont from GPU memory void UnloadSpriteFont(SpriteFont spriteFont) { - UnloadTexture(spriteFont.texture); - free(spriteFont.charValues); - free(spriteFont.charRecs); - - TraceLog(INFO, "Unloaded sprite font data"); + // NOTE: Make sure spriteFont is not default font (fallback) + if (spriteFont.texture.id != defaultFont.texture.id) + { + UnloadTexture(spriteFont.texture); + free(spriteFont.charValues); + free(spriteFont.charRecs); + free(spriteFont.charOffsets); + free(spriteFont.charAdvanceX); + + TraceLog(INFO, "Unloaded sprite font data"); + } } // Draw text (using default font) @@ -295,14 +332,14 @@ void DrawText(const char *text, int posX, int posY, int fontSize, Color color) void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, int fontSize, int spacing, Color tint) { int length = strlen(text); - int offsetX = 0; - int offsetY = 0; // Line break! + int textOffsetX = 0; + int textOffsetY = 0; // Line break! float scaleFactor; unsigned char letter; Rectangle rec; - scaleFactor = (float)fontSize/spriteFont.charRecs[0].height; + scaleFactor = (float)fontSize/spriteFont.size; // NOTE: Some ugly hacks are made to support Latin-1 Extended characters directly // written in C code files (codified by default as UTF-8) @@ -331,8 +368,9 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, int f { if ((unsigned char)text[i] == '\n') { - offsetY += ((spriteFont.size + spriteFont.size/2)*scaleFactor); - offsetX = 0; + // NOTE: Fixed line spacing of 1.5 lines + textOffsetY += ((spriteFont.size + spriteFont.size/2)*scaleFactor); + textOffsetX = 0; rec.x = -1; } else rec = spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR]; @@ -340,9 +378,12 @@ void DrawTextEx(SpriteFont spriteFont, const char *text, Vector2 position, int f if (rec.x > 0) { - DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + offsetX, position.y + offsetY, rec.width*scaleFactor, rec.height*scaleFactor} , (Vector2){ 0, 0 }, 0.0f, tint); + DrawTexturePro(spriteFont.texture, rec, (Rectangle){ position.x + textOffsetX + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].x*scaleFactor, + position.y + textOffsetY + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].y*scaleFactor, + rec.width*scaleFactor, rec.height*scaleFactor} , (Vector2){ 0, 0 }, 0.0f, tint); - offsetX += (rec.width*scaleFactor + spacing); + if (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR] == 0) textOffsetX += (rec.width*scaleFactor + spacing); + else textOffsetX += (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR]*scaleFactor + spacing); } } } @@ -360,6 +401,31 @@ const char *FormatText(const char *text, ...) return buffer; } +// Get a piece of a text string +const char *SubText(const char *text, int position, int length) +{ + static char buffer[MAX_SUBTEXT_LENGTH]; + int textLength = strlen(text); + + if (position >= textLength) + { + position = textLength - 1; + length = 0; + } + + if (length >= textLength) length = textLength; + + for (int c = 0 ; c < length ; c++) + { + *(buffer+c) = *(text+position); + text++; + } + + *(buffer+length) = '\0'; + + return buffer; +} + // Measure string width for default font int MeasureText(const char *text, int fontSize) { @@ -393,14 +459,15 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int if (text[i] != '\n') { - textWidth += spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR].width; + if (spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR] != 0) textWidth += spriteFont.charAdvanceX[(int)text[i] - FONT_FIRST_CHAR]; + else textWidth += (spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR].width + spriteFont.charOffsets[(int)text[i] - FONT_FIRST_CHAR].x); } else { if (tempTextWidth < textWidth) tempTextWidth = textWidth; lenCounter = 0; textWidth = 0; - textHeight += (spriteFont.size + spriteFont.size/2); + textHeight += (spriteFont.size + spriteFont.size/2); // NOTE: Fixed line spacing of 1.5 lines } if (tempLen < lenCounter) tempLen = lenCounter; @@ -560,7 +627,7 @@ static SpriteFont LoadRBMF(const char *fileName) char charsDataType; // Char data type provided } rbmfInfoHeader; - SpriteFont spriteFont; + SpriteFont spriteFont = { 0 }; rbmfInfoHeader rbmfHeader; unsigned int *rbmfFileData = NULL; @@ -628,6 +695,8 @@ static SpriteFont LoadRBMF(const char *fileName) // Get characters data using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars spriteFont.charValues = (int *)malloc(spriteFont.numChars*sizeof(int)); spriteFont.charRecs = (Rectangle *)malloc(spriteFont.numChars*sizeof(Rectangle)); + spriteFont.charOffsets = (Vector2 *)malloc(spriteFont.numChars*sizeof(Vector2)); + spriteFont.charAdvanceX = (int *)malloc(spriteFont.numChars*sizeof(int)); int currentLine = 0; int currentPosX = charsDivisor; @@ -641,6 +710,10 @@ static SpriteFont LoadRBMF(const char *fileName) spriteFont.charRecs[i].y = charsDivisor + currentLine * ((int)rbmfHeader.charHeight + charsDivisor); spriteFont.charRecs[i].width = (int)rbmfCharWidthData[i]; spriteFont.charRecs[i].height = (int)rbmfHeader.charHeight; + + // NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0) + spriteFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f }; + spriteFont.charAdvanceX[i] = 0; testPosX += (spriteFont.charRecs[i].width + charsDivisor); @@ -669,114 +742,181 @@ static SpriteFont LoadRBMF(const char *fileName) return spriteFont; } -// Generate a sprite font from TTF data (font size required) -// NOTE: This function is a mess, it should be completely redone! -static SpriteFont LoadTTF(const char *fileName, int fontSize) +// Load a BMFont file (AngelCode font file) +static SpriteFont LoadBMFont(const char *fileName) { - // Steps: - - // 1) Generate sprite sheet image with characters from TTF - // 2) Load image as SpriteFont + #define MAX_BUFFER_SIZE 256 SpriteFont font = { 0 }; + font.texture.id = 0; + + char buffer[MAX_BUFFER_SIZE]; + char *searchPoint = NULL; + + int fontSize = 0; + int texWidth, texHeight; + char texFileName[128]; + int numChars = 0; - Image image; - image.width = 512; - image.height = 512; - //image.pixels = (Color *)malloc(image.width*image.height*sizeof(Color)); + int base; // Useless data + + FILE *fntFile; + + fntFile = fopen(fileName, "rt"); + + if (fntFile == NULL) + { + TraceLog(WARNING, "[%s] FNT file could not be opened", fileName); + return font; + } + + // NOTE: We skip first line, it contains no useful information + fgets(buffer, MAX_BUFFER_SIZE, fntFile); + //searchPoint = strstr(buffer, "size"); + //sscanf(searchPoint, "size=%i", &fontSize); + + fgets(buffer, MAX_BUFFER_SIZE, fntFile); + searchPoint = strstr(buffer, "lineHeight"); + sscanf(searchPoint, "lineHeight=%i base=%i scaleW=%i scaleH=%i", &fontSize, &base, &texWidth, &texHeight); + + TraceLog(DEBUG, "[%s] Font size: %i", fileName, fontSize); + TraceLog(DEBUG, "[%s] Font texture scale: %ix%i", fileName, texWidth, texHeight); + + fgets(buffer, MAX_BUFFER_SIZE, fntFile); + searchPoint = strstr(buffer, "file"); + sscanf(searchPoint, "file=\"%128[^\"]\"", texFileName); + + TraceLog(DEBUG, "[%s] Font texture filename: %s", fileName, texFileName); + + fgets(buffer, MAX_BUFFER_SIZE, fntFile); + searchPoint = strstr(buffer, "count"); + sscanf(searchPoint, "count=%i", &numChars); + + TraceLog(DEBUG, "[%s] Font num chars: %i", fileName, numChars); + + // Compose correct path using route of .fnt file (fileName) and texFileName + char *texPath = NULL; + char *lastSlash = NULL; + + lastSlash = strrchr(fileName, '/'); // you need escape character + texPath = malloc(strlen(fileName) - strlen(lastSlash) + 1 + strlen(texFileName) + 1); + memcpy(texPath, fileName, strlen(fileName) - strlen(lastSlash)); + strcat(texPath, "/"); + strcat(texPath, texFileName); + strcat(texPath, "\0"); + + TraceLog(DEBUG, "[%s] Font texture loading path: %s", fileName, texPath); + + font.texture = LoadTexture(texPath); + font.size = fontSize; + font.numChars = numChars; + font.charValues = (int *)malloc(numChars*sizeof(int)); + font.charRecs = (Rectangle *)malloc(numChars*sizeof(Rectangle)); + font.charOffsets = (Vector2 *)malloc(numChars*sizeof(Vector2)); + font.charAdvanceX = (int *)malloc(numChars*sizeof(int)); + + free(texPath); + + int charId, charX, charY, charWidth, charHeight, charOffsetX, charOffsetY, charAdvanceX; + + for (int i = 0; i < numChars; i++) + { + fgets(buffer, MAX_BUFFER_SIZE, fntFile); + sscanf(buffer, "char id=%i x=%i y=%i width=%i height=%i xoffset=%i yoffset=%i xadvance=%i", + &charId, &charX, &charY, &charWidth, &charHeight, &charOffsetX, &charOffsetY, &charAdvanceX); + + // Save data properly in sprite font + font.charValues[i] = charId; + font.charRecs[i] = (Rectangle){ charX, charY, charWidth, charHeight }; + font.charOffsets[i] = (Vector2){ (float)charOffsetX, (float)charOffsetY }; + font.charAdvanceX[i] = charAdvanceX; + } + + // TODO: Font data could be not ordered by charId: 32,33,34,35... review charValues and charRecs order + + fclose(fntFile); + + TraceLog(INFO, "[%s] SpriteFont loaded successfully", fileName); + + return font; + +} + +// Generate a sprite font from TTF file data (font size required) +// TODO: Review texture packing method and generation (use oversampling) +static SpriteFont LoadTTF(const char *fileName, int fontSize) +{ + // NOTE: Generated font uses some hardcoded values + #define FONT_TEXTURE_WIDTH 512 // Font texture width + #define FONT_TEXTURE_HEIGHT 512 // Font texture height + #define FONT_FIRST_CHAR 32 // Font first character (32 - space) + #define FONT_NUM_CHARS 95 // ASCII 32..126 is 95 glyphs unsigned char *ttfBuffer = (unsigned char *)malloc(1 << 25); + unsigned char *dataBitmap = (unsigned char *)malloc(FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT*sizeof(unsigned char)); // One channel bitmap returned! + stbtt_bakedchar charData[FONT_NUM_CHARS]; // ASCII 32..126 is 95 glyphs - // TODO: Load TTF and generate bitmap font and chars data -> REVIEW! - - stbtt_packedchar chardata[128]; // Num characters: 128 (?) -> REVIEW! - - unsigned char *tempBitmap = (unsigned char *)malloc(image.width*image.height*sizeof(unsigned char)); // One channel bitmap returned! - - // Reference struct -/* - typedef struct - { - unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap - float xoff,yoff,xadvance; - float xoff2,yoff2; - } stbtt_packedchar; -*/ - - stbtt_pack_context pc; - + SpriteFont font = { 0 }; + FILE *ttfFile = fopen(fileName, "rb"); + + if (ttfFile == NULL) + { + TraceLog(WARNING, "[%s] FNT file could not be opened", fileName); + return font; + } fread(ttfBuffer, 1, 1<<25, ttfFile); - stbtt_PackBegin(&pc, tempBitmap, image.width, image.height, 0, 1, NULL); - - //stbtt_PackSetOversampling(&pc, 1, 1); - //stbtt_PackFontRange(&pc, ttfBuffer, 0, fontSize, 32, 95, chardata[0]+32); - stbtt_PackSetOversampling(&pc, 2, 2); // Better results - stbtt_PackFontRange(&pc, ttfBuffer, 0, fontSize, 32, 95, chardata + 32); - //stbtt_PackSetOversampling(&pc, 3, 1); - //stbtt_PackFontRange(&pc, ttfBuffer, 0, fontSize, 32, 95, chardata[2]+32); - - stbtt_PackEnd(&pc); + // NOTE: Using stb_truetype crappy packing method, no guarante the font fits the image... + stbtt_BakeFontBitmap(ttfBuffer,0, fontSize, dataBitmap, FONT_TEXTURE_WIDTH, FONT_TEXTURE_HEIGHT, FONT_FIRST_CHAR, FONT_NUM_CHARS, charData); free(ttfBuffer); - - // Now we have image data in tempBitmap and chardata filled... -/* - for (int i = 0; i < 512*512; i++) + + // Convert image data from grayscale to to UNCOMPRESSED_GRAY_ALPHA + unsigned char *dataGrayAlpha = (unsigned char *)malloc(FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT*sizeof(unsigned char)*2); // Two channels + int k = 0; + + for (int i = 0; i < FONT_TEXTURE_WIDTH*FONT_TEXTURE_HEIGHT; i++) { - image.pixels[i].r = tempBitmap[i]; - image.pixels[i].g = tempBitmap[i]; - image.pixels[i].b = tempBitmap[i]; - image.pixels[i].a = 255; + dataGrayAlpha[k] = 255; + dataGrayAlpha[k + 1] = dataBitmap[i]; + + k += 2; } -*/ - free(tempBitmap); + + free(dataBitmap); + + // Sprite font generation from TTF extracted data + Image image; + image.width = FONT_TEXTURE_WIDTH; + image.height = FONT_TEXTURE_HEIGHT; + image.mipmaps = 1; + image.format = UNCOMPRESSED_GRAY_ALPHA; + image.data = dataGrayAlpha; - // REFERENCE EXAMPLE -/* - //To draw, provide *text, posX, posY - //stbtt_aligned_quad letter; - //stbtt_GetPackedQuad(chardata[0], BITMAP_W, BITMAP_H, *text++, &posX, &posY, &letter, font ? 0 : integer_align); - - void print(float x, float y, int fontNum, char *text) - { - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, font_tex); - glBegin(GL_QUADS); - while (*text) { - stbtt_aligned_quad q; - stbtt_GetPackedQuad(chardata[fontNum], BITMAP_W, BITMAP_H, *text++, &x, &y, &q, fontNum ? 0 : integer_align); - drawBoxTC(q.x0,q.y0,q.x1,q.y1, q.s0,q.t0,q.s1,q.t1); - } - glEnd(); - } - - print(100,160, 0, "This is a test"); -*/ -/* - font.numChars = 95; - font.charValues (int *)malloc(font.numChars*sizeof(int)); - font.charRecs = (Character *)malloc(font.numChars*sizeof(Character)); font.texture = LoadTextureFromImage(image); + UnloadImage(image); // Unloads dataGrayAlpha - //stbtt_aligned_quad letter; - //int x = 0, y = 0; - + font.size = fontSize; + font.numChars = FONT_NUM_CHARS; + font.charValues = (int *)malloc(font.numChars*sizeof(int)); + font.charRecs = (Rectangle *)malloc(font.numChars*sizeof(Rectangle)); + font.charOffsets = (Vector2 *)malloc(font.numChars*sizeof(Vector2)); + font.charAdvanceX = (int *)malloc(font.numChars*sizeof(int)); + for (int i = 0; i < font.numChars; i++) { - font.charValues[i] = i + 32; + font.charValues[i] = i + FONT_FIRST_CHAR; - //stbtt_GetPackedQuad(chardata[0], 512, 512, i, &x, &y, &letter, 0); - - font.charRecs[i].x = chardata[i + 32].x0; - font.charRecs[i].y = chardata[i + 32].y0; - font.charRecs[i].width = chardata[i + 32].x1 - chardata[i + 32].x0; - font.charRecs[i].height = chardata[i + 32].y1 - chardata[i + 32].y0; + font.charRecs[i].x = (int)charData[i].x0; + font.charRecs[i].y = (int)charData[i].y0; + font.charRecs[i].width = (int)charData[i].x1 - (int)charData[i].x0; + font.charRecs[i].height = (int)charData[i].y1 - (int)charData[i].y0; + + font.charOffsets[i] = (Vector2){ charData[i].xoff, charData[i].yoff }; + font.charAdvanceX[i] = (int)charData[i].xadvance; } -*/ - UnloadImage(image); return font; } \ No newline at end of file diff --git a/src/textures.c b/src/textures.c index f97812dad..f03d2d9ad 100644 --- a/src/textures.c +++ b/src/textures.c @@ -549,8 +549,7 @@ void ImageFormat(Image *image, int newFormat) for (int i = 0; i < image->width*image->height; i++) { - ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[k].r*0.299f + (float)pixels[k].g*0.587f + (float)pixels[k].b*0.114f); - k++; + ((unsigned char *)image->data)[i] = (unsigned char)((float)pixels[i].r*0.299f + (float)pixels[i].g*0.587f + (float)pixels[i].b*0.114f); } } break; @@ -570,9 +569,9 @@ void ImageFormat(Image *image, int newFormat) { image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short)); - unsigned char r; - unsigned char g; - unsigned char b; + unsigned char r = 0; + unsigned char g = 0; + unsigned char b = 0; for (int i = 0; i < image->width*image->height; i++) { @@ -581,8 +580,6 @@ void ImageFormat(Image *image, int newFormat) b = (unsigned char)(round((float)pixels[k].b*31/255)); ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 5 | (unsigned short)b; - - k++; } } break; @@ -600,45 +597,43 @@ void ImageFormat(Image *image, int newFormat) } break; case UNCOMPRESSED_R5G5B5A1: { + #define ALPHA_THRESHOLD 50 + image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short)); - unsigned char r; - unsigned char g; - unsigned char b; - unsigned char a = 1; + unsigned char r = 0; + unsigned char g = 0; + unsigned char b = 0; + unsigned char a = 0; for (int i = 0; i < image->width*image->height; i++) { - r = (unsigned char)(round((float)pixels[k].r*31/255)); - g = (unsigned char)(round((float)pixels[k].g*31/255)); - b = (unsigned char)(round((float)pixels[k].b*31/255)); - a = (pixels[k].a > 50) ? 1 : 0; + r = (unsigned char)(round((float)pixels[i].r*31/255)); + g = (unsigned char)(round((float)pixels[i].g*31/255)); + b = (unsigned char)(round((float)pixels[i].b*31/255)); + a = (pixels[i].a > ALPHA_THRESHOLD) ? 1 : 0; - ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1| (unsigned short)a; - - k++; + ((unsigned short *)image->data)[i] = (unsigned short)r << 11 | (unsigned short)g << 6 | (unsigned short)b << 1 | (unsigned short)a; } - + } break; case UNCOMPRESSED_R4G4B4A4: { image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short)); - unsigned char r; - unsigned char g; - unsigned char b; - unsigned char a; + unsigned char r = 0; + unsigned char g = 0; + unsigned char b = 0; + unsigned char a = 0; for (int i = 0; i < image->width*image->height; i++) { - r = (unsigned char)(round((float)pixels[k].r*15/255)); - g = (unsigned char)(round((float)pixels[k].g*15/255)); - b = (unsigned char)(round((float)pixels[k].b*15/255)); - a = (unsigned char)(round((float)pixels[k].a*15/255)); + r = (unsigned char)(round((float)pixels[i].r*15/255)); + g = (unsigned char)(round((float)pixels[i].g*15/255)); + b = (unsigned char)(round((float)pixels[i].b*15/255)); + a = (unsigned char)(round((float)pixels[i].a*15/255)); ((unsigned short *)image->data)[i] = (unsigned short)r << 12 | (unsigned short)g << 8| (unsigned short)b << 4| (unsigned short)a; - - k++; } } break; @@ -664,6 +659,114 @@ void ImageFormat(Image *image, int newFormat) } } +// Dither image data to 16bpp or lower (Floyd-Steinberg dithering) +// NOTE: In case selected bpp do not represent an known 16bit format, +// dithered data is stored in the LSB part of the unsigned short +void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp) +{ + if (image->format >= 8) + { + TraceLog(WARNING, "Compressed data formats can not be dithered"); + return; + } + + if ((rBpp+gBpp+bBpp+aBpp) > 16) + { + TraceLog(WARNING, "Unsupported dithering bpps (%ibpp), only 16bpp or lower modes supported", (rBpp+gBpp+bBpp+aBpp)); + } + else + { + Color *pixels = GetImageData(*image); + + free(image->data); // free old image data + + if ((image->format != UNCOMPRESSED_R8G8B8) && (image->format != UNCOMPRESSED_R8G8B8A8)) + { + TraceLog(WARNING, "Image format is already 16bpp or lower, dithering could have no effect"); + } + + // Define new image format, check if desired bpp match internal known format + if ((rBpp == 5) && (gBpp == 6) && (bBpp == 5) && (aBpp == 0)) image->format = UNCOMPRESSED_R5G6B5; + else if ((rBpp == 5) && (gBpp == 5) && (bBpp == 5) && (aBpp == 1)) image->format = UNCOMPRESSED_R5G5B5A1; + else if ((rBpp == 4) && (gBpp == 4) && (bBpp == 4) && (aBpp == 4)) image->format = UNCOMPRESSED_R4G4B4A4; + else + { + image->format = 0; + TraceLog(WARNING, "Unsupported dithered OpenGL internal format: %ibpp (R%iG%iB%iA%i)", (rBpp+gBpp+bBpp+aBpp), rBpp, gBpp, bBpp, aBpp); + } + + // NOTE: We will store the dithered data as unsigned short (16bpp) + image->data = (unsigned short *)malloc(image->width*image->height*sizeof(unsigned short)); + + Color oldpixel = WHITE; + Color newpixel = WHITE; + + int error_r, error_g, error_b; + unsigned short pixel_r, pixel_g, pixel_b, pixel_a; // Used for 16bit pixel composition + + #define MIN(a,b) (((a)<(b))?(a):(b)) + + for (int y = 0; y < image->height; y++) + { + for (int x = 0; x < image->width; x++) + { + oldpixel = pixels[y*image->width + x]; + + // TODO: New pixel obtained by bits truncate, it would be better to round values (check ImageFormat()) + newpixel.r = oldpixel.r>>(8 - rBpp); // R bits + newpixel.g = oldpixel.g>>(8 - gBpp); // G bits + newpixel.b = oldpixel.b>>(8 - bBpp); // B bits + newpixel.a = oldpixel.a>>(8 - aBpp); // A bits (not used on dithering) + + // NOTE: Error must be computed between new and old pixel but using same number of bits! + // We want to know how much color precision we have lost... + error_r = (int)oldpixel.r - (int)(newpixel.r<<(8 - rBpp)); + error_g = (int)oldpixel.g - (int)(newpixel.g<<(8 - gBpp)); + error_b = (int)oldpixel.b - (int)(newpixel.b<<(8 - bBpp)); + + pixels[y*image->width + x] = newpixel; + + // NOTE: Some cases are out of the array and should be ignored + if (x < (image->width - 1)) + { + pixels[y*image->width + x+1].r = MIN((int)pixels[y*image->width + x+1].r + (int)((float)error_r*7.0f/16), 0xff); + pixels[y*image->width + x+1].g = MIN((int)pixels[y*image->width + x+1].g + (int)((float)error_g*7.0f/16), 0xff); + pixels[y*image->width + x+1].b = MIN((int)pixels[y*image->width + x+1].b + (int)((float)error_b*7.0f/16), 0xff); + } + + if ((x > 0) && (y < (image->height - 1))) + { + pixels[(y+1)*image->width + x-1].r = MIN((int)pixels[(y+1)*image->width + x-1].r + (int)((float)error_r*3.0f/16), 0xff); + pixels[(y+1)*image->width + x-1].g = MIN((int)pixels[(y+1)*image->width + x-1].g + (int)((float)error_g*3.0f/16), 0xff); + pixels[(y+1)*image->width + x-1].b = MIN((int)pixels[(y+1)*image->width + x-1].b + (int)((float)error_b*3.0f/16), 0xff); + } + + if (y < (image->height - 1)) + { + pixels[(y+1)*image->width + x].r = MIN((int)pixels[(y+1)*image->width + x].r + (int)((float)error_r*5.0f/16), 0xff); + pixels[(y+1)*image->width + x].g = MIN((int)pixels[(y+1)*image->width + x].g + (int)((float)error_g*5.0f/16), 0xff); + pixels[(y+1)*image->width + x].b = MIN((int)pixels[(y+1)*image->width + x].b + (int)((float)error_b*5.0f/16), 0xff); + } + + if ((x < (image->width - 1)) && (y < (image->height - 1))) + { + pixels[(y+1)*image->width + x+1].r = MIN((int)pixels[(y+1)*image->width + x+1].r + (int)((float)error_r*1.0f/16), 0xff); + pixels[(y+1)*image->width + x+1].g = MIN((int)pixels[(y+1)*image->width + x+1].g + (int)((float)error_g*1.0f/16), 0xff); + pixels[(y+1)*image->width + x+1].b = MIN((int)pixels[(y+1)*image->width + x+1].b + (int)((float)error_b*1.0f/16), 0xff); + } + + pixel_r = (unsigned short)newpixel.r; + pixel_g = (unsigned short)newpixel.g; + pixel_b = (unsigned short)newpixel.b; + pixel_a = (unsigned short)newpixel.a; + + ((unsigned short *)image->data)[y*image->width + x] = (pixel_r<<(gBpp + bBpp + aBpp)) | (pixel_g<<(bBpp + aBpp)) | (pixel_b< - + diff --git a/src_android/jni/Android.mk b/src_android/jni/Android.mk index bd40d2aa4..f9c20e661 100644 --- a/src_android/jni/Android.mk +++ b/src_android/jni/Android.mk @@ -43,11 +43,11 @@ LOCAL_SRC_FILES :=\ ../../src/textures.c \ ../../src/text.c \ ../../src/shapes.c \ + ../../src/gestures.c \ ../../src/models.c \ ../../src/utils.c \ ../../src/audio.c \ ../../src/stb_vorbis.c \ - ../../src/gestures.c \ # Required includes paths (.h) LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/include $(LOCAL_PATH)/../../src diff --git a/templates/advance_game/makefile b/templates/advance_game/makefile index 80e9357c4..b6dfc5342 100644 --- a/templates/advance_game/makefile +++ b/templates/advance_game/makefile @@ -83,7 +83,7 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads else - INCLUDES = -I. -I../../src + INCLUDES = -I. -I../../src -IC:/raylib/raylib/src # external libraries headers # GLFW3 INCLUDES += -I../../external/glfw3/include @@ -97,7 +97,7 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) LFLAGS = -L. -L../../src -L/opt/vc/lib else - LFLAGS = -L. -L../../src + LFLAGS = -L. -L../../src -LC:/raylib/raylib/src # external libraries to link with # GLFW3 LFLAGS += -L../../external/glfw3/lib/$(LIBPATH) @@ -115,8 +115,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),LINUX) # libraries for Debian GNU/Linux desktop compiling # requires the following packages: - # libopenal-dev libglew-dev libegl1-mesa-dev - LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -pthread + # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev + LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread + # on XWindow could require also below libraries, just uncomment + #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor else ifeq ($(PLATFORM_OS),OSX) # libraries for OS X 10.9 desktop compiling @@ -136,14 +138,15 @@ ifeq ($(PLATFORM),PLATFORM_RPI) LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal endif ifeq ($(PLATFORM),PLATFORM_WEB) - LIBS = ../../src/libraylib.bc + # just adjust the correct path to libraylib.bc + LIBS = C:/raylib/raylib/src/libraylib.bc endif # define additional parameters and flags for windows ifeq ($(PLATFORM_OS),WINDOWS) # resources file contains windows exe icon # -Wl,--subsystem,windows hides the console window - WINFLAGS = ../../src/resources -Wl,--subsystem,windows + WINFLAGS = C:/raylib/raylib/src/resources -Wl,--subsystem,windows endif ifeq ($(PLATFORM),PLATFORM_WEB) diff --git a/templates/android_project/AndroidManifest.xml b/templates/android_project/AndroidManifest.xml index 8bb0534fb..f9f41b335 100644 --- a/templates/android_project/AndroidManifest.xml +++ b/templates/android_project/AndroidManifest.xml @@ -23,7 +23,7 @@ android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen" > diff --git a/templates/android_project/assets/ambient.ogg b/templates/android_project/assets/ambient.ogg new file mode 100644 index 000000000..af7f836ed Binary files /dev/null and b/templates/android_project/assets/ambient.ogg differ diff --git a/templates/android_project/jni/basic_game.c b/templates/android_project/jni/basic_game.c index 987599a8a..8a0413c3f 100644 --- a/templates/android_project/jni/basic_game.c +++ b/templates/android_project/jni/basic_game.c @@ -30,7 +30,7 @@ void android_main(struct android_app *app) const int screenHeight = 450; GameScreen currentScreen = LOGO; - + InitWindow(screenWidth, screenHeight, app); // TODO: Initialize all required variables and load all required data here! @@ -43,7 +43,9 @@ void android_main(struct android_app *app) int framesCounter = 0; // Used to count frames - //SetTargetFPS(60); // Not required on Android, already locked to 60 fps + PlayMusicStream("ambient.ogg"); + + SetTargetFPS(60); // Not required on Android, already locked to 60 fps //-------------------------------------------------------------------------------------- // Main game loop @@ -51,6 +53,8 @@ void android_main(struct android_app *app) { // Update //---------------------------------------------------------------------------------- + UpdateMusicStream(); + switch(currentScreen) { case LOGO: @@ -70,7 +74,7 @@ void android_main(struct android_app *app) // TODO: Update TITLE screen variables here! // Press enter to change to GAMEPLAY screen - if (IsScreenTouched()) + if (GetGestureType() == GESTURE_TAP) { PlaySound(fx); currentScreen = GAMEPLAY; @@ -81,8 +85,8 @@ void android_main(struct android_app *app) // TODO: Update GAMEPLAY screen variables here! // Press enter to change to ENDING screen - if (IsScreenTouched()) - { + if (GetGestureType() == GESTURE_TAP) + { PlaySound(fx); currentScreen = ENDING; } @@ -92,7 +96,7 @@ void android_main(struct android_app *app) // TODO: Update ENDING screen variables here! // Press enter to return to TITLE screen - if (IsScreenTouched()) + if (GetGestureType() == GESTURE_TAP) { PlaySound(fx); currentScreen = TITLE; diff --git a/templates/android_project/jni/include/raylib.h b/templates/android_project/jni/include/raylib.h index b14ae082e..72211b59e 100644 --- a/templates/android_project/jni/include/raylib.h +++ b/templates/android_project/jni/include/raylib.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib 1.3.0 (www.raylib.com) +* raylib 1.4.0 (www.raylib.com) * * A simple and easy-to-use library to learn videogames programming * @@ -70,7 +70,7 @@ #endif #if defined(PLATFORM_ANDROID) - #include // Defines android_app struct + typedef struct android_app; // Define android_app struct (android_native_app_glue.h) #endif //---------------------------------------------------------------------------------- @@ -117,10 +117,53 @@ #define KEY_RIGHT_CONTROL 345 #define KEY_RIGHT_ALT 346 +// Keyboard Alhpa Numeric Keys +#define KEY_ZERO 48 +#define KEY_ONE 49 +#define KEY_TWO 50 +#define KEY_THREE 51 +#define KEY_FOUR 52 +#define KEY_FIVE 53 +#define KEY_SIX 54 +#define KEY_SEVEN 55 +#define KEY_EIGHT 56 +#define KEY_NINE 57 +#define KEY_A 65 +#define KEY_B 66 +#define KEY_C 67 +#define KEY_D 68 +#define KEY_E 69 +#define KEY_F 70 +#define KEY_G 71 +#define KEY_H 72 +#define KEY_I 73 +#define KEY_J 74 +#define KEY_K 75 +#define KEY_L 76 +#define KEY_M 77 +#define KEY_N 78 +#define KEY_O 79 +#define KEY_P 80 +#define KEY_Q 81 +#define KEY_R 82 +#define KEY_S 83 +#define KEY_T 84 +#define KEY_U 85 +#define KEY_V 86 +#define KEY_W 87 +#define KEY_X 88 +#define KEY_Y 89 +#define KEY_Z 90 + // Mouse Buttons #define MOUSE_LEFT_BUTTON 0 -#define MOUSE_RIGHT_BUTTON 1 -#define MOUSE_MIDDLE_BUTTON 2 +#if defined(PLATFORM_WEB) + #define MOUSE_RIGHT_BUTTON 2 + #define MOUSE_MIDDLE_BUTTON 1 +#else + #define MOUSE_RIGHT_BUTTON 1 + #define MOUSE_MIDDLE_BUTTON 2 +#endif // Gamepad Number #define GAMEPAD_PLAYER1 0 @@ -143,6 +186,12 @@ // TODO: Review Xbox360 USB Controller Buttons +// Android Physic Buttons +#define ANDROID_BACK 4 +#define ANDROID_MENU 82 +#define ANDROID_VOLUME_UP 24 +#define ANDROID_VOLUME_DOWN 25 + // Some Basic Colors // NOTE: Custom raylib color palette for amazing visuals on WHITE background #define LIGHTGRAY (Color){ 200, 200, 200, 255 } // Light Gray @@ -248,6 +297,8 @@ typedef struct SpriteFont { int numChars; // Number of characters int *charValues; // Characters values array Rectangle *charRecs; // Characters rectangles within the texture + Vector2 *charOffsets; // Characters offsets (on drawing) + int *charAdvanceX; // Characters x advance (on drawing) } SpriteFont; // Camera type, defines a camera position/orientation in 3d space @@ -286,7 +337,9 @@ typedef struct Shader { // Uniforms int projectionLoc; // Projection matrix uniform location point (vertex shader) - int modelviewLoc; // ModeView matrix uniform location point (vertex shader) + int modelviewLoc; // ModelView matrix uniform location point (vertex shader) + int modelLoc; // Model transformation matrix uniform location point (vertex shader) + int viewLoc; // View transformation matrix uniform location point (vertex shader) int tintColorLoc; // Color uniform location point (fragment shader) int mapDiffuseLoc; // Diffuse map texture uniform location point (fragment shader) @@ -323,6 +376,26 @@ typedef struct Wave { short channels; } Wave; +// Light type +typedef struct Light { + float position[3]; + float rotation[3]; + float intensity[1]; + float ambientColor[3]; + float diffuseColor[3]; + float specularColor[3]; + float specularIntensity[1]; +} Light; + +// Material type +typedef struct Material { + float ambientColor[3]; + float diffuseColor[3]; + float specularColor[3]; + float glossiness[1]; + float normalDepth[1]; +} Material; + // Texture formats // NOTE: Support depends on OpenGL version and platform typedef enum { @@ -365,9 +438,58 @@ typedef enum { GESTURE_PINCH_OUT = 1024 } Gestures; +typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction; + +// Gesture events +// NOTE: MAX_TOUCH_POINTS fixed to 4 +typedef struct { + int touchAction; + int pointCount; + int pointerId[4]; + Vector2 position[4]; +} GestureEvent; + // Camera system modes typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode; +// Collider types +typedef enum { RectangleCollider, CircleCollider } ColliderType; + +// Physics struct +typedef struct Physics { + bool enabled; + bool debug; // Should be used by programmer for testing purposes + Vector2 gravity; +} Physics; + +// Transform struct +typedef struct Transform { + Vector2 position; + float rotation; + Vector2 scale; +} Transform; + +// Rigidbody struct +typedef struct Rigidbody { + bool enabled; + float mass; + Vector2 acceleration; + Vector2 velocity; + bool isGrounded; + bool isContact; // Avoid freeze player when touching floor + bool applyGravity; + float friction; // 0.0f to 1.0f + float bounciness; // 0.0f to 1.0f +} Rigidbody; + +// Collider struct +typedef struct Collider { + bool enabled; + ColliderType type; + Rectangle bounds; // Just used for RectangleCollider type + int radius; // Just used for CircleCollider type +} Collider; + #ifdef __cplusplus extern "C" { // Prevents name mangling of functions #endif @@ -399,6 +521,7 @@ int GetScreenHeight(void); // Get current scree void ClearBackground(Color color); // Sets Background Color void BeginDrawing(void); // Setup drawing canvas to start drawing +void BeginDrawingEx(int blendMode, Shader shader, Matrix transform); // Setup drawing canvas with extended parameters void EndDrawing(void); // End canvas drawing and Swap Buffers (Double Buffering) void Begin3dMode(Camera cam); // Initializes 3D mode for drawing (Camera setup) @@ -423,6 +546,9 @@ bool IsFileDropped(void); // Check if a file h char **GetDroppedFiles(int *count); // Retrieve dropped files into window void ClearDroppedFiles(void); // Clear dropped files paths buffer +void StorageSaveValue(int position, int value); // Storage save integer value (to defined position) +int StorageLoadValue(int position); // Storage load integer value (from defined position) + //------------------------------------------------------------------------------------ // Input Handling Functions (Module: core) //------------------------------------------------------------------------------------ @@ -458,22 +584,21 @@ bool IsGamepadButtonUp(int gamepad, int button); // Detect if a gamepad b #endif #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) -//------------------------------------------------------------------------------------ -// Gestures and Touch Handling Functions (Module: gestures) -//------------------------------------------------------------------------------------ int GetTouchX(void); // Returns touch position X (relative to screen size) int GetTouchY(void); // Returns touch position Y (relative to screen size) Vector2 GetTouchPosition(void); // Returns touch position XY (relative to screen size) +bool IsButtonPressed(int button); // Detect if an android physic button has been pressed +bool IsButtonDown(int button); // Detect if an android physic button is being pressed +bool IsButtonReleased(int button); // Detect if an android physic button has been released -#if defined(PLATFORM_WEB) -void InitGesturesSystem(void); // Init gestures system (web) -#elif defined(PLATFORM_ANDROID) -void InitGesturesSystem(struct android_app *app); // Init gestures system (android) -#endif +//------------------------------------------------------------------------------------ +// Gestures and Touch Handling Functions (Module: gestures) +//------------------------------------------------------------------------------------ void UpdateGestures(void); // Update gestures detected (must be called every frame) bool IsGestureDetected(void); // Check if a gesture have been detected int GetGestureType(void); // Get latest detected gesture void SetGesturesEnabled(unsigned int gestureFlags); // Enable a set of gestures using flags +void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into gestures float GetGestureDragIntensity(void); // Get gesture drag intensity float GetGestureDragAngle(void); // Get gesture drag angle @@ -540,16 +665,31 @@ Image LoadImageEx(Color *pixels, int width, int height); Image LoadImageRaw(const char *fileName, int width, int height, int format, int headerSize); // Load image data from RAW file Image LoadImageFromRES(const char *rresName, int resId); // Load an image from rRES file (raylib Resource) Texture2D LoadTexture(const char *fileName); // Load an image as texture into GPU memory -Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat, int mipmapCount); // Load a texture from raw data into GPU memory +Texture2D LoadTextureEx(void *data, int width, int height, int textureFormat); // Load a texture from raw data into GPU memory Texture2D LoadTextureFromRES(const char *rresName, int resId); // Load an image as texture from rRES file (raylib Resource) Texture2D LoadTextureFromImage(Image image); // Load a texture from image data void UnloadImage(Image image); // Unload image from CPU memory (RAM) void UnloadTexture(Texture2D texture); // Unload texture from GPU memory Color *GetImageData(Image image); // Get pixel data from image as a Color struct array Image GetTextureData(Texture2D texture); // Get pixel data from GPU texture and return an Image -void ImageConvertToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two) -void ImageConvertFormat(Image *image, int newFormat); // Convert image data to desired format +void ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two) +void ImageFormat(Image *image, int newFormat); // Convert image data to desired format +void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp); // Dither image data to 16bpp or lower (Floyd-Steinberg dithering) +Image ImageCopy(Image image); // Create an image duplicate (useful for transformations) +void ImageCrop(Image *image, Rectangle crop); // Crop an image to a defined rectangle +void ImageResize(Image *image, int newWidth, int newHeight); // Resize and image (bilinear filtering) +void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec); // Draw a source image within a destination image +Image ImageText(const char *text, int fontSize, Color color); // Create an image from text (default font) +Image ImageTextEx(SpriteFont font, const char *text, int fontSize, int spacing, Color tint); // Create an image from text (custom sprite font) +void ImageFlipVertical(Image *image); // Flip image vertically +void ImageFlipHorizontal(Image *image); // Flip image horizontally +void ImageColorTint(Image *image, Color color); // Modify image color: tint +void ImageColorInvert(Image *image); // Modify image color: invert +void ImageColorGrayscale(Image *image); // Modify bimage color: grayscale +void ImageColorContrast(Image *image, float contrast); // Modify image color: contrast (-100 to 100) +void ImageColorBrightness(Image *image, int brightness); // Modify image color: brightness (-255 to 255) void GenTextureMipmaps(Texture2D texture); // Generate GPU mipmaps for a texture +void UpdateTexture(Texture2D texture, void *pixels); // Update GPU texture with new data void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2 @@ -573,6 +713,7 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int void DrawFPS(int posX, int posY); // Shows current FPS on top-left corner const char *FormatText(const char *text, ...); // Formatting of text with variables to 'embed' +const char *SubText(const char *text, int position, int length); // Get a piece of a text string //------------------------------------------------------------------------------------ // Basic 3d Shapes Drawing Functions (Module: models) @@ -607,6 +748,7 @@ void SetModelTexture(Model *model, Texture2D texture); void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) void DrawModelEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint); // Draw a model with extended parameters void DrawModelWires(Model model, Vector3 position, float scale, Color color); // Draw a model wires (with texture if set) +void DrawModelWiresEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vector3 center, float size, Color tint); // Draw a billboard texture defined by sourceRec @@ -640,6 +782,47 @@ void SetShaderMap(Shader *shader, int mapLocation, Texture2D texture, int textur void SetBlendMode(int mode); // Set blending mode (alpha, additive, multiplied) +//---------------------------------------------------------------------------------- +// Lighting System Functions (engine-module: lighting) +// NOTE: light and material structs uses float pointers instead of vectors to be compatible with SetShaderValue() +//---------------------------------------------------------------------------------- +// Lights functions +void SetLightPosition(Light *light, Vector3 position); // Set light position converting position vector to float pointer +void SetLightRotation(Light *light, Vector3 rotation); // Set light rotation converting rotation vector to float pointer +void SetLightIntensity(Light *light, float intensity); // Set light intensity value +void SetLightAmbientColor(Light *light, Vector3 color); // Set light ambient color value (it will be multiplied by material ambient color) +void SetLightDiffuseColor(Light *light, Vector3 color); // Set light diffuse color (light color) +void SetLightSpecularColor(Light *light, Vector3 color); // Set light specular color (it will be multiplied by material specular color) +void SetLightSpecIntensity(Light *light, float specIntensity); // Set light specular intensity (specular color scalar multiplier) + +// Materials functions +void SetMaterialAmbientColor(Material *material, Vector3 color); // Set material ambient color value (it will be multiplied by light ambient color) +void SetMaterialDiffuseColor(Material *material, Vector3 color); // Set material diffuse color (material color, should use DrawModel() tint parameter) +void SetMaterialSpecularColor(Material *material, Vector3 color); // Set material specular color (it will be multiplied by light specular color) +void SetMaterialGlossiness(Material *material, float glossiness); // Set material glossiness value (recommended values: 0 - 100) +void SetMaterialNormalDepth(Material *material, float depth); // Set normal map depth (B component from RGB type map scalar multiplier) + +//---------------------------------------------------------------------------------- +// Physics System Functions (engine-module: physics) +//---------------------------------------------------------------------------------- +void InitPhysics(void); // Initialize all internal physics values +void SetPhysics(Physics settings); // Set physics settings values using Physics data type to overwrite internal physics settings + +void AddRigidbody(int index, Rigidbody rigidbody); // Initialize a new rigidbody with parameters to internal index slot +void AddCollider(int index, Collider collider); // Initialize a new Collider with parameters to internal index slot + +void ApplyPhysics(int index, Vector2 *position); // Apply physics to internal rigidbody, physics calculations are applied to position pointer parameter +void SetRigidbodyEnabled(int index, bool state); // Set enabled state to a defined rigidbody +void SetRigidbodyVelocity(int index, Vector2 velocity); // Set velocity of rigidbody (without considering of mass value) +void SetRigidbodyAcceleration(int index, Vector2 acceleration); // Set acceleration of rigidbody (without considering of mass value) +void AddRigidbodyForce(int index, Vector2 force); // Set rigidbody force (considering mass value) +void AddForceAtPosition(Vector2 position, float intensity, float radius); // Add a force to all enabled rigidbodies at a position + +void SetColliderEnabled(int index, bool state); // Set enabled state to a defined collider + +Rigidbody GetRigidbody(int index); // Returns the internal rigidbody data defined by index parameter +Collider GetCollider(int index); // Returns the internal collider data defined by index parameter + //------------------------------------------------------------------------------------ // Audio Loading and Playing Functions (Module: audio) //------------------------------------------------------------------------------------ diff --git a/templates/android_project/jni/libs/libraylib.a b/templates/android_project/jni/libs/libraylib.a index 3e8cce7df..14e10ab79 100644 Binary files a/templates/android_project/jni/libs/libraylib.a and b/templates/android_project/jni/libs/libraylib.a differ diff --git a/templates/basic_game/makefile b/templates/basic_game/makefile index 5ce3aa3e9..9a52c4eb6 100644 --- a/templates/basic_game/makefile +++ b/templates/basic_game/makefile @@ -83,7 +83,7 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads else - INCLUDES = -I. -I../../src + INCLUDES = -I. -I../../src -IC:/raylib/raylib/src # external libraries headers # GLFW3 INCLUDES += -I../../external/glfw3/include @@ -97,14 +97,14 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) LFLAGS = -L. -L../../src -L/opt/vc/lib else - LFLAGS = -L. -L../../src + LFLAGS = -L. -L../../src -LC:/raylib/raylib/src # external libraries to link with # GLFW3 LFLAGS += -L../../external/glfw3/lib/$(LIBPATH) ifneq ($(PLATFORM_OS),OSX) # OpenAL Soft LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH) - # GLEW + # GLEW LFLAGS += -L../../external/glew/lib/$(LIBPATH) endif endif @@ -115,8 +115,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),LINUX) # libraries for Debian GNU/Linux desktop compiling # requires the following packages: - # libopenal-dev libglew-dev libegl1-mesa-dev - LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -pthread + # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev + LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread + # on XWindow could require also below libraries, just uncomment + #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor else ifeq ($(PLATFORM_OS),OSX) # libraries for OS X 10.9 desktop compiling @@ -136,14 +138,15 @@ ifeq ($(PLATFORM),PLATFORM_RPI) LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal endif ifeq ($(PLATFORM),PLATFORM_WEB) - LIBS = ../../src/libraylib.bc + # just adjust the correct path to libraylib.bc + LIBS = C:/raylib/raylib/src/libraylib.bc endif # define additional parameters and flags for windows ifeq ($(PLATFORM_OS),WINDOWS) # resources file contains windows exe icon # -Wl,--subsystem,windows hides the console window - WINFLAGS = ../../src/resources -Wl,--subsystem,windows + WINFLAGS = C:/raylib/raylib/src/resources -Wl,--subsystem,windows endif ifeq ($(PLATFORM),PLATFORM_WEB) diff --git a/templates/basic_test/makefile b/templates/basic_test/makefile index cf763628a..a0ed2608f 100644 --- a/templates/basic_test/makefile +++ b/templates/basic_test/makefile @@ -83,7 +83,7 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads else - INCLUDES = -I. -I../../src + INCLUDES = -I. -I../../src -IC:/raylib/raylib/src # external libraries headers # GLFW3 INCLUDES += -I../../external/glfw3/include @@ -97,14 +97,14 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) LFLAGS = -L. -L../../src -L/opt/vc/lib else - LFLAGS = -L. -L../../src + LFLAGS = -L. -L../../src -LC:/raylib/raylib/src # external libraries to link with # GLFW3 LFLAGS += -L../../external/glfw3/lib/$(LIBPATH) ifneq ($(PLATFORM_OS),OSX) # OpenAL Soft LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH) - # GLEW + # GLEW LFLAGS += -L../../external/glew/lib/$(LIBPATH) endif endif @@ -115,11 +115,13 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),LINUX) # libraries for Debian GNU/Linux desktop compiling # requires the following packages: - # libopenal-dev libglew-dev libegl1-mesa-dev - LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -pthread + # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev + LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread + # on XWindow could require also below libraries, just uncomment + #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor else ifeq ($(PLATFORM_OS),OSX) - # libraries for OS X 10.9 desktop compiling + # libraries for OS X 10.9 desktop compiling # requires the following packages: # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev LIBS = -lraylib -lglfw -framework OpenGL -framework OpenAl -framework Cocoa @@ -136,14 +138,15 @@ ifeq ($(PLATFORM),PLATFORM_RPI) LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal endif ifeq ($(PLATFORM),PLATFORM_WEB) - LIBS = ../../src/libraylib.bc + # just adjust the correct path to libraylib.bc + LIBS = C:/raylib/raylib/src/libraylib.bc endif # define additional parameters and flags for windows ifeq ($(PLATFORM_OS),WINDOWS) # resources file contains windows exe icon # -Wl,--subsystem,windows hides the console window - WINFLAGS = ../../src/resources -Wl,--subsystem,windows + WINFLAGS = C:/raylib/raylib/src/resources -Wl,--subsystem,windows endif ifeq ($(PLATFORM),PLATFORM_WEB) diff --git a/templates/simple_game/makefile b/templates/simple_game/makefile index 586233a7e..30216e5dd 100644 --- a/templates/simple_game/makefile +++ b/templates/simple_game/makefile @@ -83,7 +83,7 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads else - INCLUDES = -I. -I../../src + INCLUDES = -I. -I../../src -IC:/raylib/raylib/src # external libraries headers # GLFW3 INCLUDES += -I../../external/glfw3/include @@ -97,14 +97,14 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) LFLAGS = -L. -L../../src -L/opt/vc/lib else - LFLAGS = -L. -L../../src + LFLAGS = -L. -L../../src -LC:/raylib/raylib/src # external libraries to link with # GLFW3 LFLAGS += -L../../external/glfw3/lib/$(LIBPATH) ifneq ($(PLATFORM_OS),OSX) # OpenAL Soft LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH) - # GLEW + # GLEW LFLAGS += -L../../external/glew/lib/$(LIBPATH) endif endif @@ -115,8 +115,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),LINUX) # libraries for Debian GNU/Linux desktop compiling # requires the following packages: - # libopenal-dev libglew-dev libegl1-mesa-dev - LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -pthread + # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev + LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread + # on XWindow could require also below libraries, just uncomment + #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor else ifeq ($(PLATFORM_OS),OSX) # libraries for OS X 10.9 desktop compiling @@ -136,14 +138,15 @@ ifeq ($(PLATFORM),PLATFORM_RPI) LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal endif ifeq ($(PLATFORM),PLATFORM_WEB) - LIBS = ../../src/libraylib.bc + # just adjust the correct path to libraylib.bc + LIBS = C:/raylib/raylib/src/libraylib.bc endif # define additional parameters and flags for windows ifeq ($(PLATFORM_OS),WINDOWS) # resources file contains windows exe icon # -Wl,--subsystem,windows hides the console window - WINFLAGS = ../../src/resources -Wl,--subsystem,windows + WINFLAGS = C:/raylib/raylib/src/resources -Wl,--subsystem,windows endif ifeq ($(PLATFORM),PLATFORM_WEB) diff --git a/templates/standard_game/makefile b/templates/standard_game/makefile index cdb42f537..ec847b0e4 100644 --- a/templates/standard_game/makefile +++ b/templates/standard_game/makefile @@ -83,7 +83,7 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) INCLUDES = -I. -I../../src -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads else - INCLUDES = -I. -I../../src + INCLUDES = -I. -I../../src -IC:/raylib/raylib/src # external libraries headers # GLFW3 INCLUDES += -I../../external/glfw3/include @@ -97,14 +97,14 @@ endif ifeq ($(PLATFORM),PLATFORM_RPI) LFLAGS = -L. -L../../src -L/opt/vc/lib else - LFLAGS = -L. -L../../src + LFLAGS = -L. -L../../src -LC:/raylib/raylib/src # external libraries to link with # GLFW3 LFLAGS += -L../../external/glfw3/lib/$(LIBPATH) ifneq ($(PLATFORM_OS),OSX) # OpenAL Soft LFLAGS += -L../../external/openal_soft/lib/$(LIBPATH) - # GLEW + # GLEW LFLAGS += -L../../external/glew/lib/$(LIBPATH) endif endif @@ -115,8 +115,10 @@ ifeq ($(PLATFORM),PLATFORM_DESKTOP) ifeq ($(PLATFORM_OS),LINUX) # libraries for Debian GNU/Linux desktop compiling # requires the following packages: - # libopenal-dev libglew-dev libegl1-mesa-dev - LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor -lm -pthread + # libglfw3-dev libopenal-dev libglew-dev libegl1-mesa-dev + LIBS = -lraylib -lglfw3 -lGLEW -lGL -lopenal -lm -pthread + # on XWindow could require also below libraries, just uncomment + #LIBS += -lX11 -lXrandr -lXinerama -lXi -lXxf86vm -lXcursor else ifeq ($(PLATFORM_OS),OSX) # libraries for OS X 10.9 desktop compiling @@ -136,14 +138,15 @@ ifeq ($(PLATFORM),PLATFORM_RPI) LIBS = -lraylib -lGLESv2 -lEGL -lpthread -lrt -lm -lbcm_host -lopenal endif ifeq ($(PLATFORM),PLATFORM_WEB) - LIBS = ../../src/libraylib.bc + # just adjust the correct path to libraylib.bc + LIBS = C:/raylib/raylib/src/libraylib.bc endif # define additional parameters and flags for windows ifeq ($(PLATFORM_OS),WINDOWS) # resources file contains windows exe icon # -Wl,--subsystem,windows hides the console window - WINFLAGS = ../../src/resources -Wl,--subsystem,windows + WINFLAGS = C:/raylib/raylib/src/resources -Wl,--subsystem,windows endif ifeq ($(PLATFORM),PLATFORM_WEB)