From 9bf411f5805e246c790beb0556a6912f6ca33452 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Tue, 6 Oct 2015 17:30:03 +0200 Subject: Added a bunch of image manipulation functions: Renamed functions (for coherence with new ones): - ImageConvertToPOT() -> ImageToPOT() - ImageConvertFormat() -> ImageFormat() New functions added (IN PROGRESS): - ImageCopy() - ImageCrop() - ImageResize() (Uses stb_image_resize.h) - ImageDraw() - ImageDrawText() - ImageDrawTextEx() - ImageFlipVertical() - ImageFlipHorizontal() - ImageColorInvert() - ImageColorGrayscale() - ImageColorContrast() - ImageColorBrightness() --- src/raylib.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index b14ae082..74e6208f 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -547,8 +547,20 @@ void UnloadImage(Image image); 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 +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 +void ImageDrawText(Image *dst, const char *text, Vector2 position, int size, Color color); // Draw text within an image +void ImageDrawTextEx(Image *dst, SpriteFont font, const char *text, Vector2 position, int size, Color color); +void ImageFlipVertical(Image *image); +void ImageFlipHorizontal(Image *image); +void ImageColorInvert(Image *image); +void ImageColorGrayscale(Image *image); +void ImageColorContrast(Image *image, float contrast); +void ImageColorBrightness(Image *image, int brightness); void GenTextureMipmaps(Texture2D texture); // Generate GPU mipmaps for a texture void DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D -- cgit v1.2.3 From afdf357fbee7f01535bddefb4e62cb1308ed55b5 Mon Sep 17 00:00:00 2001 From: Ray Date: Sun, 25 Oct 2015 01:50:15 +0200 Subject: Added some image manipulation functions Added (or completed functions): Image ImageText(const char *text, int fontSize, Color color); Image ImageTextEx(SpriteFont font, const char *text, int fontSize, int spacing, Color tint); void ImageFlipVertical(Image *image); void ImageFlipHorizontal(Image *image); void ImageColorTint(Image *image, Color color); void ImageColorInvert(Image *image); void ImageColorGrayscale(Image *image); void ImageColorContrast(Image *image, float contrast); void ImageColorBrightness(Image *image, int brightness); --- src/raylib.h | 21 ++--- src/text.c | 4 +- src/textures.c | 261 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 232 insertions(+), 54 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 74e6208f..9067c77d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -547,20 +547,21 @@ void UnloadImage(Image image); 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 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 ImageToPOT(Image *image, Color fillColor); // Convert image to POT (power-of-two) +void ImageFormat(Image *image, int newFormat); // Convert image data to desired format 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 -void ImageDrawText(Image *dst, const char *text, Vector2 position, int size, Color color); // Draw text within an image -void ImageDrawTextEx(Image *dst, SpriteFont font, const char *text, Vector2 position, int size, Color color); -void ImageFlipVertical(Image *image); -void ImageFlipHorizontal(Image *image); -void ImageColorInvert(Image *image); -void ImageColorGrayscale(Image *image); -void ImageColorContrast(Image *image, float contrast); -void ImageColorBrightness(Image *image, int brightness); +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 DrawTexture(Texture2D texture, int posX, int posY, Color tint); // Draw a Texture2D diff --git a/src/text.c b/src/text.c index 381aa052..5e947187 100644 --- a/src/text.c +++ b/src/text.c @@ -279,9 +279,7 @@ void DrawText(const char *text, int posX, int posY, int fontSize, Color color) Vector2 position = { (float)posX, (float)posY }; int defaultFontSize = 10; // Default Font chars height in pixel - if (fontSize < defaultFontSize) fontSize = defaultFontSize; - int spacing = fontSize / defaultFontSize; DrawTextEx(defaultFont, text, position, fontSize, spacing, color); @@ -380,7 +378,7 @@ Vector2 MeasureTextEx(SpriteFont spriteFont, const char *text, int fontSize, int for (int i = 0; i < len; i++) { - textWidth += spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR].width; + if (text[i] != '\n') textWidth += spriteFont.charRecs[(int)text[i] - FONT_FIRST_CHAR].width; } if (fontSize <= spriteFont.charRecs[0].height) scaleFactor = 1.0f; diff --git a/src/textures.c b/src/textures.c index 6307702f..66d2afc5 100644 --- a/src/textures.c +++ b/src/textures.c @@ -806,12 +806,9 @@ void ImageResize(Image *image, int newWidth, int newHeight) UnloadImage(*image); *image = LoadImageEx(output, newWidth, newHeight); - - free(output); - - // Reformat 32bit RGBA image to original format - ImageFormat(image, format); + ImageFormat(image, format); // Reformat 32bit RGBA image to original format + free(output); free(pixels); } @@ -877,104 +874,286 @@ void ImageDraw(Image *dst, Image src, Rectangle srcRec, Rectangle dstRec) } } - free(srcPixels); - - int format = dst->format; - - UnloadImage(*dst); + UnloadImage(*dst); // NOTE: Only dst->data is unloaded *dst = LoadImageEx(dstPixels, dst->width, dst->height); + ImageFormat(dst, dst->format); + free(srcPixels); free(dstPixels); - - ImageFormat(dst, format); } -// Draw a text within an image (destination) -// NOTE: Default font is used -void ImageDrawText(Image *dst, const char *text, Vector2 position, int size, Color color) +// Create an image from text (default font) +Image ImageText(const char *text, int fontSize, Color color) { - ImageDrawTextEx(dst, GetDefaultFont(), text, position, size, color); + int defaultFontSize = 10; // Default Font chars height in pixel + if (fontSize < defaultFontSize) fontSize = defaultFontSize; + int spacing = fontSize / defaultFontSize; + + Image imText = ImageTextEx(GetDefaultFont(), text, fontSize, spacing, color); + + return imText; } -// Draw a text within an image (destination) -// NOTE: Defined SpriteFont is used -void ImageDrawTextEx(Image *dst, SpriteFont font, const char *text, Vector2 position, int size, Color color) +// Create an image from text (custom sprite font) +Image ImageTextEx(SpriteFont font, const char *text, int fontSize, int spacing, Color tint) { + int length = strlen(text); + int posX = 0; + + Vector2 imSize = MeasureTextEx(font, text, font.size, spacing); + + // NOTE: GetTextureData() not available in OpenGL ES Image imFont = GetTextureData(font.texture); - int posX = (int)position.x; + ImageFormat(&imFont, UNCOMPRESSED_R8G8B8A8); // Required for color tint + ImageColorTint(&imFont, tint); // Apply color tint to font + + Color *fontPixels = GetImageData(imFont); - Rectangle srcRec = { 0, 0, 0, font.size }; - Rectangle dstRec = { posX, (int)position.y, 0, font.size }; - int length = strlen(text); + // Create image to store text + Color *pixels = (Color *)malloc(sizeof(Color)*(int)imSize.x*(int)imSize.y); for (int i = 0; i < length; i++) { - srcRec.x = font.charRecs[(int)text[i] - 32].x; - srcRec.y = font.charRecs[(int)text[i] - 32].y; - srcRec.width = font.charRecs[(int)text[i] - 32].width; - dstRec.width = font.charRecs[(int)text[i] - 32].width; - - printf("[%c] Source Rectangle: %i, %i, %i, %i\n", text[i], srcRec.x, srcRec.y, srcRec.width, srcRec.height); - printf("[%c] Destination Rectangle: %i, %i, %i, %i\n\n", text[i], dstRec.x, dstRec.y, dstRec.width, dstRec.height); + Rectangle letterRec = font.charRecs[(int)text[i] - 32]; - ImageDraw(dst, imFont, srcRec, dstRec); + for (int y = letterRec.y; y < (letterRec.y + letterRec.height); y++) + { + for (int x = posX; x < (posX + letterRec.width); x++) + { + pixels[(y - letterRec.y)*(int)imSize.x + x] = fontPixels[y*font.texture.width + (x - posX + letterRec.x)]; + } + } - dstRec.x += srcRec.width; + posX += letterRec.width + spacing; } UnloadImage(imFont); + + Image imText = LoadImageEx(pixels, (int)imSize.x, (int)imSize.y); + + // Scale image depending on text size + if (fontSize > (int)imSize.y) + { + float scaleFactor = (float)fontSize/imSize.y; + TraceLog(INFO, "Scalefactor: %f", scaleFactor); + + // TODO: Allow nearest-neighbor scaling algorithm + ImageResize(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor)); + } + + free(pixels); + free(fontPixels); + + return imText; } +// Flip image vertically void ImageFlipVertical(Image *image) { - Image copy = ImageCopy(*image); - ImageFormat(©, UNCOMPRESSED_R8G8B8A8); - - Color *srcPixels = GetImageData(copy); // Get source image data as Color array - Color *dstPixels = GetImageData(copy); + Color *srcPixels = GetImageData(*image); + Color *dstPixels = (Color *)malloc(sizeof(Color)*image->width*image->height); for (int y = 0; y < image->height; y++) { for (int x = 0; x < image->width; x++) { - //dstPixels[y*image->width + x] = srcPixels[]; + dstPixels[y*image->width + x] = srcPixels[(image->height - 1 - y)*image->width + x]; } } + Image processed = LoadImageEx(dstPixels, image->width, image->height); + ImageFormat(&processed, image->format); + UnloadImage(*image); + free(srcPixels); free(dstPixels); - ImageFormat(©, image->format); + image->data = processed.data; +} + +// Flip image horizontally +void ImageFlipHorizontal(Image *image) +{ + Color *srcPixels = GetImageData(*image); + Color *dstPixels = (Color *)malloc(sizeof(Color)*image->width*image->height); + for (int y = 0; y < image->height; y++) + { + for (int x = 0; x < image->width; x++) + { + dstPixels[y*image->width + x] = srcPixels[y*image->width + (image->width - 1 - x)]; + } + } + + Image processed = LoadImageEx(dstPixels, image->width, image->height); + ImageFormat(&processed, image->format); UnloadImage(*image); - image = © + + free(srcPixels); + free(dstPixels); + + image->data = processed.data; } -void ImageFlipHorizontal(Image *image) +// Modify image color: tint +void ImageColorTint(Image *image, Color color) { + Color *pixels = GetImageData(*image); + + float cR = (float)color.r/255; + float cG = (float)color.g/255; + float cB = (float)color.b/255; + float cA = (float)color.a/255; + for (int y = 0; y < image->height; y++) + { + for (int x = 0; x < image->width; x++) + { + unsigned char r = 255*((float)pixels[y*image->width + x].r/255*cR); + unsigned char g = 255*((float)pixels[y*image->width + x].g/255*cG); + unsigned char b = 255*((float)pixels[y*image->width + x].b/255*cB); + unsigned char a = 255*((float)pixels[y*image->width + x].a/255*cA); + + pixels[y*image->width + x].r = r; + pixels[y*image->width + x].g = g; + pixels[y*image->width + x].b = b; + pixels[y*image->width + x].a = a; + } + } + + Image processed = LoadImageEx(pixels, image->width, image->height); + ImageFormat(&processed, image->format); + UnloadImage(*image); + free(pixels); + + TraceLog(INFO,"color tint applied"); + + image->data = processed.data; } +// Modify image color: invert void ImageColorInvert(Image *image) { + Color *pixels = GetImageData(*image); + for (int y = 0; y < image->height; y++) + { + for (int x = 0; x < image->width; x++) + { + pixels[y*image->width + x].r = 255 - pixels[y*image->width + x].r; + pixels[y*image->width + x].g = 255 - pixels[y*image->width + x].g; + pixels[y*image->width + x].b = 255 - pixels[y*image->width + x].b; + } + } + + Image processed = LoadImageEx(pixels, image->width, image->height); + ImageFormat(&processed, image->format); + UnloadImage(*image); + free(pixels); + + image->data = processed.data; } +// Modify image color: grayscale void ImageColorGrayscale(Image *image) { ImageFormat(image, UNCOMPRESSED_GRAYSCALE); } +// Modify image color: contrast +// NOTE: Contrast values between -100 and 100 void ImageColorContrast(Image *image, float contrast) { + if (contrast < -100) contrast = -100; + if (contrast > 100) contrast = 100; + + contrast = (100.0 + contrast)/100.0; + contrast *= contrast; + + Color *pixels = GetImageData(*image); + + for (int y = 0; y < image->height; y++) + { + for (int x = 0; x < image->width; x++) + { + float pR = (float)pixels[y*image->width + x].r/255.0; + pR -= 0.5; + pR *= contrast; + pR += 0.5; + pR *= 255; + if (pR < 0) pR = 0; + if (pR > 255) pR = 255; + + float pG = (float)pixels[y*image->width + x].g/255.0; + pG -= 0.5; + pG *= contrast; + pG += 0.5; + pG *= 255; + if (pG < 0) pG = 0; + if (pG > 255) pG = 255; + + float pB = (float)pixels[y*image->width + x].b/255.0; + pB -= 0.5; + pB *= contrast; + pB += 0.5; + pB *= 255; + if (pB < 0) pB = 0; + if (pB > 255) pB = 255; + + pixels[y*image->width + x].r = (unsigned char)pR; + pixels[y*image->width + x].g = (unsigned char)pG; + pixels[y*image->width + x].b = (unsigned char)pB; + } + } + + Image processed = LoadImageEx(pixels, image->width, image->height); + ImageFormat(&processed, image->format); + UnloadImage(*image); + free(pixels); + image->data = processed.data; } +// Modify image color: brightness +// NOTE: Brightness values between -255 and 255 void ImageColorBrightness(Image *image, int brightness) { + if (brightness < -255) brightness = -255; + if (brightness > 255) brightness = 255; + + Color *pixels = GetImageData(*image); + + for (int y = 0; y < image->height; y++) + { + for (int x = 0; x < image->width; x++) + { + int cR = pixels[y*image->width + x].r + brightness; + int cG = pixels[y*image->width + x].g + brightness; + int cB = pixels[y*image->width + x].b + brightness; + + if (cR < 0) cR = 1; + if (cR > 255) cR = 255; + + if (cG < 0) cG = 1; + if (cG > 255) cG = 255; + + if (cB < 0) cB = 1; + if (cB > 255) cB = 255; + + pixels[y*image->width + x].r = (unsigned char)cR; + pixels[y*image->width + x].g = (unsigned char)cG; + pixels[y*image->width + x].b = (unsigned char)cB; + } + } + + Image processed = LoadImageEx(pixels, image->width, image->height); + ImageFormat(&processed, image->format); + UnloadImage(*image); + free(pixels); + image->data = processed.data; } // Generate GPU mipmaps for a texture -- cgit v1.2.3 From 932396922db13b0c118a0b493d4e34b0f6db3b97 Mon Sep 17 00:00:00 2001 From: Joshua Reisenauer Date: Mon, 26 Oct 2015 00:21:52 -0700 Subject: Added Alpha Numeric Mapping For Develop Branch GLFW mappings. --- src/raylib.h | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 9067c77d..15642256 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -117,6 +117,44 @@ #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 -- cgit v1.2.3 From 580c0a72966b0dbc6eae26e8b01657e732ec266a Mon Sep 17 00:00:00 2001 From: Ray Date: Fri, 30 Oct 2015 11:30:32 +0100 Subject: Moved gestures touch functionality back to core Required gestures module when compiling for Android and Web --- src/core.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/gestures.c | 63 +++++++++------------------------------- src/raylib.h | 7 +++-- 3 files changed, 107 insertions(+), 55 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index 47bce873..b2d94506 100644 --- a/src/core.c +++ b/src/core.c @@ -95,6 +95,11 @@ #define DEFAULT_GAMEPAD_DEV "/dev/input/js0" #endif +#if defined(PLATFORM_WEB) + #include + #include +#endif + //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- @@ -158,6 +163,10 @@ static int renderOffsetY = 0; // Offset Y from render area (must b static bool fullscreen = false; // Fullscreen mode (useful only for PLATFORM_DESKTOP) static Matrix downscaleView; // Matrix to downscale view (in case screen size bigger than display size) +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) +static Vector2 touchPosition; // Touch position on screen +#endif + #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) static const char *windowTitle; // Window text title... @@ -247,6 +256,10 @@ static void TakeScreenshot(void); static void AndroidCommandCallback(struct android_app *app, int32_t cmd); // Process Android activity lifecycle commands #endif +#if defined(PLATFORM_WEB) +static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *e, void *userData); +#endif + //---------------------------------------------------------------------------------- // Module Functions Definition - Window and OpenGL Context Functions //---------------------------------------------------------------------------------- @@ -279,6 +292,12 @@ void InitWindow(int width, int height, const char *title) InitGamepad(); // Gamepad init #endif +#if defined(PLATFORM_WEB) + InitGesturesSystem(); + + emscripten_set_fullscreenchange_callback(0, 0, 1, EmscriptenFullscreenChangeCallback); +#endif + mousePosition.x = screenWidth/2; mousePosition.y = screenHeight/2; @@ -335,6 +354,8 @@ void InitWindow(int width, int height, struct android_app *state) //InitGesturesSystem(app); // NOTE: Must be called by user InitAssetManager(app->activity->assetManager); + + InitGesturesSystem(app); TraceLog(INFO, "Android app initialized successfully"); @@ -499,7 +520,7 @@ void EndDrawing(void) SwapBuffers(); // Copy back buffer to front buffer PollInputEvents(); // Poll user events - + currentTime = GetTime(); drawTime = currentTime - previousTime; previousTime = currentTime; @@ -814,7 +835,7 @@ Vector2 GetMousePosition(void) void SetMousePosition(Vector2 position) { mousePosition = position; -#if defined(PLATFORM_DESKTOP) +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) // NOTE: emscripten not implemented glfwSetCursorPos(window, position.x, position.y); #endif @@ -969,6 +990,41 @@ bool IsGamepadButtonUp(int gamepad, int button) } #endif +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) +// Returns touch position X +int GetTouchX(void) +{ + return (int)touchPosition.x; +} + +// Returns touch position Y +int GetTouchY(void) +{ + return (int)touchPosition.y; +} + +// Returns touch position XY +// TODO: touch position should be scaled depending on display size and render size +Vector2 GetTouchPosition(void) +{ + Vector2 position = touchPosition; + + if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) + { + // TODO: Seems to work ok but... review! + position.x = position.x*((float)screenWidth/(float)(displayWidth - renderOffsetX)) - renderOffsetX/2; + position.y = position.y*((float)screenHeight/(float)(displayHeight - renderOffsetY)) - renderOffsetY/2; + } + else + { + position.x = position.x*((float)renderWidth/(float)displayWidth) - renderOffsetX/2; + position.y = position.y*((float)renderHeight/(float)displayHeight) - renderOffsetY/2; + } + + return position; +} +#endif + //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- @@ -1547,6 +1603,13 @@ static bool GetMouseButtonStatus(int button) // Poll (store) all input events static void PollInputEvents(void) { +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) + // Touch events reading (requires gestures module) + touchPosition = GetRawTouchPosition(); + + UpdateGestures(); +#endif + #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) // Mouse input polling double mouseX; @@ -1940,6 +2003,31 @@ static void SetupFramebufferSize(int displayWidth, int displayHeight) } } +#if defined(PLATFORM_WEB) +static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const EmscriptenFullscreenChangeEvent *e, void *userData) +{ + //isFullscreen: int e->isFullscreen + //fullscreenEnabled: int e->fullscreenEnabled + //fs element nodeName: (char *) e->nodeName + //fs element id: (char *) e->id + //Current element size: (int) e->elementWidth, (int) e->elementHeight + //Screen size:(int) e->screenWidth, (int) e->screenHeight + + if (e->isFullscreen) + { + TraceLog(INFO, "Canvas scaled to fullscreen. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); + } + else + { + TraceLog(INFO, "Canvas scaled to windowed. ElementSize: (%ix%i), ScreenSize(%ix%i)", e->elementWidth, e->elementHeight, e->screenWidth, e->screenHeight); + } + + // TODO: Depending on scaling factor (screen vs element), calculate factor to scale mouse/touch input + + return 0; +} +#endif + // Plays raylib logo appearing animation static void LogoAnimation(void) { diff --git a/src/gestures.c b/src/gestures.c index 61660571..f5e8c62f 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -122,7 +122,7 @@ static int currentGesture = GESTURE_NONE; static unsigned int enabledGestures = 0; // TODO: Currently not in use... -static Vector2 touchPosition; +static Vector2 rawTouchPosition; //---------------------------------------------------------------------------------- // Module specific Functions Declaration @@ -147,55 +147,15 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) // Module Functions Definition //---------------------------------------------------------------------------------- -// Returns touch position X -int GetTouchX(void) +// Get touch position (could require further processing depending on display size) +Vector2 GetRawTouchPosition(void) { - return (int)touchPosition.x; -} - -// Returns touch position Y -int GetTouchY(void) -{ - return (int)touchPosition.y; -} - -// Returns touch position XY -// TODO: touch position should be scaled depending on display size and render size -Vector2 GetTouchPosition(void) -{ - Vector2 position = touchPosition; -/* - if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) - { - // TODO: Seems to work ok but... review! - position.x = position.x*((float)screenWidth / (float)(displayWidth - renderOffsetX)) - renderOffsetX/2; - position.y = position.y*((float)screenHeight / (float)(displayHeight - renderOffsetY)) - renderOffsetY/2; - } - else - { - position.x = position.x*((float)renderWidth / (float)displayWidth) - renderOffsetX/2; - position.y = position.y*((float)renderHeight / (float)displayHeight) - renderOffsetY/2; - } -*/ - return position; + return rawTouchPosition; } // Check if a gesture have been detected bool IsGestureDetected(void) { -/* - if (currentGesture == GESTURE_DRAG) TraceLog(INFO, "DRAG"); - else if (currentGesture == GESTURE_TAP) TraceLog(INFO, "TAP"); - else if (currentGesture == GESTURE_DOUBLETAP) TraceLog(INFO, "DOUBLE"); - else if (currentGesture == GESTURE_HOLD) TraceLog(INFO, "HOLD"); - else if (currentGesture == GESTURE_SWIPE_RIGHT) TraceLog(INFO, "RIGHT"); - else if (currentGesture == GESTURE_SWIPE_UP) TraceLog(INFO, "UP"); - else if (currentGesture == GESTURE_SWIPE_LEFT) TraceLog(INFO, "LEFT"); - else if (currentGesture == GESTURE_SWIPE_DOWN) TraceLog(INFO, "DOWN"); - else if (currentGesture == GESTURE_PINCH_IN) TraceLog(INFO, "PINCH IN"); - else if (currentGesture == GESTURE_PINCH_OUT) TraceLog(INFO, "PINCH OUT"); -*/ - if (currentGesture != GESTURE_NONE) return true; else return false; } @@ -382,7 +342,7 @@ static void ProcessMotionEvent(GestureEvent event) { lastDragPosition = endDragPosition; - endDragPosition = touchPosition; + endDragPosition = rawTouchPosition; //endDragPosition.x = AMotionEvent_getX(event, 0); //endDragPosition.y = AMotionEvent_getY(event, 0); @@ -594,8 +554,8 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) if (type == AINPUT_EVENT_TYPE_MOTION) { - touchPosition.x = AMotionEvent_getX(event, 0); - touchPosition.y = AMotionEvent_getY(event, 0); + rawTouchPosition.x = AMotionEvent_getX(event, 0); + rawTouchPosition.y = AMotionEvent_getY(event, 0); } else if (type == AINPUT_EVENT_TYPE_KEY) { @@ -676,10 +636,13 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent 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].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"); - touchPosition = gestureEvent.position[0]; + rawTouchPosition = gestureEvent.position[0]; ProcessMotionEvent(gestureEvent); diff --git a/src/raylib.h b/src/raylib.h index 9067c77d..d3729a91 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -458,13 +458,14 @@ 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) +//------------------------------------------------------------------------------------ +// 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) -- cgit v1.2.3 From 76024b5036f060a19a1a2eea49c401d6db81cda8 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 4 Nov 2015 18:33:46 +0100 Subject: Added some texture functionality (view details) LoadTextureEx() - Simplified parameters UpdateTexture() - Added, allows updating GPU texture data --- src/raylib.h | 3 ++- src/rlgl.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- src/rlgl.h | 3 ++- src/textures.c | 14 ++++++++++--- 4 files changed, 76 insertions(+), 10 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 419989d0..0b07e523 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -579,7 +579,7 @@ 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) @@ -602,6 +602,7 @@ void ImageColorGrayscale(Image *image); 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 diff --git a/src/rlgl.c b/src/rlgl.c index ebff0d53..0befad3f 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1880,6 +1880,38 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma return id; } +void rlglUpdateTexture(unsigned int id, int width, int height, int format, void *data) +{ + glBindTexture(GL_TEXTURE_2D, id); + +#if defined(GRAPHICS_API_OPENGL_33) + switch (format) + { + case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RG, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; + case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + default: TraceLog(WARNING, "Texture format updating not supported"); break; + } +#elif defined(GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_ES2) + // NOTE: on OpenGL ES 2.0 (WebGL), internalFormat must match format and options allowed are: GL_LUMINANCE, GL_RGB, GL_RGBA + switch (format) + { + case UNCOMPRESSED_GRAYSCALE: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_GRAY_ALPHA: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G6B5: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + case UNCOMPRESSED_R5G5B5A1: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, (unsigned short *)data); break; + case UNCOMPRESSED_R4G4B4A4: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, (unsigned short *)data); break; + case UNCOMPRESSED_R8G8B8A8: glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; + default: TraceLog(WARNING, "Texture format updating not supported"); break; + } +#endif +} + // Generate mipmap data for selected texture void rlglGenerateMipmaps(unsigned int textureId) { @@ -2046,6 +2078,7 @@ unsigned char *rlglReadScreenPixels(int width, int height) // Read texture pixel data // NOTE: Retrieving pixel data from GPU (glGetTexImage()) not supported on OpenGL ES 2.0 +//void *rlglReadTexturePixels(Texture2D texture) // Required to know texture size! It could not be retrieved on OpenGL ES 2.0 void *rlglReadTexturePixels(unsigned int textureId, unsigned int format) { void *pixels = NULL; @@ -2108,14 +2141,32 @@ void *rlglReadTexturePixels(unsigned int textureId, unsigned int format) #endif #if defined(GRAPHICS_API_OPENGL_ES2) - // TODO: Look for some way to retrieve texture width and height from id + // TODO: Look for some way to retrieve texture width and height from id -> NO WAY AVAILABLE int width = 1024; int height = 1024; FBO fbo = rlglLoadFBO(width, height); - // NOTE: Altenatively we can bind texture to color fbo and glReadPixels() + // NOTE: Two possible Options: + // 1 - Bind texture to color fbo attachment and glReadPixels() + // 2 - Create an fbo, activate it, render quad with texture, glReadPixels() + +#define GET_TEXTURE_FBO_OPTION_1 + +#if defined(GET_TEXTURE_FBO_OPTION_1) + glBindFramebuffer(GL_FRAMEBUFFER, fbo.id); + + // Attach color texture and depth renderbuffer to FBO + // NOTE: texture must RGB + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0); + + pixels = (unsigned char *)malloc(width*height*3*sizeof(unsigned char)); + glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + +#elif defined(GET_TEXTURE_FBO_OPTION_2) // Render texture to fbo glBindFramebuffer(GL_FRAMEBUFFER, fbo.id); glClearColor(0.0, 0.0, 0.0, 0.0); @@ -2131,8 +2182,12 @@ void *rlglReadTexturePixels(unsigned int textureId, unsigned int format) //glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); - //Model quad = GenModelQuad(width, height); - //DrawModel(quad, (Vector3){ 0, 0, 0 }, 1.0f, WHITE); + Model quad; + //quad.mesh = GenMeshQuad(width, height); + quad.transform = MatrixIdentity(); + quad.shader = simpleShader; + + DrawModel(quad, (Vector3){ 0, 0, 0 }, 1.0f, WHITE); pixels = (unsigned char *)malloc(width*height*4*sizeof(unsigned char)); @@ -2140,7 +2195,8 @@ void *rlglReadTexturePixels(unsigned int textureId, unsigned int format) // Bind framebuffer 0, which means render to back buffer glBindFramebuffer(GL_FRAMEBUFFER, 0); - +#endif // GET_TEXTURE_FBO_OPTION + // Clean up temporal fbo rlglUnloadFBO(fbo); #endif diff --git a/src/rlgl.h b/src/rlgl.h index 272b245e..ce823d97 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -242,7 +242,8 @@ void rlglClose(void); // De-init rlgl void rlglDraw(void); // Draw VAO/VBO void rlglInitGraphics(int offsetX, int offsetY, int width, int height); // Initialize Graphics (OpenGL stuff) -unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount); // Load in GPU OpenGL texture +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 // NOTE: There is a set of shader related functions that are available to end user, diff --git a/src/textures.c b/src/textures.c index 007547ca..076ed935 100644 --- a/src/textures.c +++ b/src/textures.c @@ -338,16 +338,17 @@ Texture2D LoadTexture(const char *fileName) return texture; } -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) { Texture2D texture; texture.width = width; texture.height = height; - texture.mipmaps = mipmapCount; + texture.mipmaps = 1; texture.format = textureFormat; - texture.id = rlglLoadTexture(data, width, height, textureFormat, mipmapCount); + texture.id = rlglLoadTexture(data, width, height, textureFormat, 1); return texture; } @@ -1172,6 +1173,13 @@ void GenTextureMipmaps(Texture2D texture) #endif } +// Update GPU texture with new data +// NOTE: pixels data must match texture.format +void UpdateTexture(Texture2D texture, void *pixels) +{ + rlglUpdateTexture(texture.id, texture.width, texture.height, texture.format, pixels); +} + // Draw a Texture2D void DrawTexture(Texture2D texture, int posX, int posY, Color tint) { -- cgit v1.2.3 From c17c1ccaea53a9591ddc0e57fb55644904e0d49e Mon Sep 17 00:00:00 2001 From: Ray Date: Thu, 5 Nov 2015 13:42:18 +0100 Subject: Corrected html5 glfw3 bug Mouse button values are inverted! --- src/raylib.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 0b07e523..d8655451 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -157,8 +157,13 @@ // 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 -- cgit v1.2.3 From 1b39b2e2612dfd7613e3bfb6948e8d27472ab8c1 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 14 Dec 2015 23:30:27 +0100 Subject: Added BeginDrawingEx() BeginDrawing() function with extended parameters --- src/core.c | 13 ++++++++++++- src/raylib.h | 3 ++- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index b2d94506..3fc8b47d 100644 --- a/src/core.c +++ b/src/core.c @@ -510,6 +510,17 @@ void BeginDrawing(void) // 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(GetMatrixVector(transform)); +} + // End canvas drawing and Swap Buffers (Double Buffering) void EndDrawing(void) { @@ -1097,7 +1108,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); diff --git a/src/raylib.h b/src/raylib.h index d8655451..daf8133c 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -442,6 +442,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) @@ -508,7 +509,7 @@ Vector2 GetTouchPosition(void); // Returns touch positio //------------------------------------------------------------------------------------ // Gestures and Touch Handling Functions (Module: gestures) //------------------------------------------------------------------------------------ -Vector2 GetRawTouchPosition(void); // Gewt touch position (raw) +Vector2 GetRawTouchPosition(void); // Get touch position (raw) #if defined(PLATFORM_WEB) void InitGesturesSystem(void); // Init gestures system (web) #elif defined(PLATFORM_ANDROID) -- cgit v1.2.3 From 4db2da91850fcc55ec08df253e533e236eb91451 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Mon, 21 Dec 2015 16:42:13 +0100 Subject: Added new matrix location points and extra functions - New model and view transformation matrix added, useful for shaders. Modelview matrix not deleted to keep opengl 1.1 pipeline compatibility. - New extra function added DrawModelWiresEx() to set a rotation and scale transformations to a wire model drawing. - Other writing and little audio.c bug fixed. --- src/audio.c | 2 +- src/libraylib.a | Bin 0 -> 394980 bytes src/models.c | 185 +++++++++++++++++++++++++++++--------------------------- src/raylib.h | 5 +- src/rlgl.c | 10 +++ src/rlgl.h | 4 +- 6 files changed, 114 insertions(+), 92 deletions(-) create mode 100644 src/libraylib.a (limited to 'src/raylib.h') diff --git a/src/audio.c b/src/audio.c index 8ef71116..6313c9dc 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/libraylib.a b/src/libraylib.a new file mode 100644 index 00000000..1da3aae4 Binary files /dev/null and b/src/libraylib.a differ diff --git a/src/models.c b/src/models.c index f7e39863..090c4d86 100644 --- a/src/models.c +++ b/src/models.c @@ -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); @@ -1164,6 +1164,13 @@ void DrawModelWires(Model model, Vector3 position, float scale, Color color) 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) { diff --git a/src/raylib.h b/src/raylib.h index daf8133c..cf401cca 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -329,7 +329,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) @@ -666,6 +668,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 diff --git a/src/rlgl.c b/src/rlgl.c index 3862ac74..f9108342 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1498,6 +1498,8 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r glUseProgram(model.shader.id); // Apply transformation provided in model.transform matrix + // TODO: review if at this point the modelview matrix just contains view matrix values + Matrix viewworld = modelview; // Store view matrix before applying model transformations Matrix modelviewworld = MatrixMultiply(model.transform, modelview); // World-space transformation // Apply transformations provided in function @@ -1513,6 +1515,8 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r // NOTE: Drawing in OpenGL 3.3+, transform is passed to shader glUniformMatrix4fv(model.shader.projectionLoc, 1, false, GetMatrixVector(projection)); + glUniformMatrix4fv(model.shader.modelLoc, 1, false, GetMatrixVector(transform)); + glUniformMatrix4fv(model.shader.viewLoc, 1, false, GetMatrixVector(viewworld)); glUniformMatrix4fv(model.shader.modelviewLoc, 1, false, GetMatrixVector(modelviewworld)); // Apply color tinting to model @@ -2242,6 +2246,8 @@ Shader LoadShader(char *vsFileName, char *fsFileName) // Get handles to GLSL uniform locations (vertex shader) shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix"); + shader.modelLoc = glGetUniformLocation(shader.id, "modelMatrix"); + shader.viewLoc = glGetUniformLocation(shader.id, "viewMatrix"); shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix"); // Get handles to GLSL uniform locations (fragment shader) @@ -2781,6 +2787,8 @@ static Shader LoadDefaultShader(void) // Get handles to GLSL uniform locations (vertex shader) shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix"); + shader.modelLoc = glGetUniformLocation(shader.id, "modelMatrix"); + shader.viewLoc = glGetUniformLocation(shader.id, "viewMatrix"); shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix"); // Get handles to GLSL uniform locations (fragment shader) @@ -2861,6 +2869,8 @@ static Shader LoadSimpleShader(void) // Get handles to GLSL uniform locations (vertex shader) shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix"); + shader.modelLoc = glGetUniformLocation(shader.id, "modelMatrix"); + shader.viewLoc = glGetUniformLocation(shader.id, "viewMatrix"); shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix"); // Get handles to GLSL uniform locations (fragment shader) diff --git a/src/rlgl.h b/src/rlgl.h index 0960fa83..a7df043e 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -160,7 +160,9 @@ typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; // 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) -- cgit v1.2.3 From 1bcb5ddd505e5c4bdac6f254e931e9c3145be88d Mon Sep 17 00:00:00 2001 From: victorfisac Date: Mon, 21 Dec 2015 17:25:22 +0100 Subject: Added lighting engine module - New lighting engine module which contains new data types Light and Material. These data types and functions facilitates making a basic 3D iluminated program with a light and a model. - Added lighting engine module example (currently included in raylib.h; it might be compiled by separate and include lighting.h in game source C file). - Corrected some opengl defines control structures and added some TODO to fix raylib-opengl 1.1 source build (note: now source can be compiled without errors, but rlglReadPixels() won't work properly). Note: most of functions of phong version 330 shader are not in v100 shaders, so I couldn't write a version 100 phong shader. These functions are included from version 150. --- examples/lighting_blinn_phong.c | 180 + examples/lighting_blinn_phong.png | Bin 0 -> 50097 bytes examples/resources/model/shapes.obj | 6433 +++++++++++++++++++++++++++++++++++ examples/resources/shaders/phong.fs | 76 + examples/resources/shaders/phong.vs | 28 + shaders/gl330/phong.fs | 76 + shaders/gl330/phong.vs | 28 + src/libraylib.a | Bin 394980 -> 0 bytes src/lighting.c | 124 + src/lighting.h | 87 + src/raylib.h | 40 + src/rlgl.c | 7 +- 12 files changed, 7078 insertions(+), 1 deletion(-) create mode 100644 examples/lighting_blinn_phong.c create mode 100644 examples/lighting_blinn_phong.png create mode 100644 examples/resources/model/shapes.obj create mode 100644 examples/resources/shaders/phong.fs create mode 100644 examples/resources/shaders/phong.vs create mode 100644 shaders/gl330/phong.fs create mode 100644 shaders/gl330/phong.vs delete mode 100644 src/libraylib.a create mode 100644 src/lighting.c create mode 100644 src/lighting.h (limited to 'src/raylib.h') diff --git a/examples/lighting_blinn_phong.c b/examples/lighting_blinn_phong.c new file mode 100644 index 00000000..beb2c4da --- /dev/null +++ b/examples/lighting_blinn_phong.c @@ -0,0 +1,180 @@ +/******************************************************************************************* +* +* raylib - Phong lighting shader example +* +* This example has been created using raylib v1.3.0 (www.raylib.com) +* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) +* +* Copyright (c) 2015 Ramon Santamaria (Ray San - raysan@raysanweb.com) +* +********************************************************************************************/ + +#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 [lighting] example - basic blinn-phong lighting"); + SetTargetFPS(60); + + // Camera initialization + Camera camera = {{ 10.0, 8.0, 10.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }}; + + // Model initialization + Vector3 position = { 0.0, 0.0, 0.0 }; + 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 directionalLight; + Material blinnMaterial; + + // Light initialization + SetLightPosition(&directionalLight, (Vector3){5.0f, 1.0f, 1.0f}); + SetLightRotation(&directionalLight, (Vector3){5.0f, 1.0f, 1.0f}); + SetLightIntensity(&directionalLight, 1); + SetLightAmbientColor(&directionalLight, (Vector3){0.6f, 0.3f, 0}); + SetLightDiffuseColor(&directionalLight, (Vector3){1, 1, 1}); + SetLightSpecularColor(&directionalLight, (Vector3){1, 1, 1}); + SetLightSpecIntensity(&directionalLight, 1); + + // Material initialization + SetMaterialAmbientColor(&blinnMaterial, (Vector3){0.2f, 0.2f, 0.2f}); + SetMaterialDiffuseColor(&blinnMaterial, (Vector3){1.0f, 1.0f, 1.0f}); + SetMaterialSpecularColor(&blinnMaterial, (Vector3){1.0f, 1.0f, 1.0f}); + SetMaterialGlossiness(&blinnMaterial, 50); + + // 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 + float cameraPosition[3] = { camera.position.x, camera.position.y, camera.position.z }; // Camera position vector in float array + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + + // Update camera position and its float array for shader + UpdateCamera(&camera); + cameraPosition[0] = camera.position.x; + cameraPosition[1] = camera.position.y; + cameraPosition[2] = camera.position.z; + + // Glossiness input control + if(IsKeyDown(KEY_UP)) + { + blinnMaterial.glossiness[0] += SHININESS_SPEED; + } + else if(IsKeyDown(KEY_DOWN)) + { + blinnMaterial.glossiness[0] -= SHININESS_SPEED; + + if(blinnMaterial.glossiness[0] < 0) blinnMaterial.glossiness[0] = 0; + } + + // Light X movement + if(IsKeyDown(KEY_D)) + { + directionalLight.position[0] += LIGHT_SPEED; + } + else if(IsKeyDown(KEY_A)) + { + directionalLight.position[0] -= LIGHT_SPEED; + } + + // Light Y movement + if(IsKeyDown(KEY_LEFT_SHIFT)) + { + directionalLight.position[1] += LIGHT_SPEED; + } + else if(IsKeyDown(KEY_LEFT_CONTROL)) + { + directionalLight.position[1] -= LIGHT_SPEED; + } + + // Light Z movement + if(IsKeyDown(KEY_S)) + { + directionalLight.position[2] += LIGHT_SPEED; + } + else if(IsKeyDown(KEY_W)) + { + directionalLight.position[2] -= LIGHT_SPEED; + } + + // Send light values to shader + SetShaderValue(shader, lIntensityLoc, directionalLight.intensity, 1); + SetShaderValue(shader, lAmbientLoc, directionalLight.ambientColor, 3); + SetShaderValue(shader, lDiffuseLoc, directionalLight.diffuseColor, 3); + SetShaderValue(shader, lSpecularLoc, directionalLight.specularColor, 3); + SetShaderValue(shader, lSpecIntensityLoc, directionalLight.specularIntensity, 1); + + // Send material values to shader + SetShaderValue(shader, mAmbientLoc, blinnMaterial.ambientColor, 3); + SetShaderValue(shader, mSpecularLoc, blinnMaterial.specularColor, 3); + SetShaderValue(shader, mGlossLoc, blinnMaterial.glossiness, 1); + + // Send camera and light transform values to shader + SetShaderValue(shader, cameraLoc, cameraPosition, 3); + SetShaderValue(shader, lightLoc, directionalLight.position, 3); + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + Begin3dMode(camera); + + DrawModel(model, position, 0.1f, (Color){255 * blinnMaterial.diffuseColor[0], 255 * blinnMaterial.diffuseColor[1], 255 * blinnMaterial.diffuseColor[2], 255}); + + DrawSphere((Vector3){directionalLight.position[0], directionalLight.position[1], directionalLight.position[2]}, 1, YELLOW); + + End3dMode(); + + // Draw FPS + DrawFPS(10, 10); + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + // Unload all loaded data + UnloadShader(shader); + UnloadModel(model); + + 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 00000000..4a3c5d18 Binary files /dev/null and b/examples/lighting_blinn_phong.png differ diff --git a/examples/resources/model/shapes.obj b/examples/resources/model/shapes.obj new file mode 100644 index 00000000..80205310 --- /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/phong.fs b/examples/resources/shaders/phong.fs new file mode 100644 index 00000000..bb8826f4 --- /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 tintColor; + +// 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/examples/resources/shaders/phong.vs b/examples/resources/shaders/phong.vs new file mode 100644 index 00000000..25163902 --- /dev/null +++ b/examples/resources/shaders/phong.vs @@ -0,0 +1,28 @@ +#version 330 + +// Vertex input data +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; + +// Projection and model data +uniform mat4 projectionMatrix; +uniform mat4 modelviewMatrix; +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 = projectionMatrix * modelviewMatrix * vec4(vertexPosition, 1.0); +} \ No newline at end of file diff --git a/shaders/gl330/phong.fs b/shaders/gl330/phong.fs new file mode 100644 index 00000000..bb8826f4 --- /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 tintColor; + +// 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 00000000..25163902 --- /dev/null +++ b/shaders/gl330/phong.vs @@ -0,0 +1,28 @@ +#version 330 + +// Vertex input data +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; + +// Projection and model data +uniform mat4 projectionMatrix; +uniform mat4 modelviewMatrix; +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 = projectionMatrix * modelviewMatrix * vec4(vertexPosition, 1.0); +} \ No newline at end of file diff --git a/src/libraylib.a b/src/libraylib.a deleted file mode 100644 index 1da3aae4..00000000 Binary files a/src/libraylib.a and /dev/null differ diff --git a/src/lighting.c b/src/lighting.c new file mode 100644 index 00000000..98e1696a --- /dev/null +++ b/src/lighting.c @@ -0,0 +1,124 @@ +/********************************************************************************************** +* +* raylib lighting engine module - Lighting and materials management functions +* +* 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 LIGHTING_STANDALONE // NOTE: To use the lighting module as standalone lib, just uncomment this line + +#if defined(LIGHTING_STANDALONE) + #include "lighting.h" +#else + #include "raylib.h" +#endif + +#include + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +//... + +//---------------------------------------------------------------------------------- +// Types and Structures Definitions +//---------------------------------------------------------------------------------- +//... + +//---------------------------------------------------------------------------------- +// Module Functions Definition +//---------------------------------------------------------------------------------- + +// Lights functions +void SetLightPosition(Light *light, Vector3 position) +{ + light->position[0] = position.x; + light->position[1] = position.y; + light->position[2] = position.z; +} + +void SetLightRotation(Light *light, Vector3 rotation) +{ + light->rotation[0] = rotation.x; + light->rotation[1] = rotation.y; + light->rotation[2] = rotation.z; +} + +void SetLightIntensity(Light *light, float intensity) +{ + light->intensity[0] = intensity; +} + +void SetLightAmbientColor(Light *light, Vector3 color) +{ + light->ambientColor[0] = color.x; + light->ambientColor[1] = color.y; + light->ambientColor[2] = color.z; +} + +void SetLightDiffuseColor(Light *light, Vector3 color) +{ + light->diffuseColor[0] = color.x; + light->diffuseColor[1] = color.y; + light->diffuseColor[2] = color.z; +} + +void SetLightSpecularColor(Light *light, Vector3 color) +{ + light->specularColor[0] = color.x; + light->specularColor[1] = color.y; + light->specularColor[2] = color.z; +} + +void SetLightSpecIntensity(Light *light, float specIntensity) +{ + light->specularIntensity[0] = specIntensity; +} + +// Materials functions +void SetMaterialAmbientColor(Material *material, Vector3 color) +{ + material->ambientColor[0] = color.x; + material->ambientColor[1] = color.y; + material->ambientColor[2] = color.z; +} + +void SetMaterialDiffuseColor(Material *material, Vector3 color) +{ + material->diffuseColor[0] = color.x; + material->diffuseColor[1] = color.y; + material->diffuseColor[2] = color.z; +} + +void SetMaterialSpecularColor(Material *material, Vector3 color) +{ + material->specularColor[0] = color.x; + material->specularColor[1] = color.y; + material->specularColor[2] = color.z; +} + +void SetMaterialGlossiness(Material *material, float glossiness) +{ + material->glossiness[0] = glossiness; +} + +void SetMaterialNormalDepth(Material *material, float depth) +{ + material->normalDepth[0] = depth; +} \ No newline at end of file diff --git a/src/lighting.h b/src/lighting.h new file mode 100644 index 00000000..67a65d45 --- /dev/null +++ b/src/lighting.h @@ -0,0 +1,87 @@ +/******************************************************************************************* +* +* raylib lighting engine module - Lighting and materials management functions +* +* 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 LIGHTING_H +#define LIGHTING_H + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +//... + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +// NOTE: Below types are required for LIGHTING_STANDALONE usage +//---------------------------------------------------------------------------------- +// Vector3 type +typedef struct Vector3 { + float x; + float y; + float z; +} Vector3; + +// 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; + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +// 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) + +#ifdef __cplusplus +} +#endif + +#endif // LIGHTING_H \ No newline at end of file diff --git a/src/raylib.h b/src/raylib.h index cf401cca..04ece42e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -368,6 +368,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 { @@ -702,6 +722,26 @@ 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) + //------------------------------------------------------------------------------------ // Audio Loading and Playing Functions (Module: audio) //------------------------------------------------------------------------------------ diff --git a/src/rlgl.c b/src/rlgl.c index f9108342..8a0440e0 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1094,6 +1094,7 @@ 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) @@ -1120,6 +1121,7 @@ void rlglInitPostpro(void) // 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) @@ -1939,7 +1943,8 @@ void rlglGenerateMipmaps(unsigned int textureId) { #if defined(GRAPHICS_API_OPENGL_11) // Compute required mipmaps - void *data = rlglReadTexturePixels(textureId, UNCOMPRESSED_R8G8B8A8); // TODO: Detect internal format + // TODO: rlglReadTexturePixels() needs Texture2D type parameter, not unsigned int parameter + void *data; // = rlglReadTexturePixels(textureId, UNCOMPRESSED_R8G8B8A8); // TODO: Detect internal format // NOTE: data size is reallocated to fit mipmaps data int mipmapCount = GenerateMipmaps(data, width, height); -- cgit v1.2.3 From e683fe88b9ab0fde76521a0367cdff4c229ac60c Mon Sep 17 00:00:00 2001 From: victorfisac Date: Mon, 21 Dec 2015 21:12:35 +0100 Subject: Added physics engine-module and example - Added new physics engine-module with four new data types: Physics, Transform, Rigidbody and Collider. This library contains functions to apply physics calculations to a position vector calculating collisions automatically. - Fixed some writing mistakes of lighting module. --- examples/lighting_blinn_phong.c | 18 ++- examples/physics_basic_rigidbody.c | 144 +++++++++++++++++++ examples/physics_basic_rigidbody.png | Bin 0 -> 18144 bytes src/libraylib.a | Bin 0 -> 432294 bytes src/lighting.c | 2 +- src/lighting.h | 2 +- src/physics.c | 272 +++++++++++++++++++++++++++++++++++ src/physics.h | 99 +++++++++++++ src/raylib.h | 57 ++++++++ 9 files changed, 588 insertions(+), 6 deletions(-) create mode 100644 examples/physics_basic_rigidbody.c create mode 100644 examples/physics_basic_rigidbody.png create mode 100644 src/libraylib.a create mode 100644 src/physics.c create mode 100644 src/physics.h (limited to 'src/raylib.h') diff --git a/examples/lighting_blinn_phong.c b/examples/lighting_blinn_phong.c index beb2c4da..46f95148 100644 --- a/examples/lighting_blinn_phong.c +++ b/examples/lighting_blinn_phong.c @@ -1,11 +1,21 @@ /******************************************************************************************* * -* raylib - Phong lighting shader example +* raylib [lighting] example - Basic Phong lighting * -* This example has been created using raylib v1.3.0 (www.raylib.com) +* 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 (Ray San - raysan@raysanweb.com) +* Copyright (c) 2015 Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -22,7 +32,7 @@ int main() const int screenHeight = 450; SetConfigFlags(FLAG_MSAA_4X_HINT); - InitWindow(screenWidth, screenHeight, "raylib [lighting] example - basic blinn-phong lighting"); + InitWindow(screenWidth, screenHeight, "raylib [lighting] example - blinn phong lighting"); SetTargetFPS(60); // Camera initialization diff --git a/examples/physics_basic_rigidbody.c b/examples/physics_basic_rigidbody.c new file mode 100644 index 00000000..2f3fffbc --- /dev/null +++ b/examples/physics_basic_rigidbody.c @@ -0,0 +1,144 @@ +/******************************************************************************************* +* +* raylib [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 00000000..3d691637 Binary files /dev/null and b/examples/physics_basic_rigidbody.png differ diff --git a/src/libraylib.a b/src/libraylib.a new file mode 100644 index 00000000..5ba9eda7 Binary files /dev/null and b/src/libraylib.a differ diff --git a/src/lighting.c b/src/lighting.c index 98e1696a..5cf2a2ec 100644 --- a/src/lighting.c +++ b/src/lighting.c @@ -42,7 +42,7 @@ //... //---------------------------------------------------------------------------------- -// Module Functions Definition +// Module Functions Declarations //---------------------------------------------------------------------------------- // Lights functions diff --git a/src/lighting.h b/src/lighting.h index 67a65d45..a35113c3 100644 --- a/src/lighting.h +++ b/src/lighting.h @@ -61,7 +61,7 @@ typedef struct Material { } Material; //---------------------------------------------------------------------------------- -// Module Functions Declaration +// Module Functions Definitions // NOTE: light and material structs uses float pointers instead of vectors to be compatible with SetShaderValue() //---------------------------------------------------------------------------------- // Lights functions diff --git a/src/physics.c b/src/physics.c new file mode 100644 index 00000000..90a8b2e9 --- /dev/null +++ b/src/physics.c @@ -0,0 +1,272 @@ +/********************************************************************************************** +* +* 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 PHYSICS_STANDALONE // NOTE: To use the physics module as standalone lib, just uncomment this line + +#if defined(PHYSICS_STANDALONE) + #include "physics.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.01f // 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 Functions Definition +//---------------------------------------------------------------------------------- +void InitPhysics() +{ + 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 gravity + rigidbodies[index].velocity.y += rigidbodies[index].acceleration.y; + rigidbodies[index].velocity.x += rigidbodies[index].acceleration.x; + + rigidbodies[index].velocity.y += physics.gravity.y; + rigidbodies[index].velocity.x += physics.gravity.x; + + // 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) + { + rigidbodies[index].velocity.y -= rigidbodies[index].friction; + } + else if (rigidbodies[index].velocity.y < -DECIMAL_FIX) + { + rigidbodies[index].velocity.y += rigidbodies[index].friction; + } + else + { + rigidbodies[index].velocity.y = 0; + } + + // Apply friction to acceleration + if (rigidbodies[index].isGrounded) + { + 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) + { + rigidbodies[index].acceleration.y -= rigidbodies[index].friction; + } + else if (rigidbodies[index].acceleration.y < -DECIMAL_FIX) + { + rigidbodies[index].acceleration.y += rigidbodies[index].friction; + } + else + { + rigidbodies[index].acceleration.y = 0; + } + + // 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 AddRigidbodyForce(int index, Vector2 force) +{ + rigidbodies[index].acceleration.x = force.x * rigidbodies[index].mass; + rigidbodies[index].acceleration.y = force.y * rigidbodies[index].mass; +} + +void SetColliderEnabled(int index, bool state) +{ + colliders[index].enabled = state; +} + +Collider GetCollider(int index) +{ + return colliders[index]; +} + +Rigidbody GetRigidbody(int index) +{ + return rigidbodies[index]; +} \ No newline at end of file diff --git a/src/physics.h b/src/physics.h new file mode 100644 index 00000000..211f31a2 --- /dev/null +++ b/src/physics.h @@ -0,0 +1,99 @@ +/********************************************************************************************** +* +* 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 PHYSICS_H +#define PHYSICS_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 Declaration +//---------------------------------------------------------------------------------- +void InitPhysics(); // 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 AddRigidbodyForce(int index, Vector2 force); // Set rigidbody force (considering mass value) + +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 // PHYSICS_H \ No newline at end of file diff --git a/src/raylib.h b/src/raylib.h index 04ece42e..4eefa3ea 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -433,6 +433,44 @@ typedef enum { // 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 @@ -742,6 +780,25 @@ void SetMaterialSpecularColor(Material *material, Vector3 color); // Set m 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(); // 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 AddRigidbodyForce(int index, Vector2 force); // Set rigidbody force (considering mass value) + +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) //------------------------------------------------------------------------------------ -- cgit v1.2.3 From 5dbb93dbb476c35d8f8aab24d9c3507640b171e8 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 30 Dec 2015 13:32:41 +0100 Subject: Added function: ImageDither() Corrected some code details --- src/raylib.h | 2 + src/textures.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 134 insertions(+), 29 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 4eefa3ea..785ebebb 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -654,6 +654,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) @@ -692,6 +693,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) diff --git a/src/textures.c b/src/textures.c index f97812da..54cf2cc9 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< Date: Sat, 2 Jan 2016 10:45:51 +0100 Subject: Improved fonts support Added LoadBMFont() to load AngelCode fonts (.fnt) Implemented LoadTTF() to load .ttf fonts (crappy packaging) --- src/raylib.h | 4 +- src/text.c | 306 ++++++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 210 insertions(+), 100 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 785ebebb..1113958d 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 * @@ -291,6 +291,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 diff --git a/src/text.c b/src/text.c index 0930b779..1a75b9e4 100644 --- a/src/text.c +++ b/src/text.c @@ -34,10 +34,12 @@ // 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 //---------------------------------------------------------------------------------- @@ -70,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); @@ -185,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; @@ -210,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; @@ -222,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 @@ -237,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); @@ -254,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; + + defaultFont.charOffsets = (Vector2 *)malloc(defaultFont.numChars*sizeof(Vector2)); + defaultFont.charAdvanceX = (int *)malloc(defaultFont.numChars*sizeof(int)); + + for (int i = 0; i < defaultFont.numChars; i++) + { + // NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0) + defaultFont.charOffsets[i] = (Vector2){ 0.0f, 0.0f }; + defaultFont.charAdvanceX[i] = 0; + } } else { @@ -263,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; } @@ -270,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) @@ -296,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) @@ -332,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]; @@ -341,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); } } } @@ -419,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; @@ -695,114 +736,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; - unsigned char *ttfBuffer = (unsigned char *)malloc(1 << 25); + fntFile = fopen(fileName, "rt"); - // TODO: Load TTF and generate bitmap font and chars data -> REVIEW! + if (fntFile == NULL) + { + TraceLog(WARNING, "[%s] FNT file could not be opened", fileName); + return font; + } - stbtt_packedchar chardata[128]; // Num characters: 128 (?) -> REVIEW! + // 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); - unsigned char *tempBitmap = (unsigned char *)malloc(image.width*image.height*sizeof(unsigned char)); // One channel bitmap returned! + TraceLog(INFO, "[%s] SpriteFont loaded successfully", fileName); - // Reference struct -/* - typedef struct - { - unsigned short x0,y0,x1,y1; // coordinates of bbox in bitmap - float xoff,yoff,xadvance; - float xoff2,yoff2; - } stbtt_packedchar; -*/ + return font; + +} - stbtt_pack_context pc; +// 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 + + 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; - } -*/ - free(tempBitmap); - - // 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); + dataGrayAlpha[k] = 255; + dataGrayAlpha[k + 1] = dataBitmap[i]; - 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(); + k += 2; } + + 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; - 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); - - //stbtt_aligned_quad letter; - //int x = 0, y = 0; - + UnloadImage(image); // Unloads dataGrayAlpha + + 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; - - //stbtt_GetPackedQuad(chardata[0], 512, 512, i, &x, &y, &letter, 0); + font.charValues[i] = i + FONT_FIRST_CHAR; - 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 -- cgit v1.2.3 From d32feaa6685584e9856aa94f4d5bf80b7f5b861c Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 3 Jan 2016 13:01:21 +0100 Subject: Reviewed Android inputs and gestures system Corrected Android processing for some inputs (BACK button, VOLUME buttons) Redesigned Gestures system (some work still required) SetEnabledGestures() - Only support desired gestures (requires some review) --- src/core.c | 224 +++++++++++++++++++++++++++++++------- src/gestures.c | 332 +++++++++++++++------------------------------------------ src/gestures.h | 21 ++-- src/raylib.h | 20 ++-- 4 files changed, 294 insertions(+), 303 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index acfc63d5..14510a1b 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,8 @@ 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 #elif defined(PLATFORM_RPI) static EGL_DISPMANX_WINDOW_T nativeWindow; // Native window (graphic device) @@ -149,6 +149,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 +255,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 //---------------------------------------------------------------------------------- @@ -293,9 +296,15 @@ 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; @@ -350,24 +359,23 @@ void InitWindow(int width, int height, struct android_app *state) //state->userData = &engine; app->onAppCmd = AndroidCommandCallback; - - InitAssetManager(app->activity->assetManager); + app->onInputEvent = AndroidInputCallback; - InitGesturesSystem(app); + InitAssetManager(app->activity->assetManager); TraceLog(INFO, "Android app initialized successfully"); + // 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; } } } @@ -1221,7 +1229,6 @@ static void InitDisplay(int width, int height) }; EGLint numConfigs; - EGLConfig config; // Get an EGL display connection display = eglGetDisplay(EGL_DEFAULT_DISPLAY); @@ -1455,30 +1462,62 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) if (app->window != NULL) { - // Init device display (monitor, LCD, ...) - InitDisplay(screenWidth, screenHeight); + if (contextRebindRequired) + { + // Reset screen scaling to full display size + EGLint displayFormat; + eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &displayFormat); + ANativeWindow_setBuffersGeometry(app->window, renderWidth, renderHeight, displayFormat); - // Init OpenGL graphics - InitGraphics(); + // Recreate display surface and re-attach OpenGL context + surface = eglCreateWindowSurface(display, config, app->window, NULL); + eglMakeCurrent(display, surface, surface, context); - // Load default font for convenience - // NOTE: External function (defined in module: text) - LoadDefaultFont(); + 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(); + // Init hi-res timer + InitTimer(); - // raylib logo appearing animation (if enabled) - if (showLogo) - { - SetTargetFPS(60); - LogoAnimation(); + // 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: @@ -1489,11 +1528,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; @@ -1524,6 +1570,61 @@ 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); + + //if (keycode == AKEYCODE_HOME) { } + //if (keycode == AKEYCODE_POWER) { } + if (keycode == AKEYCODE_BACK) + { + // Eat BACK_BUTTON, 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) @@ -1613,9 +1714,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 @@ -1645,23 +1745,18 @@ static void PollInputEvents(void) glfwPollEvents(); // Register keyboard/mouse events... and window events! #elif defined(PLATFORM_ANDROID) - // TODO: Check virtual keyboard (?) - // 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); } } @@ -2035,6 +2130,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/gestures.c b/src/gestures.c index adde85b9..88cdb528 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -42,23 +42,12 @@ #include // Used for clock functions #endif -#if defined(PLATFORM_ANDROID) - #include // Java native interface - #include // Android sensors functions - #include // Defines AWINDOW_FLAG_FULLSCREEN and others -#endif - -#if defined(PLATFORM_WEB) - #include - #include -#endif - //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- #define FORCE_TO_SWIPE 20 #define TAP_TIMEOUT 300 -#define MAX_TOUCH_POINTS 4 +//#define MAX_TOUCH_POINTS 4 //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -69,20 +58,6 @@ typedef enum { 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 //---------------------------------------------------------------------------------- @@ -119,133 +94,24 @@ static float pinchDelta = 0; // Pinch delta displacement static int previousGesture = GESTURE_NONE; static int currentGesture = GESTURE_NONE; -static unsigned int enabledGestures = 0; // TODO: Currently not in use... - -static Vector2 rawTouchPosition; +// Enabled gestures flags, all gestures enabled by default +static unsigned int enabledGestures = 0b0000011111111111; //---------------------------------------------------------------------------------- // 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) +// Process gesture event and translate it into gestures +void ProcessGestureEvent(GestureEvent event) { // Resets dragVector = (Vector2){ 0, 0 }; @@ -257,7 +123,7 @@ static void ProcessMotionEvent(GestureEvent event) { case TYPE_MOTIONLESS: // Detect TAP, DOUBLE_TAP and HOLD events { - if (event.action == DOWN) + if (event.touchAction == TOUCH_DOWN) { if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]); else @@ -279,7 +145,7 @@ static void ProcessMotionEvent(GestureEvent event) else currentGesture = GESTURE_TAP; } } - else if (event.action == UP) + else if (event.touchAction == TOUCH_UP) { currentGesture = GESTURE_NONE; @@ -297,7 +163,7 @@ static void ProcessMotionEvent(GestureEvent event) eventTime = GetCurrentTime(); } // Begin dragging - else if (event.action == MOVE) + else if (event.touchAction == TOUCH_MOVE) { if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]); else @@ -316,7 +182,7 @@ static void ProcessMotionEvent(GestureEvent event) case TYPE_DRAG: // Detect DRAG and SWIPE events { // end of the drag - if (event.action == UP) + if (event.touchAction == TOUCH_UP) { // Return Swipe if we have enough sensitivity if (intensity > FORCE_TO_SWIPE) @@ -334,14 +200,13 @@ static void ProcessMotionEvent(GestureEvent event) gestureType = TYPE_MOTIONLESS; } // Update while we are dragging - else if (event.action == MOVE) + else if (event.touchAction == TOUCH_MOVE) { if (event.pointCount > 1) InitPinchGesture(event.position[0], event.position[1]); else { lastDragPosition = endDragPosition; - - endDragPosition = rawTouchPosition; + endDragPosition = event.position[0]; //endDragPosition.x = AMotionEvent_getX(event, 0); //endDragPosition.y = AMotionEvent_getY(event, 0); @@ -359,7 +224,7 @@ static void ProcessMotionEvent(GestureEvent event) } break; case TYPE_DUAL_INPUT: { - if (event.action == UP) + if (event.touchAction == TOUCH_UP) { if (event.pointCount == 1) { @@ -368,7 +233,7 @@ static void ProcessMotionEvent(GestureEvent event) } gestureType = TYPE_MOTIONLESS; } - else if (event.action == MOVE) + else if (event.touchAction == TOUCH_MOVE) { // Adapt the ending position of the inputs firstEndPinchPosition = event.position[0]; @@ -410,9 +275,78 @@ static void ProcessMotionEvent(GestureEvent event) } } break; } - //-------------------------------------------------------------------- } +// 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) +{ + // Get current gesture only if enabled + return (enabledGestures & currentGesture); +} + +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 + + 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; @@ -520,103 +454,3 @@ static double GetCurrentTime() 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 keycode = AKeyEvent_getKeyCode(event); - int32_t AKeyEvent_getMetaState(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 ((keycode == 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 \ No newline at end of file diff --git a/src/gestures.h b/src/gestures.h index 896f3028..b5cf2767 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/raylib.h b/src/raylib.h index 1113958d..864a240a 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -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 //---------------------------------------------------------------------------------- @@ -432,6 +432,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; + // Camera system modes typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode; @@ -571,16 +582,11 @@ Vector2 GetTouchPosition(void); // Returns touch positio //------------------------------------------------------------------------------------ // Gestures and Touch Handling Functions (Module: gestures) //------------------------------------------------------------------------------------ -Vector2 GetRawTouchPosition(void); // Get 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 -- cgit v1.2.3 From a299bc289b36a40efcf9d02597d5122546458021 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Sun, 3 Jan 2016 17:53:29 +0100 Subject: Improved and added functions to physac engine module - Improved physics calculations. - Added AddForceAtPosition function (added to all enabled rigidbodies). - Updated raylib header. --- src/physac.c | 150 +++++++++++++++++++++++++++++++++++++++++++---------------- src/physac.h | 28 +++++------ src/raylib.h | 24 +++++----- 3 files changed, 138 insertions(+), 64 deletions(-) (limited to 'src/raylib.h') diff --git a/src/physac.c b/src/physac.c index 11e1766e..73ce7adc 100644 --- a/src/physac.c +++ b/src/physac.c @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib physics engine module - Basic functions to apply physics to 2D objects +* [physac] raylib physics engine module - Basic functions to apply physics to 2D objects * * Copyright (c) 2015 Victor Fisac and Ramon Santamaria * @@ -36,7 +36,7 @@ // Defines and Macros //---------------------------------------------------------------------------------- #define MAX_ELEMENTS 1024 // Stored rigidbodies and colliders array length -#define DECIMAL_FIX 0.01f // Decimal margin for collision checks (avoid rigidbodies shake) +#define DECIMAL_FIX 0.26f // Decimal margin for collision checks (avoid rigidbodies shake) //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -52,7 +52,14 @@ static Rigidbody rigidbodies[MAX_ELEMENTS]; static bool collisionChecker = false; //---------------------------------------------------------------------------------- -// Module Functions Definition +// 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() { @@ -94,12 +101,32 @@ void ApplyPhysics(int index, Vector2 *position) { if (rigidbodies[index].enabled) { - // Apply gravity - rigidbodies[index].velocity.y += rigidbodies[index].acceleration.y; - rigidbodies[index].velocity.x += rigidbodies[index].acceleration.x; + // 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; + } - rigidbodies[index].velocity.y += physics.gravity.y; - rigidbodies[index].velocity.x += physics.gravity.x; + 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) @@ -118,11 +145,11 @@ void ApplyPhysics(int index, Vector2 *position) } } - if (rigidbodies[index].velocity.y > DECIMAL_FIX) + if (rigidbodies[index].velocity.y > DECIMAL_FIX / 2) { rigidbodies[index].velocity.y -= rigidbodies[index].friction; } - else if (rigidbodies[index].velocity.y < -DECIMAL_FIX) + else if (rigidbodies[index].velocity.y < -DECIMAL_FIX / 2) { rigidbodies[index].velocity.y += rigidbodies[index].friction; } @@ -131,35 +158,13 @@ void ApplyPhysics(int index, Vector2 *position) rigidbodies[index].velocity.y = 0; } - // Apply friction to acceleration - if (rigidbodies[index].isGrounded) - { - 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; - } - } + // Apply gravity + rigidbodies[index].velocity.y += physics.gravity.y; + rigidbodies[index].velocity.x += physics.gravity.x; - if (rigidbodies[index].acceleration.y > DECIMAL_FIX) - { - rigidbodies[index].acceleration.y -= rigidbodies[index].friction; - } - else if (rigidbodies[index].acceleration.y < -DECIMAL_FIX) - { - rigidbodies[index].acceleration.y += rigidbodies[index].friction; - } - else - { - rigidbodies[index].acceleration.y = 0; - } + // 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; @@ -250,10 +255,49 @@ void SetRigidbodyVelocity(int index, Vector2 velocity) 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; + 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) @@ -270,3 +314,29 @@ 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 index aec57d6f..7dbfe1fe 100644 --- a/src/physac.h +++ b/src/physac.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib physics engine module - Basic functions to apply physics to 2D objects +* [physac] raylib physics engine module - Basic functions to apply physics to 2D objects * * Copyright (c) 2015 Victor Fisac and Ramon Santamaria * @@ -74,23 +74,25 @@ extern "C" { // Prevents name mangling of functions #endif //---------------------------------------------------------------------------------- -// Module Functions Declaration +// Module Functions Declarations //---------------------------------------------------------------------------------- -void InitPhysics(); // Initialize all internal physics values -void SetPhysics(Physics settings); // Set physics settings values using Physics data type to overwrite internal physics settings +void InitPhysics(); // 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 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 AddRigidbodyForce(int index, Vector2 force); // Set rigidbody force (considering mass value) +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 +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 +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 } diff --git a/src/raylib.h b/src/raylib.h index 864a240a..99a6979c 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -793,21 +793,23 @@ void SetMaterialNormalDepth(Material *material, float depth); // Set n //---------------------------------------------------------------------------------- // Physics System Functions (engine-module: physics) //---------------------------------------------------------------------------------- -void InitPhysics(); // Initialize all internal physics values -void SetPhysics(Physics settings); // Set physics settings values using Physics data type to overwrite internal physics settings +void InitPhysics(); // 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 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 AddRigidbodyForce(int index, Vector2 force); // Set rigidbody force (considering mass value) +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 +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 +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) -- cgit v1.2.3 From 70d405b41bcbbd73b9f752f4dc3910100abd1a36 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 4 Jan 2016 15:12:34 +0100 Subject: Added functionality: Storage values Two new functions added to save/load values as binary data: - StorageSaveValue() - StorageLoadValue() --- examples/core_storage_values.c | 85 +++++++++++++++++++++++++++++++++++++++ examples/core_storage_values.png | Bin 0 -> 16147 bytes src/core.c | 61 ++++++++++++++++++++++++++++ src/raylib.h | 3 ++ 4 files changed, 149 insertions(+) create mode 100644 examples/core_storage_values.c create mode 100644 examples/core_storage_values.png (limited to 'src/raylib.h') diff --git a/examples/core_storage_values.c b/examples/core_storage_values.c new file mode 100644 index 00000000..3190d0a0 --- /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 00000000..6cfd552d Binary files /dev/null and b/examples/core_storage_values.png differ diff --git a/src/core.c b/src/core.c index 14510a1b..06260281 100644 --- a/src/core.c +++ b/src/core.c @@ -708,6 +708,67 @@ void ClearDroppedFiles(void) } #endif +// 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; +} + // TODO: Gives the ray trace from mouse position Ray GetMouseRay(Vector2 mousePosition, Camera camera) { diff --git a/src/raylib.h b/src/raylib.h index 99a6979c..f1203537 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -540,6 +540,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) //------------------------------------------------------------------------------------ -- cgit v1.2.3 From ea500923565f66326e0ace470184374f158781d8 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Mon, 4 Jan 2016 21:00:20 +0100 Subject: Add Android physic buttons input detection - Added functions for detect when pressed, during down and when released. - Added defines for back, menu, volume up and down button numbers. --- src/core.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++--- src/raylib.h | 9 +++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index 06260281..6a470240 100644 --- a/src/core.c +++ b/src/core.c @@ -122,6 +122,8 @@ 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[512] = { 1 }; // Required to check if button pressed/released once +static int currentButtonState[512] = { 1 }; // Required to check if button pressed/released once #elif defined(PLATFORM_RPI) static EGL_DISPMANX_WINDOW_T nativeWindow; // Native window (graphic device) @@ -365,6 +367,13 @@ void InitWindow(int width, int height, struct android_app *state) TraceLog(INFO, "Android app initialized successfully"); + // Init button states values (default up) + for(int i = 0; i < 512; i++) + { + currentButtonState[i] = 1; + previousButtonState[i] = 1; + } + // Wait for window to be initialized (display and context) while (!windowReady) { @@ -1101,6 +1110,34 @@ Vector2 GetTouchPosition(void) return position; } + +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 //---------------------------------------------------------------------------------- @@ -1648,12 +1685,14 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) { int32_t keycode = AKeyEvent_getKeyCode(event); //int32_t AKeyEvent_getMetaState(event); + + currentButtonState[keycode] = AKeyEvent_getAction (event); // Down = 0, Up = 1 //if (keycode == AKEYCODE_HOME) { } - //if (keycode == AKEYCODE_POWER) { } - if (keycode == AKEYCODE_BACK) + if (keycode == AKEYCODE_POWER) { return 1; } + if ((keycode == AKEYCODE_BACK) || (keycode == AKEYCODE_MENU)) { - // Eat BACK_BUTTON, just do nothing... and don't let to be handled by OS! + // 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)) @@ -1778,6 +1817,7 @@ static void PollInputEvents(void) // TODO: Remove this requirement... UpdateGestures(); + #endif #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) @@ -1806,6 +1846,9 @@ static void PollInputEvents(void) glfwPollEvents(); // Register keyboard/mouse events... and window events! #elif defined(PLATFORM_ANDROID) + // Register previous keys states + for (int i = 0; i < 512; i++) previousButtonState[i] = currentButtonState[i]; + // Poll Events (registered events) // NOTE: Activity is paused if not enabled (appEnabled) while ((ident = ALooper_pollAll(appEnabled ? 0 : -1, NULL, &events,(void**)&source)) >= 0) diff --git a/src/raylib.h b/src/raylib.h index f1203537..641eac4b 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -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 @@ -581,6 +587,9 @@ 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) -- cgit v1.2.3 From fe0cf8f9a9d6cafa40a1baf8b3cdace0268ccb82 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Tue, 5 Jan 2016 13:58:20 +0100 Subject: Added some comments and fixed spaces --- src/core.c | 1 + src/physac.c | 2 +- src/physac.h | 2 +- src/raylib.h | 4 ++-- templates/android_project/jni/include/raylib.h | 4 ++-- 5 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index 40691403..1d05edc6 100644 --- a/src/core.c +++ b/src/core.c @@ -1111,6 +1111,7 @@ Vector2 GetTouchPosition(void) return position; } +// Detect if a button has been pressed once bool IsButtonPressed(int button) { bool pressed = false; diff --git a/src/physac.c b/src/physac.c index 73ce7adc..6e3b6e61 100644 --- a/src/physac.c +++ b/src/physac.c @@ -61,7 +61,7 @@ static Vector2 Vector2Normalize(Vector2 vector); //---------------------------------------------------------------------------------- // Module Functions Definitions //---------------------------------------------------------------------------------- -void InitPhysics() +void InitPhysics(void) { for (int i = 0; i < MAX_ELEMENTS; i++) { diff --git a/src/physac.h b/src/physac.h index 7dbfe1fe..558673ef 100644 --- a/src/physac.h +++ b/src/physac.h @@ -76,7 +76,7 @@ extern "C" { // Prevents name mangling of functions //---------------------------------------------------------------------------------- // Module Functions Declarations //---------------------------------------------------------------------------------- -void InitPhysics(); // Initialize all internal physics values +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 diff --git a/src/raylib.h b/src/raylib.h index 641eac4b..72211b59 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -589,7 +589,7 @@ int GetTouchY(void); // Returns touch positio 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 +bool IsButtonReleased(int button); // Detect if an android physic button has been released //------------------------------------------------------------------------------------ // Gestures and Touch Handling Functions (Module: gestures) @@ -805,7 +805,7 @@ void SetMaterialNormalDepth(Material *material, float depth); // Set n //---------------------------------------------------------------------------------- // Physics System Functions (engine-module: physics) //---------------------------------------------------------------------------------- -void InitPhysics(); // Initialize all internal physics values +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 diff --git a/templates/android_project/jni/include/raylib.h b/templates/android_project/jni/include/raylib.h index 641eac4b..72211b59 100644 --- a/templates/android_project/jni/include/raylib.h +++ b/templates/android_project/jni/include/raylib.h @@ -589,7 +589,7 @@ int GetTouchY(void); // Returns touch positio 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 +bool IsButtonReleased(int button); // Detect if an android physic button has been released //------------------------------------------------------------------------------------ // Gestures and Touch Handling Functions (Module: gestures) @@ -805,7 +805,7 @@ void SetMaterialNormalDepth(Material *material, float depth); // Set n //---------------------------------------------------------------------------------- // Physics System Functions (engine-module: physics) //---------------------------------------------------------------------------------- -void InitPhysics(); // Initialize all internal physics values +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 -- cgit v1.2.3 From 1793f2c3b87f1ed487216e23f3074085753ee346 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Thu, 7 Jan 2016 16:18:24 +0100 Subject: Added collision check between ray and box - Added CheckCollisionRayBox() function. - Updated and improved core 3d picking example (currently working as expected). --- examples/core_3d_picking.c | 14 +++++++++++--- src/models.c | 20 ++++++++++++++++++++ src/raylib.h | 1 + 3 files changed, 32 insertions(+), 3 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/core_3d_picking.c b/examples/core_3d_picking.c index 2fc05e81..0d6f4ac7 100644 --- a/examples/core_3d_picking.c +++ b/examples/core_3d_picking.c @@ -24,9 +24,12 @@ int main() Camera camera = {{ 0.0, 10.0, 10.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }}; Vector3 cubePosition = { 0.0, 1.0, 0.0 }; + Vector3 cubeSize = { 2.0, 2.0, 2.0 }; 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,8 +63,8 @@ int main() Begin3dMode(camera); - DrawCube(cubePosition, 2, 2, 2, GRAY); - DrawCubeWires(cubePosition, 2, 2, 2, DARKGRAY); + DrawCube(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, GRAY); + DrawCubeWires(cubePosition, cubeSize.x, cubeSize.y, cubeSize.z, DARKGRAY); DrawGrid(10.0, 1.0); @@ -67,6 +73,8 @@ int main() 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/src/models.c b/src/models.c index f78be41d..dd170e0b 100644 --- a/src/models.c +++ b/src/models.c @@ -1336,6 +1336,26 @@ bool CheckCollisionBoxSphere(Vector3 minBBox, Vector3 maxBBox, Vector3 centerSph return collision; } +// Detect collision between ray and 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) diff --git a/src/raylib.h b/src/raylib.h index 72211b59..b6900a97 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -756,6 +756,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 -- cgit v1.2.3 From 5e7686695fcfe32bbf956990ced0a02b7c881af1 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 11 Jan 2016 13:29:55 +0100 Subject: Review Light/Material system Simplified for the user (more intuitive and clear) Removed lighting module dependency --- examples/lighting_blinn_phong.c | 101 ++++++++++++-------------------- src/core.c | 19 +++++- src/lighting.c | 124 ---------------------------------------- src/lighting.h | 87 ---------------------------- src/raylib.h | 27 +++++---- src/raymath.c | 63 ++++++++++++-------- src/raymath.h | 3 +- src/rlgl.c | 12 ++-- 8 files changed, 113 insertions(+), 323 deletions(-) delete mode 100644 src/lighting.c delete mode 100644 src/lighting.h (limited to 'src/raylib.h') diff --git a/examples/lighting_blinn_phong.c b/examples/lighting_blinn_phong.c index d4ff548a..65dbb4f2 100644 --- a/examples/lighting_blinn_phong.c +++ b/examples/lighting_blinn_phong.c @@ -50,29 +50,28 @@ int main() int lightLoc = GetShaderLocation(shader, "lightPos"); // Light and material definitions - Light directionalLight; - Material blinnMaterial; + Light light; + Material matBlinn; // Light initialization - SetLightPosition(&directionalLight, (Vector3){5.0f, 1.0f, 1.0f}); - SetLightRotation(&directionalLight, (Vector3){5.0f, 1.0f, 1.0f}); - SetLightIntensity(&directionalLight, 1); - SetLightAmbientColor(&directionalLight, (Vector3){0.6f, 0.3f, 0}); - SetLightDiffuseColor(&directionalLight, (Vector3){1, 1, 1}); - SetLightSpecularColor(&directionalLight, (Vector3){1, 1, 1}); - SetLightSpecIntensity(&directionalLight, 1); + light.position = (Vector3){ 5.0f, 1.0f, 1.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 - SetMaterialAmbientColor(&blinnMaterial, (Vector3){0.2f, 0.2f, 0.2f}); - SetMaterialDiffuseColor(&blinnMaterial, (Vector3){1.0f, 1.0f, 1.0f}); - SetMaterialSpecularColor(&blinnMaterial, (Vector3){1.0f, 1.0f, 1.0f}); - SetMaterialGlossiness(&blinnMaterial, 50); + 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 - float cameraPosition[3] = { camera.position.x, camera.position.y, camera.position.z }; // Camera position vector in float array //-------------------------------------------------------------------------------------- // Main game loop @@ -81,69 +80,44 @@ int main() // Update //---------------------------------------------------------------------------------- - // Update camera position and its float array for shader + // Update camera position UpdateCamera(&camera); - cameraPosition[0] = camera.position.x; - cameraPosition[1] = camera.position.y; - cameraPosition[2] = camera.position.z; // Glossiness input control - if(IsKeyDown(KEY_UP)) - { - blinnMaterial.glossiness[0] += SHININESS_SPEED; - } + if(IsKeyDown(KEY_UP)) matBlinn.glossiness += SHININESS_SPEED; else if(IsKeyDown(KEY_DOWN)) { - blinnMaterial.glossiness[0] -= SHININESS_SPEED; - - if(blinnMaterial.glossiness[0] < 0) blinnMaterial.glossiness[0] = 0; + matBlinn.glossiness -= SHININESS_SPEED; + if( matBlinn.glossiness < 0) matBlinn.glossiness = 0.0f; } // Light X movement - if(IsKeyDown(KEY_D)) - { - directionalLight.position[0] += LIGHT_SPEED; - } - else if(IsKeyDown(KEY_A)) - { - directionalLight.position[0] -= LIGHT_SPEED; - } + 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)) - { - directionalLight.position[1] += LIGHT_SPEED; - } - else if(IsKeyDown(KEY_LEFT_CONTROL)) - { - directionalLight.position[1] -= LIGHT_SPEED; - } + 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)) - { - directionalLight.position[2] += LIGHT_SPEED; - } - else if(IsKeyDown(KEY_W)) - { - directionalLight.position[2] -= LIGHT_SPEED; - } + 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, directionalLight.intensity, 1); - SetShaderValue(shader, lAmbientLoc, directionalLight.ambientColor, 3); - SetShaderValue(shader, lDiffuseLoc, directionalLight.diffuseColor, 3); - SetShaderValue(shader, lSpecularLoc, directionalLight.specularColor, 3); - SetShaderValue(shader, lSpecIntensityLoc, directionalLight.specularIntensity, 1); + 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, blinnMaterial.ambientColor, 3); - SetShaderValue(shader, mSpecularLoc, blinnMaterial.specularColor, 3); - SetShaderValue(shader, mGlossLoc, blinnMaterial.glossiness, 1); + 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, cameraPosition, 3); - SetShaderValue(shader, lightLoc, directionalLight.position, 3); + SetShaderValue(shader, cameraLoc, VectorToFloat(camera.position), 3); + SetShaderValue(shader, lightLoc, VectorToFloat(light.position), 3); //---------------------------------------------------------------------------------- // Draw @@ -154,14 +128,12 @@ int main() Begin3dMode(camera); - DrawModel(model, position, 4.0f, (Color){255 * blinnMaterial.diffuseColor[0], 255 * blinnMaterial.diffuseColor[1], 255 * blinnMaterial.diffuseColor[2], 255}); - - DrawSphere((Vector3){directionalLight.position[0], directionalLight.position[1], directionalLight.position[2]}, 1, YELLOW); + DrawModel(model, position, 4.0f, matBlinn.diffuse); + DrawSphere(light.position, 1.0f, YELLOW); End3dMode(); - // Draw FPS - DrawFPS(10, 10); + DrawFPS(10, 10); // Draw FPS EndDrawing(); //---------------------------------------------------------------------------------- @@ -169,7 +141,6 @@ int main() // De-Initialization //-------------------------------------------------------------------------------------- - // Unload all loaded data UnloadShader(shader); UnloadModel(model); diff --git a/src/core.c b/src/core.c index 708f2d22..f1445cce 100644 --- a/src/core.c +++ b/src/core.c @@ -519,7 +519,7 @@ 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+ @@ -533,7 +533,7 @@ void BeginDrawingEx(int blendMode, Shader shader, Matrix transform) SetBlendMode(blendMode); SetPostproShader(shader); - rlMultMatrixf(GetMatrixVector(transform)); + rlMultMatrixf(MatrixToFloat(transform)); } // End canvas drawing and Swap Buffers (Double Buffering) @@ -588,7 +588,7 @@ void Begin3dMode(Camera camera) // Setup Camera view Matrix matView = MatrixLookAt(camera.position, camera.target, camera.up); - rlMultMatrixf(GetMatrixVector(matView)); // Multiply MODELVIEW matrix by view matrix (camera) + rlMultMatrixf(MatrixToFloat(matView)); // Multiply MODELVIEW matrix by view matrix (camera) } // Ends 3D mode and returns to default 2D orthographic mode @@ -630,6 +630,19 @@ float GetFrameTime(void) 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) { diff --git a/src/lighting.c b/src/lighting.c deleted file mode 100644 index 9014dcd4..00000000 --- a/src/lighting.c +++ /dev/null @@ -1,124 +0,0 @@ -/********************************************************************************************** -* -* raylib lighting engine module - Lighting and materials management functions -* -* 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 LIGHTING_STANDALONE // NOTE: To use the lighting module as standalone lib, just uncomment this line - -#if defined(LIGHTING_STANDALONE) - #include "lighting.h" -#else - #include "raylib.h" -#endif - -#include - -//---------------------------------------------------------------------------------- -// Defines and Macros -//---------------------------------------------------------------------------------- -//... - -//---------------------------------------------------------------------------------- -// Types and Structures Definitions -//---------------------------------------------------------------------------------- -//... - -//---------------------------------------------------------------------------------- -// Module Functions Declarations -//---------------------------------------------------------------------------------- - -// Lights functions -void SetLightPosition(Light *light, Vector3 position) -{ - light->position[0] = position.x; - light->position[1] = position.y; - light->position[2] = position.z; -} - -void SetLightRotation(Light *light, Vector3 rotation) -{ - light->rotation[0] = rotation.x; - light->rotation[1] = rotation.y; - light->rotation[2] = rotation.z; -} - -void SetLightIntensity(Light *light, float intensity) -{ - light->intensity[0] = intensity; -} - -void SetLightAmbientColor(Light *light, Vector3 color) -{ - light->ambientColor[0] = color.x; - light->ambientColor[1] = color.y; - light->ambientColor[2] = color.z; -} - -void SetLightDiffuseColor(Light *light, Vector3 color) -{ - light->diffuseColor[0] = color.x; - light->diffuseColor[1] = color.y; - light->diffuseColor[2] = color.z; -} - -void SetLightSpecularColor(Light *light, Vector3 color) -{ - light->specularColor[0] = color.x; - light->specularColor[1] = color.y; - light->specularColor[2] = color.z; -} - -void SetLightSpecIntensity(Light *light, float specIntensity) -{ - light->specularIntensity[0] = specIntensity; -} - -// Materials functions -void SetMaterialAmbientColor(Material *material, Vector3 color) -{ - material->ambientColor[0] = color.x; - material->ambientColor[1] = color.y; - material->ambientColor[2] = color.z; -} - -void SetMaterialDiffuseColor(Material *material, Vector3 color) -{ - material->diffuseColor[0] = color.x; - material->diffuseColor[1] = color.y; - material->diffuseColor[2] = color.z; -} - -void SetMaterialSpecularColor(Material *material, Vector3 color) -{ - material->specularColor[0] = color.x; - material->specularColor[1] = color.y; - material->specularColor[2] = color.z; -} - -void SetMaterialGlossiness(Material *material, float glossiness) -{ - material->glossiness[0] = glossiness; -} - -void SetMaterialNormalDepth(Material *material, float depth) -{ - material->normalDepth[0] = depth; -} diff --git a/src/lighting.h b/src/lighting.h deleted file mode 100644 index e1fc4e50..00000000 --- a/src/lighting.h +++ /dev/null @@ -1,87 +0,0 @@ -/******************************************************************************************* -* -* raylib lighting engine module - Lighting and materials management functions -* -* 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 LIGHTING_H -#define LIGHTING_H - -//---------------------------------------------------------------------------------- -// Defines and Macros -//---------------------------------------------------------------------------------- -//... - -//---------------------------------------------------------------------------------- -// Types and Structures Definition -// NOTE: Below types are required for LIGHTING_STANDALONE usage -//---------------------------------------------------------------------------------- -// Vector3 type -typedef struct Vector3 { - float x; - float y; - float z; -} Vector3; - -// 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; - -//---------------------------------------------------------------------------------- -// Module Functions Definitions -// 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) - -#ifdef __cplusplus -} -#endif - -#endif // LIGHTING_H diff --git a/src/raylib.h b/src/raylib.h index b6900a97..4d8d104d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -378,22 +378,22 @@ typedef struct 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]; + Vector3 position; + Vector3 direction; + float intensity; + float specIntensity; + Color diffuse; + Color ambient; + Color specular; } Light; // Material type typedef struct Material { - float ambientColor[3]; - float diffuseColor[3]; - float specularColor[3]; - float glossiness[1]; - float normalDepth[1]; + Color diffuse; + Color ambient; + Color specular; + float glossiness; + float normalDepth; } Material; // Texture formats @@ -535,6 +535,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 diff --git a/src/raymath.c b/src/raymath.c index eb773e5f..5feef59d 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,31 +237,32 @@ Vector3 VectorZero(void) // Module Functions Definition - Matrix math //---------------------------------------------------------------------------------- -// Returns an OpenGL-ready vector (glMultMatrixf) -// NOTE: Returned vector is row-major instead column-major as expected, -// it means, returned vector is a transposed version of the matrix! -float *GetMatrixVector(Matrix mat) -{ - static float vector[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; - - return vector; +// 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 buffer[16]; + + 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 buffer; } // Compute matrix determinant diff --git a/src/raymath.h b/src/raymath.h index e140b74c..507bf52f 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 e8b1ec47..2f525f47 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1296,8 +1296,8 @@ void rlglDraw(void) { glUseProgram(currentShader.id); - glUniformMatrix4fv(currentShader.projectionLoc, 1, false, GetMatrixVector(projection)); - glUniformMatrix4fv(currentShader.modelviewLoc, 1, false, GetMatrixVector(modelview)); + glUniformMatrix4fv(currentShader.projectionLoc, 1, false, MatrixToFloat(projection)); + glUniformMatrix4fv(currentShader.modelviewLoc, 1, false, MatrixToFloat(modelview)); glUniform1i(currentShader.mapDiffuseLoc, 0); } @@ -1524,10 +1524,10 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r // 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, GetMatrixVector(matModel)); - glUniformMatrix4fv(model.shader.viewLoc, 1, false, GetMatrixVector(matView)); - glUniformMatrix4fv(model.shader.projectionLoc, 1, false, GetMatrixVector(matProjection)); - glUniformMatrix4fv(model.shader.modelviewLoc, 1, false, GetMatrixVector(matModelView)); + glUniformMatrix4fv(model.shader.modelLoc, 1, false, MatrixToFloat(matModel)); + glUniformMatrix4fv(model.shader.viewLoc, 1, false, MatrixToFloat(matView)); + glUniformMatrix4fv(model.shader.projectionLoc, 1, false, MatrixToFloat(matProjection)); + glUniformMatrix4fv(model.shader.modelviewLoc, 1, false, MatrixToFloat(matModelView)); // Apply color tinting to model // NOTE: Just update one uniform on fragment shader -- cgit v1.2.3 From 4cc394c376c83926da67afe14855d2a3e2b06cfd Mon Sep 17 00:00:00 2001 From: victorfisac Date: Mon, 11 Jan 2016 15:59:26 +0100 Subject: Added world to screen conversion - Added function WorldToScreen(...). - Added world to screen example. - Review GetMouseRay() comment. - Removed deprecated lighting functions from raylib header. --- examples/core_world_screen.c | 77 ++++++++++++++++++++++++++++++++++++++++++++ src/core.c | 30 ++++++++++++++++- src/raylib.h | 23 ++----------- 3 files changed, 108 insertions(+), 22 deletions(-) create mode 100644 examples/core_world_screen.c (limited to 'src/raylib.h') diff --git a/examples/core_world_screen.c b/examples/core_world_screen.c new file mode 100644 index 00000000..eac5fbdc --- /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.0, 10.0, 10.0 }, { 0.0, 0.0, 0.0 }, { 0.0, 1.0, 0.0 }}; + + Vector3 cubePosition = { 0.0, 0.0, 0.0 }; + + 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, 2, 2, RED); + DrawCubeWires(cubePosition, 2, 2, 2, MAROON); + + DrawGrid(10.0, 1.0); + + 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/src/core.c b/src/core.c index f1445cce..8b61aaf7 100644 --- a/src/core.c +++ b/src/core.c @@ -791,7 +791,7 @@ int StorageLoadValue(int position) return value; } -// Gives the ray trace from mouse position +// 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 @@ -857,6 +857,34 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) 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 * GetScreenWidth(), (ndcPos.y + 1.0f) / 2.0f * GetScreenHeight() }; + + return screenPosition; +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Input (Keyboard, Mouse, Gamepad) Functions //---------------------------------------------------------------------------------- diff --git a/src/raylib.h b/src/raylib.h index 4d8d104d..d6b28e53 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -527,7 +527,8 @@ void EndDrawing(void); // End canvas drawin 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 @@ -786,26 +787,6 @@ 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) //---------------------------------------------------------------------------------- -- cgit v1.2.3 From fb6ef2c2f4fe22552908d339cda541453e43faec Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 13 Jan 2016 17:13:28 +0100 Subject: Vertex shaders optimization --- examples/resources/shaders/base.vs | 5 +-- examples/resources/shaders/bloom.fs | 2 +- examples/resources/shaders/grayscale.fs | 6 +-- examples/resources/shaders/phong.fs | 2 +- examples/resources/shaders/phong.vs | 4 +- examples/resources/shaders/shapes_base.vs | 9 ++--- examples/resources/shaders/shapes_grayscale.fs | 4 +- examples/resources/shaders/swirl.fs | 2 +- shaders/gl330/base.vs | 5 +-- shaders/gl330/bloom.fs | 2 +- shaders/gl330/blur.fs | 2 +- shaders/gl330/cross_hatching.fs | 2 +- shaders/gl330/cross_stitching.fs | 2 +- shaders/gl330/dream_vision.fs | 2 +- shaders/gl330/fisheye.fs | 2 +- shaders/gl330/grayscale.fs | 6 +-- shaders/gl330/phong.fs | 2 +- shaders/gl330/phong.vs | 7 ++-- shaders/gl330/pixel.fs | 2 +- shaders/gl330/posterization.fs | 2 +- shaders/gl330/predator.fs | 2 +- shaders/gl330/scanlines.fs | 2 +- shaders/gl330/swirl.fs | 2 +- shaders/gl330/template.fs | 4 +- shaders/gles100/base.vs | 5 +-- shaders/gles100/bloom.fs | 2 +- shaders/gles100/blur.fs | 2 +- shaders/gles100/cross_hatching.fs | 2 +- shaders/gles100/cross_stitching.fs | 2 +- shaders/gles100/dream_vision.fs | 2 +- shaders/gles100/fisheye.fs | 2 +- shaders/gles100/grayscale.fs | 6 +-- shaders/gles100/pixel.fs | 2 +- shaders/gles100/posterization.fs | 2 +- shaders/gles100/predator.fs | 2 +- shaders/gles100/scanlines.fs | 2 +- shaders/gles100/swirl.fs | 2 +- shaders/gles100/template.fs | 4 +- src/raylib.h | 4 +- src/rlgl.c | 53 +++++++++++++------------- src/rlgl.h | 4 +- 41 files changed, 86 insertions(+), 92 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/resources/shaders/base.vs b/examples/resources/shaders/base.vs index 59eae0a0..b0f930b7 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 f9cebe18..2833ce33 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 38337e00..af50b8c1 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 index bb8826f4..75b7e6d7 100644 --- a/examples/resources/shaders/phong.fs +++ b/examples/resources/shaders/phong.fs @@ -6,7 +6,7 @@ in vec3 fragNormal; // Diffuse data uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // Light attributes uniform vec3 light_ambientColor = vec3(0.6, 0.3, 0); diff --git a/examples/resources/shaders/phong.vs b/examples/resources/shaders/phong.vs index 25163902..c6ef77de 100644 --- a/examples/resources/shaders/phong.vs +++ b/examples/resources/shaders/phong.vs @@ -6,8 +6,8 @@ in vec2 vertexTexCoord; in vec3 vertexNormal; // Projection and model data -uniform mat4 projectionMatrix; -uniform mat4 modelviewMatrix; +uniform mat4 mvpMatrix; + uniform mat4 modelMatrix; // Attributes to fragment shader diff --git a/examples/resources/shaders/shapes_base.vs b/examples/resources/shaders/shapes_base.vs index 78e543b7..1fd686be 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 1b778871..23ba9153 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 ba26cc05..ace6e79d 100644 --- a/examples/resources/shaders/swirl.fs +++ b/examples/resources/shaders/swirl.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/shaders/gl330/base.vs b/shaders/gl330/base.vs index 59eae0a0..b0f930b7 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 f9cebe18..2833ce33 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 diff --git a/shaders/gl330/blur.fs b/shaders/gl330/blur.fs index b4e5bd2b..bd2b521f 100644 --- a/shaders/gl330/blur.fs +++ b/shaders/gl330/blur.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/shaders/gl330/cross_hatching.fs b/shaders/gl330/cross_hatching.fs index e2362212..7e25b25b 100644 --- a/shaders/gl330/cross_hatching.fs +++ b/shaders/gl330/cross_hatching.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/shaders/gl330/cross_stitching.fs b/shaders/gl330/cross_stitching.fs index 041bf1dc..73f867b6 100644 --- a/shaders/gl330/cross_stitching.fs +++ b/shaders/gl330/cross_stitching.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/shaders/gl330/dream_vision.fs b/shaders/gl330/dream_vision.fs index de9c04eb..f9316342 100644 --- a/shaders/gl330/dream_vision.fs +++ b/shaders/gl330/dream_vision.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/shaders/gl330/fisheye.fs b/shaders/gl330/fisheye.fs index d0e42cca..bbbff65c 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 diff --git a/shaders/gl330/grayscale.fs b/shaders/gl330/grayscale.fs index 38337e00..af50b8c1 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 = 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/shaders/gl330/phong.fs b/shaders/gl330/phong.fs index bb8826f4..75b7e6d7 100644 --- a/shaders/gl330/phong.fs +++ b/shaders/gl330/phong.fs @@ -6,7 +6,7 @@ in vec3 fragNormal; // Diffuse data uniform sampler2D texture0; -uniform vec4 tintColor; +uniform vec4 fragTintColor; // Light attributes uniform vec3 light_ambientColor = vec3(0.6, 0.3, 0); diff --git a/shaders/gl330/phong.vs b/shaders/gl330/phong.vs index 25163902..ee6d34bf 100644 --- a/shaders/gl330/phong.vs +++ b/shaders/gl330/phong.vs @@ -6,8 +6,7 @@ in vec2 vertexTexCoord; in vec3 vertexNormal; // Projection and model data -uniform mat4 projectionMatrix; -uniform mat4 modelviewMatrix; +uniform mat4 mvpMatrix; uniform mat4 modelMatrix; // Attributes to fragment shader @@ -21,8 +20,8 @@ void main() // Calculate view vector normal from model mat3 normalMatrix = transpose(inverse(mat3(modelMatrix))); - fragNormal = normalize(normalMatrix * vertexNormal); + fragNormal = normalize(normalMatrix*vertexNormal); // Calculate final vertex position - 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/pixel.fs b/shaders/gl330/pixel.fs index ec9e13d7..feee1423 100644 --- a/shaders/gl330/pixel.fs +++ b/shaders/gl330/pixel.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/shaders/gl330/posterization.fs b/shaders/gl330/posterization.fs index 652cf609..a4e49466 100644 --- a/shaders/gl330/posterization.fs +++ b/shaders/gl330/posterization.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/shaders/gl330/predator.fs b/shaders/gl330/predator.fs index 77882917..2295d01b 100644 --- a/shaders/gl330/predator.fs +++ b/shaders/gl330/predator.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/shaders/gl330/scanlines.fs b/shaders/gl330/scanlines.fs index 7f33f882..57297299 100644 --- a/shaders/gl330/scanlines.fs +++ b/shaders/gl330/scanlines.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/shaders/gl330/swirl.fs b/shaders/gl330/swirl.fs index 18a47cec..e88b59c9 100644 --- a/shaders/gl330/swirl.fs +++ b/shaders/gl330/swirl.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/shaders/gl330/template.fs b/shaders/gl330/template.fs index 92221959..660e8484 100644 --- a/shaders/gl330/template.fs +++ b/shaders/gl330/template.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 @@ -15,5 +15,5 @@ void main() // 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 eff89c56..9f339382 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 eba44d41..33754c7e 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 3c865ca0..a1069c6f 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 c308acb6..cf01b65e 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 09b3ad4a..f1afef04 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 6cbdfcd6..bb828970 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 a21257c7..e7a4485c 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 07e79614..e55545e2 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 eceff6e3..552e8900 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 f635305e..4f4c4b93 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 c85048a6..2fbdc7af 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 56a6f694..85de158d 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 b50ed39e..b0d54b23 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 9d9499f3..1f4b8ccf 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/raylib.h b/src/raylib.h index d6b28e53..1a99f007 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -336,8 +336,8 @@ typedef struct Shader { int colorLoc; // Color attibute location point (vertex shader) // Uniforms - int projectionLoc; // Projection matrix uniform location point (vertex shader) - int modelviewLoc; // ModelView 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) diff --git a/src/rlgl.c b/src/rlgl.c index 2f525f47..e3c763be 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1295,9 +1295,10 @@ 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, MatrixToFloat(projection)); - glUniformMatrix4fv(currentShader.modelviewLoc, 1, false, MatrixToFloat(modelview)); + glUniformMatrix4fv(currentShader.mvpLoc, 1, false, MatrixToFloat(matMVP)); glUniform1i(currentShader.mapDiffuseLoc, 0); } @@ -1520,14 +1521,14 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r Matrix matModelView = MatrixMultiply(matModel, matView); // Transform to camera-space coordinates // Calculate model-view-projection matrix (MVP) - //Matrix matMVP = MatrixMultiply(matModelView, matProjection); // Transform to screen-space coordinates + Matrix matMVP = MatrixMultiply(matModelView, matProjection); // Transform to screen-space coordinates // 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.projectionLoc, 1, false, MatrixToFloat(matProjection)); - glUniformMatrix4fv(model.shader.modelviewLoc, 1, false, MatrixToFloat(matModelView)); + + glUniformMatrix4fv(model.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); // Apply color tinting to model // NOTE: Just update one uniform on fragment shader @@ -2247,13 +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.mvpLoc = glGetUniformLocation(shader.id, "mvpMatrix"); + shader.modelLoc = glGetUniformLocation(shader.id, "modelMatrix"); shader.viewLoc = glGetUniformLocation(shader.id, "viewMatrix"); - shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix"); // 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 @@ -2738,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); @@ -2788,10 +2788,10 @@ static Shader LoadDefaultShader(void) shader.normalLoc = -1; // Get handles to GLSL uniform locations (vertex shader) - shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix"); + shader.mvpLoc = glGetUniformLocation(shader.id, "mvpMatrix"); + shader.modelLoc = glGetUniformLocation(shader.id, "modelMatrix"); shader.viewLoc = glGetUniformLocation(shader.id, "viewMatrix"); - shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix"); // Get handles to GLSL uniform locations (fragment shader) shader.tintColorLoc = -1; @@ -2831,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 @@ -2849,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); @@ -2870,13 +2869,13 @@ static Shader LoadSimpleShader(void) shader.colorLoc = -1; // Get handles to GLSL uniform locations (vertex shader) - shader.modelviewLoc = glGetUniformLocation(shader.id, "modelviewMatrix"); + shader.mvpLoc = glGetUniformLocation(shader.id, "mvpMatrix"); + shader.modelLoc = glGetUniformLocation(shader.id, "modelMatrix"); shader.viewLoc = glGetUniformLocation(shader.id, "viewMatrix"); - shader.projectionLoc = glGetUniformLocation(shader.id, "projectionMatrix"); // 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 diff --git a/src/rlgl.h b/src/rlgl.h index 93b56bb2..d33844ce 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -159,8 +159,8 @@ 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; // ModelView 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) -- cgit v1.2.3 From fd05d3e3531964a38ea84df920264a1ed14bb777 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 18 Jan 2016 13:36:18 +0100 Subject: Rename VertexData struct to Mesh Reviewed vertex type variables --- src/models.c | 248 +++++++++++++++++++++++++++++------------------------------ src/raylib.h | 34 +++++--- src/rlgl.c | 16 ++-- src/rlgl.h | 29 ++++--- 4 files changed, 171 insertions(+), 156 deletions(-) (limited to 'src/raylib.h') diff --git a/src/models.c b/src/models.c index 8b49731d..d4b21258 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 @@ -558,23 +558,23 @@ 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 1: We don't need CPU vertex data on OpenGL 3.3 or ES2... for static meshes... @@ -583,10 +583,10 @@ Model LoadModel(const char *fileName) /* 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); } */ } @@ -595,7 +595,7 @@ Model LoadModel(const char *fileName) } // Load a 3d model (from vertex data) -Model LoadModelEx(VertexData data) +Model LoadModelEx(Mesh data) { Model model; @@ -610,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; @@ -621,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 @@ -644,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 @@ -696,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 @@ -713,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; @@ -735,7 +735,7 @@ 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); @@ -1041,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; } @@ -1068,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; } @@ -1079,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; } @@ -1090,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; @@ -1617,9 +1617,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]; @@ -1636,7 +1636,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 @@ -1747,15 +1747,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 @@ -1783,32 +1783,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 @@ -1817,17 +1817,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; } @@ -1835,14 +1835,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; @@ -1853,19 +1853,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/raylib.h b/src/raylib.h index 1a99f007..16311df8 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -308,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 { @@ -349,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; @@ -742,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) diff --git a/src/rlgl.c b/src/rlgl.c index 7afa374e..ca08e1a2 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1100,9 +1100,9 @@ void rlglInitPostpro(void) 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 = (float)screenWidth; float h = (float)screenHeight; @@ -1112,12 +1112,12 @@ void rlglInitPostpro(void) 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 } @@ -1982,7 +1982,7 @@ void rlglGenerateMipmaps(Texture2D texture) } // Load vertex data into a VAO (if supported) and VBO -Model rlglLoadModel(VertexData mesh) +Model rlglLoadModel(Mesh mesh) { Model model; diff --git a/src/rlgl.h b/src/rlgl.h index d33844ce..066e0339 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 { @@ -179,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; @@ -254,7 +259,7 @@ void rlglGenerateMipmaps(Texture2D texture); // Gene 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 -- cgit v1.2.3 From efa1c96d19095c801a01dbf9b0214a82b7ae8c11 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 20 Jan 2016 18:20:05 +0100 Subject: Adapted raymath as single header library Added support for single header implementation and also inline functions support --- src/core.c | 45 ++++++- src/models.c | 6 +- src/raylib.h | 4 +- src/raymath.h | 414 ++++++++++++++++++++++++++++++++-------------------------- src/rlgl.c | 2 + src/rlgl.h | 9 +- 6 files changed, 282 insertions(+), 198 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index 7b7d65fc..f55dba50 100644 --- a/src/core.c +++ b/src/core.c @@ -38,9 +38,12 @@ #include "raylib.h" // raylib main header #include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 -#include "raymath.h" // Required for data type Matrix and Matrix functions #include "utils.h" // TraceLog() function // NOTE: Includes Android fopen map, InitAssetManager() + +#define RAYMATH_IMPLEMENTATION // Use raymath as a header-only library (includes implementation) +#define RAYMATH_EXTERN_INLINE // Compile raymath functions as static inline (remember, it's a compiler hint) +#include "raymath.h" // Required for Vector3 and Matrix functions #include // Standard input / output lib #include // Declares malloc() and free() for memory management, rand(), atexit() @@ -643,6 +646,46 @@ float *ColorToFloat(Color color) return buffer; } +// 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; +} + +// 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 buffer[16]; + + 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 buffer; +} + // Returns a Color struct from hexadecimal value Color GetColor(int hexValue) { diff --git a/src/models.c b/src/models.c index 06044820..3d228a30 100644 --- a/src/models.c +++ b/src/models.c @@ -34,8 +34,8 @@ #include // Required for strcmp() #include // Used for sin, cos, tan -#include "raymath.h" // Required for data type Matrix and Matrix functions #include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 +#include "raymath.h" // Required for data type Matrix and Matrix functions //---------------------------------------------------------------------------------- // Defines and Macros @@ -1373,8 +1373,8 @@ bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox) BoundingBox CalculateBoundingBox(Mesh mesh) { // Get min and max vertex to construct bounds (AABB) - Vector3 minVertex = mesh.vertices[0]; - Vector3 maxVertex = mesh.vertices[0]; + Vector3 minVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] }; + Vector3 maxVertex = (Vector3){ mesh.vertices[0], mesh.vertices[1], mesh.vertices[2] }; for (int i = 1; i < mesh.vertexCount; i++) { diff --git a/src/raylib.h b/src/raylib.h index 16311df8..0a768fe4 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -547,8 +547,8 @@ 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) +float *VectorToFloat(Vector3 vec); // Converts Vector3 to float array +float *MatrixToFloat(Matrix mat); // Converts Matrix to float array 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 diff --git a/src/raymath.h b/src/raymath.h index f5912795..8ad32528 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -1,9 +1,23 @@ /********************************************************************************************** * -* raymath +* raymath (header only file) * * Some useful functions to work with Vector3, Matrix and Quaternions * +* You must: +* #define RAYMATH_IMPLEMENTATION +* before you include this file in *only one* C or C++ file to create the implementation. +* +* Example: +* #define RAYMATH_IMPLEMENTATION +* #include "raymath.h" +* +* You can also use: +* #define RAYMATH_EXTERN_INLINE // Inlines all functions code, so it runs faster. +* // This requires lots of memory on system. +* #define RAYMATH_STANDALONE // Not dependent on raylib.h structs: Vector3, Matrix. +* +* * Copyright (c) 2015 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event @@ -22,37 +36,21 @@ * 3. This notice may not be removed or altered from any source distribution. * **********************************************************************************************/ -//============================================================================ -// YOU MUST -// -// #define RAYMATH_DEFINE -// -// Like: -// -// #define RAYMATH_DEFINE -// #include "raymath.h" -// -// YOU CAN: -// #define RAYMATH_INLINE //inlines all code, so it runs faster. This requires lots of memory on system. -// AND -// #define RAYMATH_STANDALONE //not dependent on outside libs -// -// This needs to be done for every library/source file. -//============================================================================ - -#ifdef RAYMATH_INLINE - #define RMDEF static inline -#else - #define RMDEF static -#endif #ifndef RAYMATH_H #define RAYMATH_H -//#define RAYMATH_STANDALONE // NOTE: To use raymath as standalone lib, just uncomment this line +//#define RAYMATH_STANDALONE // NOTE: To use raymath as standalone lib, just uncomment this line +//#define RAYMATH_EXTERN_INLINE // NOTE: To compile functions as static inline, uncomment this line #ifndef RAYMATH_STANDALONE - #include "raylib.h" // Required for typedef: Vector3 + #include "raylib.h" // Required for structs: Vector3, Matrix +#endif + +#if defined(RAYMATH_EXTERN_INLINE) + #define RMDEF extern inline +#else + #define RMDEF extern #endif //---------------------------------------------------------------------------------- @@ -63,18 +61,18 @@ #endif #ifndef DEG2RAD - #define DEG2RAD (PI / 180.0f) + #define DEG2RAD (PI/180.0f) #endif #ifndef RAD2DEG - #define RAD2DEG (180.0f / PI) + #define RAD2DEG (180.0f/PI) #endif //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -#ifdef RAYMATH_STANDALONE +#if defined(RAYMATH_STANDALONE) // Vector2 type typedef struct Vector2 { float x; @@ -105,7 +103,77 @@ typedef struct Quaternion { float w; } Quaternion; -#ifdef RAYMATH_DEFINE +#ifndef RAYMATH_EXTERN_INLINE + +#ifdef __cplusplus +extern "C" { +#endif + +//------------------------------------------------------------------------------------ +// Functions Declaration to work with Vector3 +//------------------------------------------------------------------------------------ +RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2); // Add two vectors +RMDEF Vector3 VectorSubtract(Vector3 v1, Vector3 v2); // Substract two vectors +RMDEF Vector3 VectorCrossProduct(Vector3 v1, Vector3 v2); // Calculate two vectors cross product +RMDEF Vector3 VectorPerpendicular(Vector3 v); // Calculate one vector perpendicular vector +RMDEF float VectorDotProduct(Vector3 v1, Vector3 v2); // Calculate two vectors dot product +RMDEF float VectorLength(const Vector3 v); // Calculate vector lenght +RMDEF void VectorScale(Vector3 *v, float scale); // Scale provided vector +RMDEF void VectorNegate(Vector3 *v); // Negate provided vector (invert direction) +RMDEF void VectorNormalize(Vector3 *v); // Normalize provided vector +RMDEF float VectorDistance(Vector3 v1, Vector3 v2); // Calculate distance between two points +RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount); // Calculate linear interpolation between two vectors +RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal +RMDEF void VectorTransform(Vector3 *v, Matrix mat); // Transforms a Vector3 by a given Matrix +RMDEF Vector3 VectorZero(void); // Return a Vector3 init to zero + +//------------------------------------------------------------------------------------ +// Functions Declaration to work with Matrix +//------------------------------------------------------------------------------------ +RMDEF float MatrixDeterminant(Matrix mat); // Compute matrix determinant +RMDEF float MatrixTrace(Matrix mat); // Returns the trace of the matrix (sum of the values along the diagonal) +RMDEF void MatrixTranspose(Matrix *mat); // Transposes provided matrix +RMDEF void MatrixInvert(Matrix *mat); // Invert provided matrix +RMDEF void MatrixNormalize(Matrix *mat); // Normalize provided matrix +RMDEF Matrix MatrixIdentity(void); // Returns identity matrix +RMDEF Matrix MatrixAdd(Matrix left, Matrix right); // Add two matrices +RMDEF Matrix MatrixSubstract(Matrix left, Matrix right); // Substract two matrices (left - right) +RMDEF Matrix MatrixTranslate(float x, float y, float z); // Returns translation matrix +RMDEF Matrix MatrixRotate(float angle, Vector3 axis); // Returns rotation matrix for an angle around an specified axis (angle in radians) +RMDEF Matrix MatrixRotateX(float angle); // Returns x-rotation matrix (angle in radians) +RMDEF Matrix MatrixRotateY(float angle); // Returns y-rotation matrix (angle in radians) +RMDEF Matrix MatrixRotateZ(float angle); // Returns z-rotation matrix (angle in radians) +RMDEF Matrix MatrixScale(float x, float y, float z); // Returns scaling matrix +RMDEF Matrix MatrixMultiply(Matrix left, Matrix right); // Returns two matrix multiplication +RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, double near, double far); // Returns perspective projection matrix +RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far); // Returns perspective projection matrix +RMDEF Matrix MatrixOrtho(double left, double right, double bottom, double top, double near, double far); // Returns orthographic projection matrix +RMDEF Matrix MatrixLookAt(Vector3 position, Vector3 target, Vector3 up); // Returns camera look-at matrix (view matrix) +RMDEF void PrintMatrix(Matrix m); // Print matrix utility + +//------------------------------------------------------------------------------------ +// Functions Declaration to work with Quaternions +//------------------------------------------------------------------------------------ +RMDEF float QuaternionLength(Quaternion quat); // Compute the length of a quaternion +RMDEF void QuaternionNormalize(Quaternion *q); // Normalize provided quaternion +RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2); // Calculate two quaternion multiplication +RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float slerp); // Calculates spherical linear interpolation between two quaternions +RMDEF Quaternion QuaternionFromMatrix(Matrix matrix); // Returns a quaternion for a given rotation matrix +RMDEF Matrix QuaternionToMatrix(Quaternion q); // Returns a matrix for a given quaternion +RMDEF Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis); // Returns rotation quaternion for an angle and axis +RMDEF void QuaternionToAxisAngle(Quaternion q, float *outAngle, Vector3 *outAxis); // Returns the rotation angle and axis for a given quaternion +RMDEF void QuaternionTransform(Quaternion *q, Matrix mat); // Transform a quaternion given a transformation matrix + +#ifdef __cplusplus +} +#endif + +#endif // notdef RAYMATH_EXTERN_INLINE + +//////////////////////////////////////////////////////////////////// end of header file + +#if defined(RAYMATH_IMPLEMENTATION) || defined(RAYMATH_EXTERN_INLINE) + #include // Used only on PrintMatrix() #include // Standard math libary: sin(), cos(), tan()... #include // Used for abs() @@ -114,18 +182,6 @@ typedef struct Quaternion { // Module Functions Definition - Vector3 math //---------------------------------------------------------------------------------- -// Converts Vector3 to float array -RMDEF 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 RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2) { @@ -229,9 +285,9 @@ RMDEF void VectorNormalize(Vector3 *v) length = VectorLength(*v); - if (length == 0) length = 1; + if (length == 0) length = 1.0f; - ilength = 1.0/length; + ilength = 1.0f/length; v->x *= ilength; v->y *= ilength; @@ -257,9 +313,9 @@ RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount) { Vector3 result; - result.x = v1.x + amount * (v2.x - v1.x); - result.y = v1.y + amount * (v2.y - v1.y); - result.z = v1.z + amount * (v2.z - v1.z); + result.x = v1.x + amount*(v2.x - v1.x); + result.y = v1.y + amount*(v2.y - v1.y); + result.z = v1.z + amount*(v2.z - v1.z); return result; } @@ -269,15 +325,15 @@ RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal) { // I is the original vector // N is the normal of the incident plane - // R = I - (2 * N * ( DotProduct[ I,N] )) + // R = I - (2*N*( DotProduct[ I,N] )) Vector3 result; float dotProduct = VectorDotProduct(vector, normal); - result.x = vector.x - (2.0 * normal.x) * dotProduct; - result.y = vector.y - (2.0 * normal.y) * dotProduct; - result.z = vector.z - (2.0 * normal.z) * dotProduct; + result.x = vector.x - (2.0f*normal.x)*dotProduct; + result.y = vector.y - (2.0f*normal.y)*dotProduct; + result.z = vector.z - (2.0f*normal.z)*dotProduct; return result; } @@ -308,34 +364,6 @@ RMDEF Vector3 VectorZero(void) // Module Functions Definition - Matrix math //---------------------------------------------------------------------------------- -// 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 -RMDEF float *MatrixToFloat(Matrix mat) -{ - static float buffer[16]; - - 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 buffer; -} - // Compute matrix determinant RMDEF float MatrixDeterminant(Matrix mat) { @@ -413,7 +441,7 @@ RMDEF void MatrixInvert(Matrix *mat) float b11 = a22*a33 - a23*a32; // Calculate the invert determinant (inlined to avoid double-caching) - float invDet = 1/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); + float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); temp.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet; temp.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet; @@ -461,7 +489,10 @@ RMDEF void MatrixNormalize(Matrix *mat) // Returns identity matrix RMDEF Matrix MatrixIdentity(void) { - Matrix result = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; + Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; return result; } @@ -519,7 +550,10 @@ RMDEF Matrix MatrixSubstract(Matrix left, Matrix right) // Returns translation matrix RMDEF Matrix MatrixTranslate(float x, float y, float z) { - Matrix result = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1 }; + Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + x, y, z, 1.0f }; return result; } @@ -536,9 +570,9 @@ RMDEF Matrix MatrixRotate(float angle, Vector3 axis) float length = sqrt(x*x + y*y + z*z); - if ((length != 1) && (length != 0)) + if ((length != 1.0f) && (length != 0.0f)) { - length = 1/length; + length = 1.0f/length; x *= length; y *= length; z *= length; @@ -594,15 +628,15 @@ RMDEF Matrix MatrixRotate(float angle, float x, float y, float z) m2 = result.m2, m6 = result.m6, m10 = result.m10, m14 = result.m14; // build rotation matrix - float r0 = x * x * c1 + c; - float r1 = x * y * c1 + z * s; - float r2 = x * z * c1 - y * s; - float r4 = x * y * c1 - z * s; - float r5 = y * y * c1 + c; - float r6 = y * z * c1 + x * s; - float r8 = x * z * c1 + y * s; - float r9 = y * z * c1 - x * s; - float r10= z * z * c1 + c; + float r0 = x*x*c1 + c; + float r1 = x*y*c1 + z*s; + float r2 = x*z*c1 - y*s; + float r4 = x*y*c1 - z*s; + float r5 = y*y*c1 + c; + float r6 = y*z*c1 + x*s; + float r8 = x*z*c1 + y*s; + float r9 = y*z*c1 - x*s; + float r10= z*z*c1 + c; // multiply rotation matrix result.m0 = r0*m0 + r4*m1 + r8*m2; @@ -673,7 +707,10 @@ RMDEF Matrix MatrixRotateZ(float angle) // Returns scaling matrix RMDEF Matrix MatrixScale(float x, float y, float z) { - Matrix result = { x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 }; + Matrix result = { x, 0.0f, 0.0f, 0.0f, + 0.0f, y, 0.0f, 0.0f, + 0.0f, 0.0f, z, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; return result; } @@ -713,25 +750,25 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, float tb = (top - bottom); float fn = (far - near); - result.m0 = (near*2.0f) / rl; - result.m1 = 0; - result.m2 = 0; - result.m3 = 0; + result.m0 = (near*2.0f)/rl; + result.m1 = 0.0f; + result.m2 = 0.0f; + result.m3 = 0.0f; - result.m4 = 0; - result.m5 = (near*2.0f) / tb; - result.m6 = 0; - result.m7 = 0; + result.m4 = 0.0f; + result.m5 = (near*2.0f)/tb; + result.m6 = 0.0f; + result.m7 = 0.0f; - result.m8 = (right + left) / rl; - result.m9 = (top + bottom) / tb; - result.m10 = -(far + near) / fn; + result.m8 = (right + left)/rl; + result.m9 = (top + bottom)/tb; + result.m10 = -(far + near)/fn; result.m11 = -1.0f; - result.m12 = 0; - result.m13 = 0; - result.m14 = -(far*near*2.0f) / fn; - result.m15 = 0; + result.m12 = 0.0f; + result.m13 = 0.0f; + result.m14 = -(far*near*2.0f)/fn; + result.m15 = 0.0f; return result; } @@ -739,7 +776,7 @@ RMDEF Matrix MatrixFrustum(double left, double right, double bottom, double top, // Returns perspective projection matrix RMDEF Matrix MatrixPerspective(double fovy, double aspect, double near, double far) { - double top = near*tanf(fovy*PI / 360.0f); + double top = near*tanf(fovy*PI/360.0f); double right = top*aspect; return MatrixFrustum(-right, right, -top, top, near, far); @@ -754,22 +791,22 @@ RMDEF Matrix MatrixOrtho(double left, double right, double bottom, double top, d float tb = (top - bottom); float fn = (far - near); - result.m0 = 2 / rl; - result.m1 = 0; - result.m2 = 0; - result.m3 = 0; - result.m4 = 0; - result.m5 = 2 / tb; - result.m6 = 0; - result.m7 = 0; - result.m8 = 0; - result.m9 = 0; - result.m10 = -2 / fn; - result.m11 = 0; - result.m12 = -(left + right) / rl; - result.m13 = -(top + bottom) / tb; - result.m14 = -(far + near) / fn; - result.m15 = 1; + result.m0 = 2.0f/rl; + result.m1 = 0.0f; + result.m2 = 0.0f; + result.m3 = 0.0f; + result.m4 = 0.0f; + result.m5 = 2.0f/tb; + result.m6 = 0.0f; + result.m7 = 0.0f; + result.m8 = 0.0f; + result.m9 = 0.0f; + result.m10 = -2.0f/fn; + result.m11 = 0.0f; + result.m12 = -(left + right)/rl; + result.m13 = -(top + bottom)/tb; + result.m14 = -(far + near)/fn; + result.m15 = 1.0f; return result; } @@ -789,19 +826,19 @@ RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up) result.m0 = x.x; result.m1 = x.y; result.m2 = x.z; - result.m3 = -((x.x * eye.x) + (x.y * eye.y) + (x.z * eye.z)); + result.m3 = -((x.x*eye.x) + (x.y*eye.y) + (x.z*eye.z)); result.m4 = y.x; result.m5 = y.y; result.m6 = y.z; - result.m7 = -((y.x * eye.x) + (y.y * eye.y) + (y.z * eye.z)); + result.m7 = -((y.x*eye.x) + (y.y*eye.y) + (y.z*eye.z)); result.m8 = z.x; result.m9 = z.y; result.m10 = z.z; - result.m11 = -((z.x * eye.x) + (z.y * eye.y) + (z.z * eye.z)); - result.m12 = 0; - result.m13 = 0; - result.m14 = 0; - result.m15 = 1; + result.m11 = -((z.x*eye.x) + (z.y*eye.y) + (z.z*eye.z)); + result.m12 = 0.0f; + result.m13 = 0.0f; + result.m14 = 0.0f; + result.m15 = 1.0f; return result; } @@ -834,9 +871,9 @@ RMDEF void QuaternionNormalize(Quaternion *q) length = QuaternionLength(*q); - if (length == 0) length = 1; + if (length == 0.0f) length = 1.0f; - ilength = 1.0/length; + ilength = 1.0f/length; q->x *= ilength; q->y *= ilength; @@ -882,8 +919,8 @@ RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) } else { - float ratioA = sin((1 - amount)*halfTheta) / sinHalfTheta; - float ratioB = sin(amount*halfTheta) / sinHalfTheta; + float ratioA = sin((1 - amount)*halfTheta)/sinHalfTheta; + float ratioB = sin(amount*halfTheta)/sinHalfTheta; result.x = (q1.x*ratioA + q2.x*ratioB); result.y = (q1.y*ratioA + q2.y*ratioB); @@ -902,15 +939,15 @@ RMDEF Quaternion QuaternionFromMatrix(Matrix matrix) float trace = MatrixTrace(matrix); - if (trace > 0) + if (trace > 0.0f) { - float s = (float)sqrt(trace + 1) * 2; - float invS = 1 / s; + float s = (float)sqrt(trace + 1)*2.0f; + float invS = 1.0f/s; - result.w = s * 0.25; - result.x = (matrix.m6 - matrix.m9) * invS; - result.y = (matrix.m8 - matrix.m2) * invS; - result.z = (matrix.m1 - matrix.m4) * invS; + result.w = s*0.25f; + result.x = (matrix.m6 - matrix.m9)*invS; + result.y = (matrix.m8 - matrix.m2)*invS; + result.z = (matrix.m1 - matrix.m4)*invS; } else { @@ -918,33 +955,33 @@ RMDEF Quaternion QuaternionFromMatrix(Matrix matrix) if (m00 > m11 && m00 > m22) { - float s = (float)sqrt(1 + m00 - m11 - m22) * 2; - float invS = 1 / s; + float s = (float)sqrt(1.0f + m00 - m11 - m22)*2.0f; + float invS = 1.0f/s; - result.w = (matrix.m6 - matrix.m9) * invS; - result.x = s * 0.25; - result.y = (matrix.m4 + matrix.m1) * invS; - result.z = (matrix.m8 + matrix.m2) * invS; + result.w = (matrix.m6 - matrix.m9)*invS; + result.x = s*0.25f; + result.y = (matrix.m4 + matrix.m1)*invS; + result.z = (matrix.m8 + matrix.m2)*invS; } else if (m11 > m22) { - float s = (float)sqrt(1 + m11 - m00 - m22) * 2; - float invS = 1 / s; + float s = (float)sqrt(1.0f + m11 - m00 - m22)*2.0f; + float invS = 1.0f/s; - result.w = (matrix.m8 - matrix.m2) * invS; - result.x = (matrix.m4 + matrix.m1) * invS; - result.y = s * 0.25; - result.z = (matrix.m9 + matrix.m6) * invS; + result.w = (matrix.m8 - matrix.m2)*invS; + result.x = (matrix.m4 + matrix.m1)*invS; + result.y = s*0.25f; + result.z = (matrix.m9 + matrix.m6)*invS; } else { - float s = (float)sqrt(1 + m22 - m00 - m11) * 2; - float invS = 1 / s; + float s = (float)sqrt(1.0f + m22 - m00 - m11)*2.0f; + float invS = 1.0f/s; - result.w = (matrix.m1 - matrix.m4) * invS; - result.x = (matrix.m8 + matrix.m2) * invS; - result.y = (matrix.m9 + matrix.m6) * invS; - result.z = s * 0.25; + result.w = (matrix.m1 - matrix.m4)*invS; + result.x = (matrix.m8 + matrix.m2)*invS; + result.y = (matrix.m9 + matrix.m6)*invS; + result.z = s*0.25f; } } @@ -974,22 +1011,22 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q) float wy = w*y2; float wz = w*z2; - result.m0 = 1 - (yy + zz); + result.m0 = 1.0f - (yy + zz); result.m1 = xy - wz; result.m2 = xz + wy; - result.m3 = 0; + result.m3 = 0.0f; result.m4 = xy + wz; - result.m5 = 1 - (xx + zz); + result.m5 = 1.0f - (xx + zz); result.m6 = yz - wx; - result.m7 = 0; + result.m7 = 0.0f; result.m8 = xz - wy; result.m9 = yz + wx; - result.m10 = 1 - (xx + yy); - result.m11 = 0; - result.m12 = 0; - result.m13 = 0; - result.m14 = 0; - result.m15 = 1; + result.m10 = 1.0f - (xx + yy); + result.m11 = 0.0f; + result.m12 = 0.0f; + result.m13 = 0.0f; + result.m14 = 0.0f; + result.m15 = 1.0f; return result; } @@ -998,17 +1035,17 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q) // NOTE: angle must be provided in radians RMDEF Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis) { - Quaternion result = { 0, 0, 0, 1 }; + Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; - if (VectorLength(axis) != 0.0) + if (VectorLength(axis) != 0.0f) - angle *= 0.5; + angle *= 0.5f; VectorNormalize(&axis); - result.x = axis.x * (float)sin(angle); - result.y = axis.y * (float)sin(angle); - result.z = axis.z * (float)sin(angle); + result.x = axis.x*(float)sin(angle); + result.y = axis.y*(float)sin(angle); + result.z = axis.z*(float)sin(angle); result.w = (float)cos(angle); QuaternionNormalize(&result); @@ -1021,23 +1058,23 @@ RMDEF void QuaternionToAxisAngle(Quaternion q, float *outAngle, Vector3 *outAxis { if (fabs(q.w) > 1.0f) QuaternionNormalize(&q); - Vector3 resAxis = { 0, 0, 0 }; - float resAngle = 0; + Vector3 resAxis = { 0.0f, 0.0f, 0.0f }; + float resAngle = 0.0f; - resAngle = 2.0f * (float)acos(q.w); - float den = (float)sqrt(1.0 - q.w * q.w); + resAngle = 2.0f*(float)acos(q.w); + float den = (float)sqrt(1.0f - q.w*q.w); if (den > 0.0001f) { - resAxis.x = q.x / den; - resAxis.y = q.y / den; - resAxis.z = q.z / den; + resAxis.x = q.x/den; + resAxis.y = q.y/den; + resAxis.z = q.z/den; } else { // This occurs when the angle is zero. // Not a problem: just set an arbitrary normalized axis. - resAxis.x = 1.0; + resAxis.x = 1.0f; } *outAxis = resAxis; @@ -1058,5 +1095,6 @@ RMDEF void QuaternionTransform(Quaternion *q, Matrix mat) q->w = mat.m3*x + mat.m7*y + mat.m11*z + mat.m15*w; } -#endif // RAYMATH_DEFINE -#endif // RAYMATH_H \ No newline at end of file +#endif // RAYMATH_IMPLEMENTATION + +#endif // RAYMATH_H \ No newline at end of file diff --git a/src/rlgl.c b/src/rlgl.c index ca08e1a2..dbcbc35f 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -32,6 +32,8 @@ #include // Declares malloc() and free() for memory management, rand() #include // Declares strcmp(), strlen(), strtok() +#include "raymath.h" // Required for Vector3 and Matrix functions + #if defined(GRAPHICS_API_OPENGL_11) #ifdef __APPLE__ // OpenGL include for OSX #include diff --git a/src/rlgl.h b/src/rlgl.h index 066e0339..fbece962 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -37,11 +37,12 @@ #endif #if defined(RLGL_STANDALONE) - #define RAYMATH_STANDALONE + #define RAYMATH_IMPLEMENTATION // Use raymath as a header-only library (includes implementation) + #define RAYMATH_EXTERN_INLINE // Compile raymath functions as static inline (remember, it's a compiler hint) + #define RAYMATH_STANDALONE // Not dependent on raylib.h structs: Vector3, Matrix + #include "raymath.h" // Required for Vector3 and Matrix functions #endif -#include "raymath.h" // Required for data type Matrix and Matrix functions - // Select desired OpenGL version // NOTE: Those preprocessor defines are only used on rlgl module, // if OpenGL version is required by any other module, it uses rlGetVersion() @@ -92,7 +93,7 @@ typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode; typedef enum { OPENGL_11 = 1, OPENGL_33, OPENGL_ES_20 } GlVersion; -#ifdef RLGL_STANDALONE +#if defined(RLGL_STANDALONE) #ifndef __cplusplus // Boolean type typedef enum { false, true } bool; -- cgit v1.2.3 From c5663ca015e550ab8e2a43c10fa72db0aab7cac8 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Wed, 20 Jan 2016 19:09:48 +0100 Subject: Some formatting tweaks --- examples/physics_basic_rigidbody.c | 24 +++++++++++++----------- examples/physics_rigidbody_force.c | 37 ++++++++++++++++++++----------------- src/physac.c | 6 +++--- src/physac.h | 3 ++- src/raylib.h | 8 ++++---- 5 files changed, 42 insertions(+), 36 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/physics_basic_rigidbody.c b/examples/physics_basic_rigidbody.c index 17d6564f..b82fe638 100644 --- a/examples/physics_basic_rigidbody.c +++ b/examples/physics_basic_rigidbody.c @@ -32,28 +32,30 @@ int main() 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}}; + 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}); + AddCollider(PLAYER_INDEX, (Collider){true, COLLIDER_RECTANGLE, (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}); + AddCollider(PLAYER_INDEX + 1, (Collider){true, COLLIDER_RECTANGLE, (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; + float jumpForce = 5.0f; + + SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop @@ -67,7 +69,7 @@ int main() ApplyPhysics(PLAYER_INDEX, &player.position); // Check jump button input - if(IsKeyDown(KEY_SPACE) && GetRigidbody(PLAYER_INDEX).isGrounded) + 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}); @@ -77,12 +79,12 @@ int main() } // Check movement buttons input - if(IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) + 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)) + 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}); @@ -110,12 +112,12 @@ int main() 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) + if (worldPhysics.debug) { // Draw every internal physics stored collider if it is active - for(int i = 0; i < 2; i++) + for (int i = 0; i < 2; i++) { - if(GetCollider(i).enabled) + if (GetCollider(i).enabled) { DrawRectangleLines(GetCollider(i).bounds.x, GetCollider(i).bounds.y, GetCollider(i).bounds.width, GetCollider(i).bounds.height, GREEN); } diff --git a/examples/physics_rigidbody_force.c b/examples/physics_rigidbody_force.c index 726e7c67..3ac560c5 100644 --- a/examples/physics_rigidbody_force.c +++ b/examples/physics_rigidbody_force.c @@ -11,11 +11,11 @@ #include "raylib.h" -#define MAX_OBJECTS 5 -#define OBJECTS_OFFSET 150 +#define MAX_OBJECTS 5 +#define OBJECTS_OFFSET 150 -#define FORCE_INTENSITY 250.0f // Customize by user -#define FORCE_RADIUS 100 // Customize by user +#define FORCE_INTENSITY 250.0f // Customize by user +#define FORCE_RADIUS 100 // Customize by user int main() { @@ -25,7 +25,7 @@ int main() 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 @@ -36,17 +36,20 @@ int main() // Objects initialization Transform objects[MAX_OBJECTS]; - for(int i = 0; i < MAX_OBJECTS; i++) + + 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}); + AddCollider(i, (Collider){true, COLLIDER_RECTANGLE, (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}); + AddCollider(MAX_OBJECTS, (Collider){true, COLLIDER_RECTANGLE, (Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, 0}); + + SetTargetFPS(60); //-------------------------------------------------------------------------------------- // Main game loop @@ -57,19 +60,19 @@ int main() // 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++) + for (int i = 0; i < MAX_OBJECTS; i++) { ApplyPhysics(i, &objects[i].position); } // Check foce button input - if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { AddForceAtPosition(GetMousePosition(), FORCE_INTENSITY, FORCE_RADIUS); } // Check debug mode toggle button input - if(IsKeyPressed(KEY_P)) + if (IsKeyPressed(KEY_P)) { // Update program physics value worldPhysics.debug = !worldPhysics.debug; @@ -86,21 +89,21 @@ int main() ClearBackground(RAYWHITE); // Check if debug mode is enabled - if(worldPhysics.debug) + if (worldPhysics.debug) { // Draw every internal physics stored collider if it is active (floor included) - for(int i = 0; i < MAX_OBJECTS + 1; i++) + for (int i = 0; i < MAX_OBJECTS + 1; i++) { - if(GetCollider(i).enabled) + 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) + 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)) + 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); } @@ -114,7 +117,7 @@ int main() else { // Draw objects - for(int i = 0; i < MAX_OBJECTS; i++) + 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); } diff --git a/src/physac.c b/src/physac.c index 6e3b6e61..6dfdbb49 100644 --- a/src/physac.c +++ b/src/physac.c @@ -183,9 +183,9 @@ void ApplyPhysics(int index, Vector2 *position) { if (colliders[index].enabled && colliders[j].enabled) { - if (colliders[index].type == RectangleCollider) + if (colliders[index].type == COLLIDER_RECTANGLE) { - if (colliders[j].type == RectangleCollider) + if (colliders[j].type == COLLIDER_RECTANGLE) { if (CheckCollisionRecs(colliders[index].bounds, colliders[j].bounds)) { @@ -207,7 +207,7 @@ void ApplyPhysics(int index, Vector2 *position) } else { - if (colliders[j].type == RectangleCollider) + if (colliders[j].type == COLLIDER_RECTANGLE) { if (CheckCollisionCircleRec((Vector2){colliders[index].bounds.x, colliders[index].bounds.y}, colliders[index].radius, colliders[j].bounds)) { diff --git a/src/physac.h b/src/physac.h index 558673ef..a1501ee3 100644 --- a/src/physac.h +++ b/src/physac.h @@ -32,7 +32,8 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -typedef enum { RectangleCollider, CircleCollider } ColliderType; +// Collider types +typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE, COLLIDER_CAPSULE } ColliderType; // Physics struct typedef struct Physics { diff --git a/src/raylib.h b/src/raylib.h index 0a768fe4..5798d907 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -463,12 +463,12 @@ typedef struct { typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON } CameraMode; // Collider types -typedef enum { RectangleCollider, CircleCollider } ColliderType; +typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE, COLLIDER_CAPSULE } ColliderType; // Physics struct typedef struct Physics { bool enabled; - bool debug; // Should be used by programmer for testing purposes + bool debug; // Should be used by programmer for testing purposes Vector2 gravity; } Physics; @@ -496,8 +496,8 @@ typedef struct Rigidbody { typedef struct Collider { bool enabled; ColliderType type; - Rectangle bounds; // Just used for RectangleCollider type - int radius; // Just used for CircleCollider type + Rectangle bounds; // Used for COLLIDER_RECTANGLE and COLLIDER_CAPSULE + int radius; // Used for COLLIDER_CIRCLE and COLLIDER_CAPSULE } Collider; #ifdef __cplusplus -- cgit v1.2.3 From fcd30c5649f28d0d9c867712898fc5537f176c85 Mon Sep 17 00:00:00 2001 From: victorfisac Date: Wed, 20 Jan 2016 19:28:47 +0100 Subject: Added ray-sphere collision detection --- src/models.c | 37 ++++++++++++++++++++++++++++++++++++- src/raylib.h | 2 ++ 2 files changed, 38 insertions(+), 1 deletion(-) (limited to 'src/raylib.h') diff --git a/src/models.c b/src/models.c index 3d228a30..80d9a13a 100644 --- a/src/models.c +++ b/src/models.c @@ -1341,7 +1341,42 @@ bool CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius { bool collision = false; - // TODO: implement collision... + Vector3 raySpherePos = VectorSubtract(spherePosition, ray.position); + float distance = VectorLength(raySpherePos); + float vector = VectorDotProduct(raySpherePos, ray.direction); + float d = sphereRadius*sphereRadius - (distance*distance - vector*vector); + + if(d >= 0.0f) collision = true; + + return collision; +} + +// Detect collision between ray and sphere with extended parameters and collision point detection +bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius, Vector3 *collisionPoint) +{ + bool collision = false; + + Vector3 raySpherePos = VectorSubtract(spherePosition, ray.position); + float distance = VectorLength(raySpherePos); + float vector = VectorDotProduct(raySpherePos, ray.direction); + float d = sphereRadius*sphereRadius - (distance*distance - vector*vector); + + if(d >= 0.0f) collision = true; + + // Calculate collision point + Vector3 offset = ray.direction; + float collisionDistance = 0; + + // Check if ray origin is inside the sphere to calculate the correct collision point + if(distance < sphereRadius) collisionDistance = vector + sqrt(d); + else collisionDistance = vector - sqrt(d); + + VectorScale(&offset, collisionDistance); + Vector3 cPoint = VectorAdd(ray.position, offset); + + collisionPoint->x = cPoint.x; + collisionPoint->y = cPoint.y; + collisionPoint->z = cPoint.z; return collision; } diff --git a/src/raylib.h b/src/raylib.h index 5798d907..bebf4bc5 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -770,6 +770,8 @@ 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 CheckCollisionRaySphere(Ray ray, Vector3 spherePosition, float sphereRadius); // Detect collision between ray and sphere +bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadius, Vector3 *collisionPoint); // Detect collision between ray and sphere with extended parameters and collision point detection 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 -- cgit v1.2.3 From 6e9d3eb0f99c8ce00b769dbd03cc011216b97068 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 23 Jan 2016 12:37:42 +0100 Subject: Review comments --- src/raylib.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index bebf4bc5..49a320d4 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -7,10 +7,10 @@ * Features: * Library written in plain C code (C99) * Uses C# PascalCase/camelCase notation -* Hardware accelerated with OpenGL (1.1, 3.3+ or ES2) +* Hardware accelerated with OpenGL (1.1, 3.3 or ES2) * Unique OpenGL abstraction layer [rlgl] -* Powerful fonts module with SpriteFonts support -* Multiple textures support, including DDS and mipmaps generation +* Powerful fonts module with SpriteFonts support (including AngelCode fonts and TTF) +* Multiple textures support, including compressed formats and mipmaps generation * Basic 3d support for Shapes, Models, Heightmaps and Billboards * Powerful math module for Vector and Matrix operations [raymath] * Audio loading and playing with streaming support (WAV and OGG) @@ -18,20 +18,21 @@ * * Used external libs: * GLFW3 (www.glfw.org) for window/context management and input -* GLEW for OpenGL extensions loading (3.3+ and ES2) +* GLAD for OpenGL extensions loading (3.3 Core profile) * stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC) * stb_image_write (Sean Barret) for image writting (PNG) * stb_vorbis (Sean Barret) for ogg audio loading +* stb_truetype (Sean Barret) for ttf fonts loading * OpenAL Soft for audio device/context management * tinfl for data decompression (DEFLATE algorithm) * * Some design decisions: -* 32bit Colors - All defined color are always RGBA -* SpriteFonts - All loaded sprite-font images are converted to RGBA and POT textures +* 32bit Colors - All defined color are always RGBA (struct Color is 4 byte) * One custom default font is loaded automatically when InitWindow() -* If using OpenGL 3.3+ or ES2, one default shader is loaded automatically (internally defined) +* If using OpenGL 3.3 or ES2, several vertex buffers (VAO/VBO) are created to manage lines-triangles-quads +* If using OpenGL 3.3 or ES2, two default shaders are loaded automatically (internally defined) * -* -- LICENSE (raylib v1.2, September 2014) -- +* -- LICENSE -- * * raylib is licensed under an unmodified zlib/libpng license, which is an OSI-certified, * BSD-like license that allows static linking with closed source software: -- cgit v1.2.3 From 08da91047e8a2c593c3bc40b31c4796ae6cbb26d Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 23 Jan 2016 13:22:13 +0100 Subject: Some code tweaks --- src/audio.c | 17 +++++------------ src/core.c | 2 ++ src/models.c | 2 +- src/raylib.h | 2 +- src/shapes.c | 4 ++-- 5 files changed, 11 insertions(+), 16 deletions(-) (limited to 'src/raylib.h') diff --git a/src/audio.c b/src/audio.c index 6313c9dc..e40fdd41 100644 --- a/src/audio.c +++ b/src/audio.c @@ -166,15 +166,8 @@ void CloseAudioDevice(void) // Load sound to memory Sound LoadSound(char *fileName) { - Sound sound; - Wave wave; - - // Init some default values for wave... - wave.data = NULL; - wave.dataSize = 0; - wave.sampleRate = 0; - wave.bitsPerSample = 0; - wave.channels = 0; + Sound sound = { 0 }; + Wave wave = { 0 }; // NOTE: The entire file is loaded to memory to play it all at once (no-streaming) @@ -236,7 +229,7 @@ Sound LoadSound(char *fileName) // Load sound from wave data Sound LoadSoundFromWave(Wave wave) { - Sound sound; + Sound sound = { 0 }; if (wave.data != NULL) { @@ -290,7 +283,7 @@ Sound LoadSoundFromWave(Wave wave) Sound LoadSoundFromRES(const char *rresName, int resId) { // NOTE: rresName could be directly a char array with all the data!!! --> TODO - Sound sound; + Sound sound = { 0 }; #if defined(AUDIO_STANDALONE) TraceLog(WARNING, "Sound loading from rRES resource file not supported on standalone mode"); @@ -791,7 +784,7 @@ static Wave LoadWAV(const char *fileName) WaveFormat waveFormat; WaveData waveData; - Wave wave; + Wave wave = { 0 }; FILE *wavFile; wavFile = fopen(fileName, "rb"); diff --git a/src/core.c b/src/core.c index 9b068300..7a5de04e 100644 --- a/src/core.c +++ b/src/core.c @@ -1230,7 +1230,9 @@ Vector2 GetTouchPosition(void) return position; } +#endif +#if defined(PLATFORM_ANDROID) // Detect if a button has been pressed once bool IsButtonPressed(int button) { diff --git a/src/models.c b/src/models.c index 80d9a13a..e90f455a 100644 --- a/src/models.c +++ b/src/models.c @@ -557,7 +557,7 @@ void DrawGizmo(Vector3 position) // Load a 3d model (from file) Model LoadModel(const char *fileName) { - Model model; + Model model = { 0 }; Mesh mesh = { 0 }; // NOTE: Initialize default data for model in case loading fails, maybe a cube? diff --git a/src/raylib.h b/src/raylib.h index 49a320d4..73200556 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -18,7 +18,7 @@ * * Used external libs: * GLFW3 (www.glfw.org) for window/context management and input -* GLAD for OpenGL extensions loading (3.3 Core profile) +* GLAD for OpenGL extensions loading (3.3 Core profile, only PLATFORM_DESKTOP) * stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA, PSD, GIF, HDR, PIC) * stb_image_write (Sean Barret) for image writting (PNG) * stb_vorbis (Sean Barret) for ogg audio loading diff --git a/src/shapes.c b/src/shapes.c index a4761536..3b4be071 100644 --- a/src/shapes.c +++ b/src/shapes.c @@ -397,8 +397,8 @@ bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec) 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(center.x - recCenterX); + float dy = fabs(center.y - recCenterY); if (dx > (rec.width/2 + radius)) { return false; } if (dy > (rec.height/2 + radius)) { return false; } -- cgit v1.2.3 From 41959eeae10d7d01fbd2abc19ccae4fc65aae031 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 24 Jan 2016 19:17:08 +0100 Subject: Added support for mouse gestures (need testing) Mouse input is interpreted as touches to allow mouse gestures detection... and get an unified inputs system for all platforms! --- src/core.c | 42 ++++++++++++++++++++++++++++++++++++------ src/raylib.h | 5 +++-- 2 files changed, 39 insertions(+), 8 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index 7a5de04e..811f082a 100644 --- a/src/core.c +++ b/src/core.c @@ -1197,23 +1197,31 @@ bool IsGamepadButtonUp(int gamepad, int button) } #endif -#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) // Returns touch position X int GetTouchX(void) { +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) return (int)touchPosition.x; +#else // PLATFORM_DESKTOP, PLATFORM_RPI + return GetMouseX(); +#endif } // Returns touch position Y int GetTouchY(void) { +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) return (int)touchPosition.y; +#else // PLATFORM_DESKTOP, PLATFORM_RPI + return GetMouseY(); +#endif } // Returns touch position XY // TODO: touch position should be scaled depending on display size and render size Vector2 GetTouchPosition(void) { +#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) Vector2 position = touchPosition; if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) @@ -1227,10 +1235,12 @@ Vector2 GetTouchPosition(void) position.x = position.x*((float)renderWidth/(float)displayWidth) - renderOffsetX/2; position.y = position.y*((float)renderHeight/(float)displayHeight) - renderOffsetY/2; } +#else // PLATFORM_DESKTOP, PLATFORM_RPI + Vector2 position = GetMousePosition(); +#endif return position; } -#endif #if defined(PLATFORM_ANDROID) // Detect if a button has been pressed once @@ -1633,6 +1643,28 @@ static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, i static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods) { currentMouseState[button] = action; + + // TODO: Test mouse gestures + +#define ENABLE_MOUSE_GESTURES +#if defined(ENABLE_MOUSE_GESTURES) + // Process mouse events as touches to be able to use mouse-gestures + GestureEvent gestureEvent; + + // Register touch actions + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_DOWN; + else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_MOVE; + else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_UP; + + // Register touch points count + gestureEvent.pointCount = 1; + + // Register touch points position, only one point registered + gestureEvent.position[0] = GetMousePosition(); + + // Gesture data is sent to gestures system for processing + ProcessGestureEvent(gestureEvent); +#endif } // GLFW3 Char Key Callback, runs on key pressed (get char value) @@ -1976,11 +2008,9 @@ static bool GetMouseButtonStatus(int button) // Poll (store) all input events static void PollInputEvents(void) { -#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) - - // TODO: Remove this requirement... + // NOTE: Gestures update must be called every frame to reset gestures correctly + // because ProcessGestureEvent() is just called on an event, not every frame UpdateGestures(); -#endif #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) // Mouse input polling diff --git a/src/raylib.h b/src/raylib.h index 73200556..41fa3f7d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -598,13 +598,15 @@ bool IsGamepadButtonReleased(int gamepad, int button); // Detect if a gamepad b bool IsGamepadButtonUp(int gamepad, int button); // Detect if a gamepad button is NOT being pressed #endif -#if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) 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_ANDROID) 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 +#endif //------------------------------------------------------------------------------------ // Gestures and Touch Handling Functions (Module: gestures) @@ -621,7 +623,6 @@ Vector2 GetGestureDragVector(void); // Get gesture drag vect int GetGestureHoldDuration(void); // Get gesture hold time in frames float GetGesturePinchDelta(void); // Get gesture pinch delta float GetGesturePinchAngle(void); // Get gesture pinch angle -#endif //------------------------------------------------------------------------------------ // Camera System Functions (Module: camera) -- cgit v1.2.3 From 3113a20390a1e4d81e9f832e7aa1d022afdb56d1 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 25 Jan 2016 11:12:31 +0100 Subject: Added bounding box calculation --- src/models.c | 29 ++++++++++++++++++----------- src/raylib.h | 2 ++ src/raymath.h | 26 ++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 11 deletions(-) (limited to 'src/raylib.h') diff --git a/src/models.c b/src/models.c index e90f455a..2d78963e 100644 --- a/src/models.c +++ b/src/models.c @@ -1275,6 +1275,20 @@ void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle sourceRec, Vec rlDisableTexture(); } +// Draw a bounding box with wires +void DrawBoundingBox(BoundingBox box) +{ + Vector3 size; + + size.x = fabsf(box.max.x - box.min.x); + size.y = fabsf(box.max.y - box.min.y); + size.z = fabsf(box.max.z - box.min.z); + + Vector3 center = { box.min.x + size.x/2.0f, box.min.y + size.y/2.0f, box.min.z + size.z/2.0f }; + + DrawCubeWires(center, size.x, size.y, size.z, GREEN); +} + // Detect collision between two spheres bool CheckCollisionSpheres(Vector3 centerA, float radiusA, Vector3 centerB, float radiusB) { @@ -1401,10 +1415,8 @@ bool CheckCollisionRayBox(Ray ray, Vector3 minBBox, Vector3 maxBBox) return collision; } -// TODO: Useful function to check collision area? -//BoundingBox GetCollisionArea(BoundingBox box1, BoundingBox box2) - // Calculate mesh bounding box limits +// NOTE: minVertex and maxVertex should be transformed by model transform matrix (position, scale, rotate) BoundingBox CalculateBoundingBox(Mesh mesh) { // Get min and max vertex to construct bounds (AABB) @@ -1413,15 +1425,10 @@ BoundingBox CalculateBoundingBox(Mesh mesh) 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]); + minVertex = VectorMin(minVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); + maxVertex = VectorMax(maxVertex, (Vector3){ mesh.vertices[i*3], mesh.vertices[i*3 + 1], mesh.vertices[i*3 + 2] }); } - - // 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; diff --git a/src/raylib.h b/src/raylib.h index 41fa3f7d..097c8865 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -765,10 +765,12 @@ void DrawModel(Model model, Vector3 position, float scale, Color tint); 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 DrawBoundingBox(BoundingBox box); // Draw bounding box (wires) 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 +BoundingBox CalculateBoundingBox(Mesh mesh); // Calculate mesh bounding box limits 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 diff --git a/src/raymath.h b/src/raymath.h index f5448504..46fab356 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -126,6 +126,8 @@ RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount); // Calculate lin RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal RMDEF void VectorTransform(Vector3 *v, Matrix mat); // Transforms a Vector3 by a given Matrix RMDEF Vector3 VectorZero(void); // Return a Vector3 init to zero +RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2); // Return min value for each pair of components +RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2); // Return max value for each pair of components //------------------------------------------------------------------------------------ // Functions Declaration to work with Matrix @@ -361,6 +363,30 @@ RMDEF Vector3 VectorZero(void) return zero; } +// Return min value for each pair of components +RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2) +{ + Vector3 result; + + result.x = fminf(vec1.x, vec2.x); + result.y = fminf(vec1.y, vec2.y); + result.z = fminf(vec1.z, vec2.z); + + return result; +} + +// Return max value for each pair of components +RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2) +{ + Vector3 result; + + result.x = fmaxf(vec1.x, vec2.x); + result.y = fmaxf(vec1.y, vec2.y); + result.z = fmaxf(vec1.z, vec2.z); + + return result; +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Matrix math //---------------------------------------------------------------------------------- -- cgit v1.2.3 From 99f99bea470ace9577950db8976aa092a678635d Mon Sep 17 00:00:00 2001 From: raysan5 Date: Mon, 25 Jan 2016 13:54:09 +0100 Subject: Simplified shader matrix uniforms --- src/raylib.h | 42 +++++++++++++++++++++--------------------- src/rlgl.c | 25 ++++++++++++++----------- 2 files changed, 35 insertions(+), 32 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 097c8865..48aeda54 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -358,12 +358,31 @@ typedef struct Shader { int mapSpecularLoc; // Specular map texture uniform location point (fragment shader) } Shader; +// Material type +// TODO: Redesign material-shaders-textures system +typedef struct Material { + //Shader shader; + + //Texture2D texDiffuse; // Diffuse texture + //Texture2D texNormal; // Normal texture + //Texture2D texSpecular; // Specular texture + + Color colDiffuse; + Color colAmbient; + Color colSpecular; + + float glossiness; + float normalDepth; +} Material; + // 3d Model type +// TODO: Replace shader/testure by material typedef struct Model { Mesh mesh; Matrix transform; Texture2D texture; // Only for OpenGL 1.1, on newer versions this should be in the shader Shader shader; + //Material material; } Model; // Ray type (useful for raycast) @@ -387,26 +406,6 @@ 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 { @@ -535,11 +534,12 @@ void BeginDrawing(void); // Setup drawing can 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 Begin3dMode(Camera camera); // 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); // Returns a ray trace from mouse position Vector2 WorldToScreen(Vector3 position, Camera camera); // Returns the screen space position from a 3d world space position +Matrix GetCameraMatrix(Camera camera); // Returns camera transform matrix (view matrix) void SetTargetFPS(int fps); // Set target FPS (maximum) float GetFPS(void); // Returns current FPS diff --git a/src/rlgl.c b/src/rlgl.c index ec909385..49300054 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1477,8 +1477,8 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r // 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.material.shader.modelLoc, 1, false, MatrixToFloat(matModel)); + //glUniformMatrix4fv(model.material.shader.viewLoc, 1, false, MatrixToFloat(matView)); glUniformMatrix4fv(model.shader.mvpLoc, 1, false, MatrixToFloat(matMVP)); @@ -2201,9 +2201,6 @@ Shader LoadShader(char *vsFileName, char *fsFileName) // Get handles to GLSL uniform locations (vertex shader) 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, "fragTintColor"); @@ -2503,6 +2500,18 @@ void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size) #endif } +// Set shader uniform value (matrix 4x4) +void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat) +{ +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + glUseProgram(shader.id); + + glUniformMatrix4fv(uniformLoc, 1, false, MatrixToFloat(mat)); + + glUseProgram(0); +#endif +} + // Default diffuse shader map texture assignment void SetShaderMapDiffuse(Shader *shader, Texture2D texture) { @@ -2741,9 +2750,6 @@ static Shader LoadDefaultShader(void) // Get handles to GLSL uniform locations (vertex shader) 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; @@ -2822,9 +2828,6 @@ static Shader LoadSimpleShader(void) // Get handles to GLSL uniform locations (vertex shader) 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, "fragTintColor"); -- cgit v1.2.3 From 13925f7bd4ad6b71f03a24024057819eb1032e05 Mon Sep 17 00:00:00 2001 From: Constantine Tarasenkov Date: Fri, 29 Jan 2016 09:09:18 +0300 Subject: Add functions to disable and enable cursor --- src/core.c | 18 ++++++++++++++++++ src/raylib.h | 2 ++ 2 files changed, 20 insertions(+) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index 8b36e1ea..cf6fcf33 100644 --- a/src/core.c +++ b/src/core.c @@ -1097,6 +1097,24 @@ void ShowCursor() cursorHidden = false; } +// Disable mouse cursor +void DisableCursor() +{ +#if defined(PLATFORM_DESKTOP) + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); +#endif + cursorHidden = true; +} + +// Enable mouse cursor +void EnableCursor() +{ +#if defined(PLATFORM_DESKTOP) + glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); +#endif + cursorHidden = false; +} + // Check if mouse cursor is hidden bool IsCursorHidden() { diff --git a/src/raylib.h b/src/raylib.h index 48aeda54..6c1a8999 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -586,6 +586,8 @@ int GetMouseWheelMove(void); // Returns mouse wheel m void ShowCursor(void); // Shows cursor void HideCursor(void); // Hides cursor +void EnableCursor(void); // Enables cursor +void DisableCursor(void); // Disables cursor bool IsCursorHidden(void); // Returns true if cursor is not visible #endif -- cgit v1.2.3 From 728e1715cc52fb25081f3ce17cb5b3f72f7eb218 Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 2 Feb 2016 16:43:42 +0100 Subject: Redesigned gestures system... ...and improved mouse gestures support Some testing still required... --- src/core.c | 29 +++++- src/gestures.c | 300 +++++++++++++++++++++++++++++---------------------------- src/raylib.h | 23 +++-- 3 files changed, 189 insertions(+), 163 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index cf6fcf33..1c9e16ae 100644 --- a/src/core.c +++ b/src/core.c @@ -253,6 +253,7 @@ static void InitGamepad(void); // Init raw gamepad inpu static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error static void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods); // GLFW3 Keyboard Callback, runs on key pressed static void MouseButtonCallback(GLFWwindow *window, int button, int action, int mods); // GLFW3 Mouse Button Callback, runs on mouse button pressed +static void MouseCursorPosCallback(GLFWwindow *window, double x, double y); // GLFW3 Cursor Position Callback, runs on mouse move static void CharCallback(GLFWwindow *window, unsigned int key); // GLFW3 Char Key Callback, runs on key pressed (get char value) static void ScrollCallback(GLFWwindow *window, double xoffset, double yoffset); // GLFW3 Srolling Callback, runs on mouse wheel static void CursorEnterCallback(GLFWwindow *window, int enter); // GLFW3 Cursor Enter Callback, cursor enters client area @@ -1415,6 +1416,7 @@ static void InitDisplay(int width, int height) glfwSetCursorEnterCallback(window, CursorEnterCallback); glfwSetKeyCallback(window, KeyCallback); glfwSetMouseButtonCallback(window, MouseButtonCallback); + glfwSetCursorPosCallback(window, MouseCursorPosCallback); // Track mouse position changes glfwSetCharCallback(window, CharCallback); glfwSetScrollCallback(window, ScrollCallback); glfwSetWindowIconifyCallback(window, WindowIconifyCallback); @@ -1677,7 +1679,7 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int // Register touch actions if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_DOWN; - else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_MOVE; + //else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_MOVE; else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_UP; // Register touch points count @@ -1685,7 +1687,28 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int // Register touch points position, only one point registered gestureEvent.position[0] = GetMousePosition(); + + // Gesture data is sent to gestures system for processing + ProcessGestureEvent(gestureEvent); +#endif +} + +// GLFW3 Cursor Position Callback, runs on mouse move +static void MouseCursorPosCallback(GLFWwindow *window, double x, double y) +{ +#define ENABLE_MOUSE_GESTURES +#if defined(ENABLE_MOUSE_GESTURES) + // Process mouse events as touches to be able to use mouse-gestures + GestureEvent gestureEvent; + + gestureEvent.touchAction = TOUCH_MOVE; + + // Register touch points count + gestureEvent.pointCount = 1; + // Register touch points position, only one point registered + gestureEvent.position[0] = (Vector2){ (float)x, (float)y }; + // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); #endif @@ -1934,7 +1957,7 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) // Register touch points count gestureEvent.pointCount = AMotionEvent_getPointerCount(event); - // Register touch points id DESKTOP + // Register touch points id gestureEvent.pointerId[0] = AMotionEvent_getPointerId(event, 0); gestureEvent.pointerId[1] = AMotionEvent_getPointerId(event, 1); @@ -2496,7 +2519,7 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent // Register touch points count gestureEvent.pointCount = touchEvent->numTouches; - // Register touch points id WEB + // Register touch points id gestureEvent.pointerId[0] = touchEvent->touches[0].identifier; gestureEvent.pointerId[1] = touchEvent->touches[1].identifier; diff --git a/src/gestures.c b/src/gestures.c index ea744555..59f2c5b7 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -46,7 +46,11 @@ // Defines and Macros //---------------------------------------------------------------------------------- #define FORCE_TO_SWIPE 20 -#define TAP_TIMEOUT 300 +#define FORCE_TO_DRAG 20 +#define FORCE_TO_PINCH 5 +#define TAP_TIMEOUT 300 // Time in milliseconds +#define PINCH_TIMEOUT 300 // Time in milliseconds +#define DOUBLETAP_RANGE 30 //#define MAX_TOUCH_POINTS 4 //---------------------------------------------------------------------------------- @@ -61,10 +65,6 @@ typedef enum { //---------------------------------------------------------------------------------- // 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 }; @@ -78,6 +78,21 @@ static Vector2 endDragPosition = { 0, 0 }; static Vector2 lastDragPosition = { 0, 0 }; static Vector2 dragVector = { 0, 0 }; +// Albert&Ian +static Vector2 touchDownPosition = { 0, 0 }; +static Vector2 touchDownPosition2 = { 0, 0 }; +static Vector2 touchUpPosition = { 0, 0 }; +static Vector2 moveDownPosition = { 0, 0 }; +static Vector2 moveDownPosition2 = { 0, 0 }; + +static int numTap = 0; +static int numHold = 0; +static int numPinch = 0; +static int pointCount = 0; +static int touchId = -1; + +static double eventTime = 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) @@ -95,7 +110,7 @@ static int previousGesture = GESTURE_NONE; static int currentGesture = GESTURE_NONE; // Enabled gestures flags, all gestures enabled by default -static unsigned int enabledGestures = 0b0000011111111111; +static unsigned int enabledGestures = 0b0000001111111111; //---------------------------------------------------------------------------------- // Module specific Functions Declaration @@ -105,6 +120,7 @@ static float CalculateAngle(Vector2 initialPosition, Vector2 actualPosition, flo static float VectorDistance(Vector2 v1, Vector2 v2); static float VectorDotProduct(Vector2 v1, Vector2 v2); static double GetCurrentTime(); +static float Vector2Distance(); //---------------------------------------------------------------------------------- // Module Functions Definition @@ -119,173 +135,160 @@ void ProcessGestureEvent(GestureEvent event) previousGesture = currentGesture; - switch (gestureType) - { - case TYPE_MOTIONLESS: // Detect TAP, DOUBLE_TAP and HOLD events + pointCount = event.pointCount; + + // Albert&Ian + if (pointCount < 2) + { + touchId = event.pointerId[0]; + if (event.touchAction == TOUCH_DOWN) { - if (event.touchAction == TOUCH_DOWN) + numTap++; // Tap counter + + // Detect GESTURE_DOUBLE_TAP + if ((currentGesture == GESTURE_NONE) && (numTap >= 2) && ((GetCurrentTime() - eventTime) < TAP_TIMEOUT) && (GetMagnitude(touchDownPosition, event.position[0]) < DOUBLETAP_RANGE)) { - 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; - } + currentGesture = GESTURE_DOUBLETAP; + numTap = 0; } - else if (event.touchAction == TOUCH_UP) + else // Detect GESTURE_TAP { - 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(); + numTap = 1; + currentGesture = GESTURE_TAP; } - // Begin dragging - else if (event.touchAction == TOUCH_MOVE) + + touchDownPosition = event.position[0]; + + touchUpPosition = touchDownPosition; + eventTime = GetCurrentTime(); + } + else if (event.touchAction == TOUCH_UP) + { + if (currentGesture = GESTURE_DRAG) { - 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; - } + touchUpPosition = event.position[0]; } - } break; - case TYPE_DRAG: // Detect DRAG and SWIPE events - { - // end of the drag - if (event.touchAction == TOUCH_UP) + + // Calculate for swipe + magnitude = GetMagnitude(touchDownPosition, touchUpPosition); + intensity = magnitude / (float)draggingTimeCounter; + + // Detect GESTURE_SWIPE + if ((intensity > FORCE_TO_SWIPE) && (touchId == 0)) + { + angle = CalculateAngle(touchDownPosition, touchUpPosition, magnitude); + if ((angle < 30) || (angle > 330)) currentGesture = GESTURE_SWIPE_RIGHT; // Right + else if ((angle > 30) && (angle < 120)) currentGesture = GESTURE_SWIPE_UP; // Up + else if ((angle > 120) && (angle < 210)) currentGesture = GESTURE_SWIPE_LEFT; // Left + else if ((angle > 210) && (angle < 300)) currentGesture = GESTURE_SWIPE_DOWN; // Down + else currentGesture = GESTURE_NONE; + } + else { - // 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; + currentGesture = GESTURE_NONE; } - // Update while we are dragging - else if (event.touchAction == TOUCH_MOVE) + + draggingTimeCounter = 0; + } + else if (event.touchAction == TOUCH_MOVE) + { + if (GetMagnitude(moveDownPosition, event.position[0]) > 5) eventTime = GetCurrentTime(); + moveDownPosition = event.position[0]; + + if (currentGesture == GESTURE_HOLD) { - 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; - - // Check if drag movement is less than minimum to keep it as hold state or switch to drag state - if(magnitude > FORCE_TO_SWIPE) - { - currentGesture = GESTURE_DRAG; - draggingTimeCounter++; - } - else currentGesture = GESTURE_HOLD; - } + if (numHold == 1) touchDownPosition = event.position[0]; + + numHold = 2; + + magnitude = GetMagnitude(touchDownPosition, moveDownPosition); + + // Detect GESTURE_DRAG + if (magnitude >= FORCE_TO_DRAG) currentGesture = GESTURE_DRAG; } - } break; - case TYPE_DUAL_INPUT: + + draggingTimeCounter++; + } + } + else + { + // two fingers + + if (event.touchAction == TOUCH_DOWN) + { + touchDownPosition = event.position[0]; + touchDownPosition2 = event.position[1]; + + currentGesture = GESTURE_HOLD; + } + else if (event.touchAction == TOUCH_MOVE) { - if (event.touchAction == TOUCH_UP) + magnitude = GetMagnitude(moveDownPosition, moveDownPosition2); + + touchDownPosition = moveDownPosition; + touchDownPosition2 = moveDownPosition2; + + moveDownPosition = event.position[0]; + moveDownPosition2 = event.position[1]; + + if ( (GetMagnitude(touchDownPosition, moveDownPosition) > FORCE_TO_PINCH) || (GetMagnitude(touchDownPosition2, moveDownPosition2) > FORCE_TO_PINCH)) { - if (event.pointCount == 1) - { - // Set the drag starting position - initialTapPosition = event.position[0]; - } - gestureType = TYPE_MOTIONLESS; + if ((GetMagnitude(moveDownPosition, moveDownPosition2) - magnitude) < 0) currentGesture = GESTURE_PINCH_IN; + else currentGesture = GESTURE_PINCH_OUT; } - else if (event.touchAction == TOUCH_MOVE) + else { - // 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; + currentGesture = GESTURE_HOLD; } - } break; + } + else if (event.touchAction == TOUCH_UP) + { + currentGesture = GESTURE_NONE; + } + } +} + +// Update gestures detected (must be called every frame) +void UpdateGestures(void) +{ + // NOTE: Gestures are processed through system callbacks on touch events + + // Detect GESTURE_HOLD + if (((currentGesture == GESTURE_TAP) || (currentGesture == GESTURE_DOUBLETAP)) && pointCount < 2) currentGesture = GESTURE_HOLD; + if ((GetCurrentTime() - eventTime) > TAP_TIMEOUT && (currentGesture == GESTURE_DRAG) && pointCount < 2) + { + currentGesture = GESTURE_HOLD; + numHold = 1; } + + // Detect GESTURE_NONE + if ((currentGesture == GESTURE_SWIPE_RIGHT) || (currentGesture == GESTURE_SWIPE_UP) || (currentGesture == GESTURE_SWIPE_LEFT) || (currentGesture == GESTURE_SWIPE_DOWN)) + { + currentGesture = GESTURE_NONE; + } +} + +// Calculate distance between two vectors +float Vector2Distance(Vector2 v1, Vector3 v2) +{ + float result; + + float dx = v2.x - v1.x; + float dy = v2.y - v1.y; + + result = sqrt(dx*dx + dy*dy); + + return result; } // Check if a gesture have been detected bool IsGestureDetected(void) { - if (currentGesture != GESTURE_NONE) return true; + if ((enabledGestures & currentGesture) != GESTURE_NONE) return true; else return false; } @@ -298,7 +301,7 @@ int GetGestureType(void) void SetGesturesEnabled(unsigned int gestureFlags) { - enabledGestures = enabledGestures | gestureFlags; + enabledGestures = gestureFlags; } // Get drag intensity (pixels per frame) @@ -440,6 +443,7 @@ static float VectorDotProduct(Vector2 v1, Vector2 v2) return result; } +// Time measure returned are milliseconds static double GetCurrentTime() { double time = 0; diff --git a/src/raylib.h b/src/raylib.h index 6c1a8999..a22c3f83 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -435,17 +435,17 @@ typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode; // Gestures type // NOTE: It could be used as flags to enable only some gestures typedef enum { - GESTURE_NONE = 1, - GESTURE_TAP = 2, - GESTURE_DOUBLETAP = 4, - GESTURE_HOLD = 8, - GESTURE_DRAG = 16, - GESTURE_SWIPE_RIGHT = 32, - GESTURE_SWIPE_LEFT = 64, - GESTURE_SWIPE_UP = 128, - GESTURE_SWIPE_DOWN = 256, - GESTURE_PINCH_IN = 512, - GESTURE_PINCH_OUT = 1024 + GESTURE_NONE = 0, + GESTURE_TAP = 1, + GESTURE_DOUBLETAP = 2, + GESTURE_HOLD = 4, + GESTURE_DRAG = 8, + GESTURE_SWIPE_RIGHT = 16, + GESTURE_SWIPE_LEFT = 32, + GESTURE_SWIPE_UP = 64, + GESTURE_SWIPE_DOWN = 128, + GESTURE_PINCH_IN = 256, + GESTURE_PINCH_OUT = 512 } Gestures; typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction; @@ -781,7 +781,6 @@ bool CheckCollisionRaySphereEx(Ray ray, Vector3 spherePosition, float sphereRadi 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 - //------------------------------------------------------------------------------------ // Shaders System Functions (Module: rlgl) // NOTE: This functions are useless when using OpenGL 1.1 -- cgit v1.2.3 From df5c64d0beee06df8c87a43e5341b6b98f82839f Mon Sep 17 00:00:00 2001 From: Ray Date: Tue, 2 Feb 2016 18:41:01 +0100 Subject: Functions parameters reorganize: Axis and Angle sin(), cos() functions cached and replaced by float c99 versions sinf(), cos() --- src/models.c | 12 ++++++------ src/raylib.h | 4 ++-- src/raymath.h | 47 +++++++++++++++++++++++++---------------------- src/rlgl.c | 8 ++++---- src/rlgl.h | 2 +- 5 files changed, 38 insertions(+), 35 deletions(-) (limited to 'src/raylib.h') diff --git a/src/models.c b/src/models.c index 2d78963e..91cb5813 100644 --- a/src/models.c +++ b/src/models.c @@ -1149,14 +1149,14 @@ void DrawModel(Model model, Vector3 position, float scale, Color tint) Vector3 vScale = { scale, scale, scale }; Vector3 rotationAxis = { 0.0f, 0.0f, 0.0f }; - DrawModelEx(model, position, 0.0f, rotationAxis, vScale, tint); + DrawModelEx(model, position, rotationAxis, 0.0f, vScale, tint); } // Draw a model with extended parameters -void DrawModelEx(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color tint) +void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, 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, false); + rlglDrawModel(model, position, rotationAxis, rotationAngle, scale, tint, false); } // Draw a model wires (with texture if set) @@ -1165,14 +1165,14 @@ void DrawModelWires(Model model, Vector3 position, float scale, Color color) Vector3 vScale = { scale, scale, scale }; Vector3 rotationAxis = { 0.0f, 0.0f, 0.0f }; - rlglDrawModel(model, position, 0.0f, rotationAxis, vScale, color, true); + rlglDrawModel(model, position, rotationAxis, 0.0f, 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) +void DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, 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); + rlglDrawModel(model, position, rotationAxis, rotationAngle, scale, tint, true); } // Draw a billboard diff --git a/src/raylib.h b/src/raylib.h index a22c3f83..c306518d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -764,9 +764,9 @@ void UnloadModel(Model model); void SetModelTexture(Model *model, Texture2D texture); // Link a texture to a model 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 DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, 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 DrawModelWiresEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model wires (with texture if set) with extended parameters void DrawBoundingBox(BoundingBox box); // Draw bounding box (wires) void DrawBillboard(Camera camera, Texture2D texture, Vector3 center, float size, Color tint); // Draw a billboard texture diff --git a/src/raymath.h b/src/raymath.h index 46fab356..35cee39f 100644 --- a/src/raymath.h +++ b/src/raymath.h @@ -141,7 +141,7 @@ RMDEF Matrix MatrixIdentity(void); // Returns identit RMDEF Matrix MatrixAdd(Matrix left, Matrix right); // Add two matrices RMDEF Matrix MatrixSubstract(Matrix left, Matrix right); // Substract two matrices (left - right) RMDEF Matrix MatrixTranslate(float x, float y, float z); // Returns translation matrix -RMDEF Matrix MatrixRotate(float angle, Vector3 axis); // Returns rotation matrix for an angle around an specified axis (angle in radians) +RMDEF Matrix MatrixRotate(Vector3 axis, float angle); // Returns rotation matrix for an angle around an specified axis (angle in radians) RMDEF Matrix MatrixRotateX(float angle); // Returns x-rotation matrix (angle in radians) RMDEF Matrix MatrixRotateY(float angle); // Returns y-rotation matrix (angle in radians) RMDEF Matrix MatrixRotateZ(float angle); // Returns z-rotation matrix (angle in radians) @@ -162,8 +162,8 @@ RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2); // Calcula RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float slerp); // Calculates spherical linear interpolation between two quaternions RMDEF Quaternion QuaternionFromMatrix(Matrix matrix); // Returns a quaternion for a given rotation matrix RMDEF Matrix QuaternionToMatrix(Quaternion q); // Returns a matrix for a given quaternion -RMDEF Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis); // Returns rotation quaternion for an angle and axis -RMDEF void QuaternionToAxisAngle(Quaternion q, float *outAngle, Vector3 *outAxis); // Returns the rotation angle and axis for a given quaternion +RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle); // Returns rotation quaternion for an angle and axis +RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle); // Returns the rotation angle and axis for a given quaternion RMDEF void QuaternionTransform(Quaternion *q, Matrix mat); // Transform a quaternion given a transformation matrix #ifdef __cplusplus @@ -587,7 +587,7 @@ RMDEF Matrix MatrixTranslate(float x, float y, float z) // Create rotation matrix from axis and angle // NOTE: Angle should be provided in radians -RMDEF Matrix MatrixRotate(float angle, Vector3 axis) +RMDEF Matrix MatrixRotate(Vector3 axis, float angle) { Matrix result; @@ -605,9 +605,9 @@ RMDEF Matrix MatrixRotate(float angle, Vector3 axis) z *= length; } - float s = sinf(angle); - float c = cosf(angle); - float t = 1.0f - c; + float sinres = sinf(angle); + float cosres = cosf(angle); + float t = 1.0f - cosres; // Cache some matrix values (speed optimization) float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; @@ -615,9 +615,9 @@ RMDEF Matrix MatrixRotate(float angle, Vector3 axis) float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; // Construct the elements of the rotation matrix - float b00 = x*x*t + c, b01 = y*x*t + z*s, b02 = z*x*t - y*s; - float b10 = x*y*t - z*s, b11 = y*y*t + c, b12 = z*y*t + x*s; - float b20 = x*z*t + y*s, b21 = y*z*t - x*s, b22 = z*z*t + c; + float b00 = x*x*t + cosres, b01 = y*x*t + z*sinres, b02 = z*x*t - y*sinres; + float b10 = x*y*t - z*sinres, b11 = y*y*t + cosres, b12 = z*y*t + x*sinres; + float b20 = x*z*t + y*sinres, b21 = y*z*t - x*sinres, b22 = z*z*t + cosres; // Perform rotation-specific matrix multiplication result.m0 = a00*b00 + a10*b01 + a20*b02; @@ -688,8 +688,8 @@ RMDEF Matrix MatrixRotateX(float angle) { Matrix result = MatrixIdentity(); - float cosres = (float)cos(angle); - float sinres = (float)sin(angle); + float cosres = cosf(angle); + float sinres = sinf(angle); result.m5 = cosres; result.m6 = -sinres; @@ -720,8 +720,8 @@ RMDEF Matrix MatrixRotateZ(float angle) { Matrix result = MatrixIdentity(); - float cosres = (float)cos(angle); - float sinres = (float)sin(angle); + float cosres = cosf(angle); + float sinres = sinf(angle); result.m0 = cosres; result.m1 = -sinres; @@ -946,8 +946,8 @@ RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) } else { - float ratioA = sin((1 - amount)*halfTheta)/sinHalfTheta; - float ratioB = sin(amount*halfTheta)/sinHalfTheta; + float ratioA = sinf((1 - amount)*halfTheta)/sinHalfTheta; + float ratioB = sinf(amount*halfTheta)/sinHalfTheta; result.x = (q1.x*ratioA + q2.x*ratioB); result.y = (q1.y*ratioA + q2.y*ratioB); @@ -1060,7 +1060,7 @@ RMDEF Matrix QuaternionToMatrix(Quaternion q) // Returns rotation quaternion for an angle and axis // NOTE: angle must be provided in radians -RMDEF Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis) +RMDEF Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) { Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; @@ -1069,11 +1069,14 @@ RMDEF Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis) angle *= 0.5f; VectorNormalize(&axis); + + float sinres = sinf(angle); + float cosres = cosf(angle); - result.x = axis.x*(float)sin(angle); - result.y = axis.y*(float)sin(angle); - result.z = axis.z*(float)sin(angle); - result.w = (float)cos(angle); + result.x = axis.x*sinres; + result.y = axis.y*sinres; + result.z = axis.z*sinres; + result.w = cosres; QuaternionNormalize(&result); @@ -1081,7 +1084,7 @@ RMDEF Quaternion QuaternionFromAxisAngle(float angle, Vector3 axis) } // Returns the rotation angle and axis for a given quaternion -RMDEF void QuaternionToAxisAngle(Quaternion q, float *outAngle, Vector3 *outAxis) +RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle) { if (fabs(q.w) > 1.0f) QuaternionNormalize(&q); diff --git a/src/rlgl.c b/src/rlgl.c index 49300054..48e6ac1b 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -411,7 +411,7 @@ void rlRotatef(float angleDeg, float x, float y, float z) Vector3 axis = (Vector3){ x, y, z }; VectorNormalize(&axis); - matRotation = MatrixRotate(angleDeg*DEG2RAD, axis); + matRotation = MatrixRotate(axis, angleDeg*DEG2RAD); MatrixTranspose(&matRotation); @@ -1406,13 +1406,13 @@ void rlglDrawPostpro(void) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glBindFramebuffer(GL_FRAMEBUFFER, 0); - rlglDrawModel(postproQuad, (Vector3){0,0,0}, 0.0f, (Vector3){0,0,0}, (Vector3){1.0f, 1.0f, 1.0f}, (Color){ 255, 255, 255, 255 }, false); + rlglDrawModel(postproQuad, (Vector3){0,0,0}, (Vector3){0,0,0}, 0.0f, (Vector3){1.0f, 1.0f, 1.0f}, (Color){ 255, 255, 255, 255 }, false); #endif } // Draw a 3d model // NOTE: Model transform can come within model struct -void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 rotationAxis, Vector3 scale, Color color, bool wires) +void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color color, bool wires) { #if defined (GRAPHICS_API_OPENGL_11) || defined(GRAPHICS_API_OPENGL_33) // NOTE: glPolygonMode() not available on OpenGL ES @@ -1461,7 +1461,7 @@ void rlglDrawModel(Model model, Vector3 position, float rotationAngle, Vector3 r // Calculate transformation matrix from function parameters // Get transform matrix (rotation -> scale -> translation) - Matrix matRotation = MatrixRotate(rotationAngle*DEG2RAD, rotationAxis); + Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD); Matrix matScale = MatrixScale(scale.x, scale.y, scale.z); Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z); Matrix matTransform = MatrixMultiply(MatrixMultiply(matRotation, matScale), matTranslation); diff --git a/src/rlgl.h b/src/rlgl.h index 64581db8..9e0aaaaa 100644 --- a/src/rlgl.h +++ b/src/rlgl.h @@ -262,7 +262,7 @@ void rlglInitPostpro(void); // Initialize postprocessing sys void rlglDrawPostpro(void); // Draw with postprocessing shader 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); +void rlglDrawModel(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color color, bool wires); Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view); // Get world coordinates from screen coordinates -- cgit v1.2.3 From 646f1c3f716dd817ff717d35480a744a8be46ead Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 3 Feb 2016 17:45:28 +0100 Subject: Some formating tweaks --- src/camera.c | 114 +++++++++++++++++++++++++++++------------------------------ src/camera.h | 4 +-- src/core.c | 15 ++++---- src/raylib.h | 4 +-- src/rlgl.c | 2 +- 5 files changed, 70 insertions(+), 69 deletions(-) (limited to 'src/raylib.h') diff --git a/src/camera.c b/src/camera.c index 1e7ac2ff..6539da5f 100644 --- a/src/camera.c +++ b/src/camera.c @@ -36,44 +36,44 @@ // Defines and Macros //---------------------------------------------------------------------------------- // CAMERA_GENERIC -#define CAMERA_SCROLL_SENSITIVITY 1.5 +#define CAMERA_SCROLL_SENSITIVITY 1.5f // FREE_CAMERA -#define FREE_CAMERA_MOUSE_SENSITIVITY 0.01 -#define FREE_CAMERA_DISTANCE_MIN_CLAMP 0.3 -#define FREE_CAMERA_DISTANCE_MAX_CLAMP 120 -#define FREE_CAMERA_MIN_CLAMP 85 -#define FREE_CAMERA_MAX_CLAMP -85 -#define FREE_CAMERA_SMOOTH_ZOOM_SENSITIVITY 0.05 -#define FREE_CAMERA_PANNING_DIVIDER 5.1 +#define FREE_CAMERA_MOUSE_SENSITIVITY 0.01f +#define FREE_CAMERA_DISTANCE_MIN_CLAMP 0.3f +#define FREE_CAMERA_DISTANCE_MAX_CLAMP 120.0f +#define FREE_CAMERA_MIN_CLAMP 85.0f +#define FREE_CAMERA_MAX_CLAMP -85.0f +#define FREE_CAMERA_SMOOTH_ZOOM_SENSITIVITY 0.05f +#define FREE_CAMERA_PANNING_DIVIDER 5.1f // ORBITAL_CAMERA -#define ORBITAL_CAMERA_SPEED 0.01 +#define ORBITAL_CAMERA_SPEED 0.01f // FIRST_PERSON -//#define FIRST_PERSON_MOUSE_SENSITIVITY 0.003 -#define FIRST_PERSON_FOCUS_DISTANCE 25 -#define FIRST_PERSON_MIN_CLAMP 85 -#define FIRST_PERSON_MAX_CLAMP -85 +//#define FIRST_PERSON_MOUSE_SENSITIVITY 0.003f +#define FIRST_PERSON_FOCUS_DISTANCE 25.0f +#define FIRST_PERSON_MIN_CLAMP 85.0f +#define FIRST_PERSON_MAX_CLAMP -85.0f -#define FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 5.0 -#define FIRST_PERSON_STEP_DIVIDER 30.0 -#define FIRST_PERSON_WAVING_DIVIDER 200.0 +#define FIRST_PERSON_STEP_TRIGONOMETRIC_DIVIDER 5.0f +#define FIRST_PERSON_STEP_DIVIDER 30.0f +#define FIRST_PERSON_WAVING_DIVIDER 200.0f -#define FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION 0.85 +#define FIRST_PERSON_HEIGHT_RELATIVE_EYES_POSITION 0.85f // THIRD_PERSON -//#define THIRD_PERSON_MOUSE_SENSITIVITY 0.003 -#define THIRD_PERSON_DISTANCE_CLAMP 1.2 -#define THIRD_PERSON_MIN_CLAMP 5 -#define THIRD_PERSON_MAX_CLAMP -85 -#define THIRD_PERSON_OFFSET (Vector3){ 0.4, 0, 0 } +//#define THIRD_PERSON_MOUSE_SENSITIVITY 0.003f +#define THIRD_PERSON_DISTANCE_CLAMP 1.2f +#define THIRD_PERSON_MIN_CLAMP 5.0f +#define THIRD_PERSON_MAX_CLAMP -85.0f +#define THIRD_PERSON_OFFSET (Vector3){ 0.4f, 0.0f, 0.0f } // PLAYER (used by camera) -#define PLAYER_WIDTH 0.4 -#define PLAYER_HEIGHT 0.9 -#define PLAYER_DEPTH 0.4 -#define PLAYER_MOVEMENT_DIVIDER 20.0 +#define PLAYER_WIDTH 0.4f +#define PLAYER_HEIGHT 0.9f +#define PLAYER_DEPTH 0.4f +#define PLAYER_MOVEMENT_DIVIDER 20.0f //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -84,11 +84,11 @@ typedef enum { MOVE_FRONT = 0, MOVE_LEFT, MOVE_BACK, MOVE_RIGHT, MOVE_UP, MOVE_D //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -static Camera internalCamera = {{2, 0, 2}, {0, 0, 0}, {0, 1, 0}}; -static Vector2 cameraAngle = { 0, 0 }; +static Camera internalCamera = {{ 2.0f, 0.0f, 2.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; +static Vector2 cameraAngle = { 0.0f, 0.0f }; static float cameraTargetDistance = 5.0f; -static Vector2 cameraMousePosition = { 0, 0 }; -static Vector2 cameraMouseVariation = { 0, 0 }; +static Vector2 cameraMousePosition = { 0.0f, 0.0f }; +static Vector2 cameraMouseVariation = { 0.0f, 0.0f }; static float mouseSensitivity = 0.003f; static int cameraMoveControl[6] = { 'W', 'A', 'S', 'D', 'E', 'Q' }; static int cameraMoveCounter = 0; @@ -107,7 +107,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition); #if defined(CAMERA_STANDALONE) // NOTE: Camera controls depend on some raylib input functions // TODO: Set your own input functions (used in ProcessCamera()) -static Vector2 GetMousePosition() { return (Vector2){ 0, 0}; } +static Vector2 GetMousePosition() { return (Vector2){ 0.0f, 0.0f }; } static void SetMousePosition(Vector2 pos) {} static int IsMouseButtonDown(int button) { return 0;} static int GetMouseWheelMove() { return 0; } @@ -129,33 +129,33 @@ void SetCameraMode(int mode) if ((cameraMode == CAMERA_FIRST_PERSON) && (mode == CAMERA_FREE)) { cameraMode = CAMERA_THIRD_PERSON; - cameraTargetDistance = 5; - cameraAngle.y = -40 * DEG2RAD; + cameraTargetDistance = 5.0f; + cameraAngle.y = -40*DEG2RAD; ProcessCamera(&internalCamera, &internalCamera.position); } else if ((cameraMode == CAMERA_FIRST_PERSON) && (mode == CAMERA_ORBITAL)) { cameraMode = CAMERA_THIRD_PERSON; - cameraTargetDistance = 5; - cameraAngle.y = -40 * DEG2RAD; + cameraTargetDistance = 5.0f; + cameraAngle.y = -40*DEG2RAD; ProcessCamera(&internalCamera, &internalCamera.position); } else if ((cameraMode == CAMERA_CUSTOM) && (mode == CAMERA_FREE)) { - cameraTargetDistance = 10; - cameraAngle.x = 45 * DEG2RAD; - cameraAngle.y = -40 * DEG2RAD; - internalCamera.target = (Vector3){ 0, 0, 0 }; + cameraTargetDistance = 10.0f; + cameraAngle.x = 45*DEG2RAD; + cameraAngle.y = -40*DEG2RAD; + internalCamera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; ProcessCamera(&internalCamera, &internalCamera.position); ShowCursor(); } else if ((cameraMode == CAMERA_CUSTOM) && (mode == CAMERA_ORBITAL)) { - cameraTargetDistance = 10; - cameraAngle.x = 225 * DEG2RAD; - cameraAngle.y = -40 * DEG2RAD; - internalCamera.target = (Vector3){ 0, 0, 0}; + cameraTargetDistance = 10.0f; + cameraAngle.x = 225*DEG2RAD; + cameraAngle.y = -40*DEG2RAD; + internalCamera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; ProcessCamera(&internalCamera, &internalCamera.position); } @@ -165,7 +165,7 @@ void SetCameraMode(int mode) // Update camera (player position is ignored) void UpdateCamera(Camera *camera) { - Vector3 position = { 0, 0, 0 }; + Vector3 position = { 0.0f, 0.0f, 0.0f }; // Process internal camera and player position (if required) if (cameraMode != CAMERA_CUSTOM) ProcessCamera(&internalCamera, &position); @@ -244,7 +244,7 @@ void SetCameraMoveControls(int frontKey, int backKey, int leftKey, int rightKey, // Set camera mouse sensitivity (1st person and 3rd person cameras) void SetCameraMouseSensitivity(float sensitivity) { - mouseSensitivity = (sensitivity/10000.0); + mouseSensitivity = (sensitivity/10000.0f); } //---------------------------------------------------------------------------------- @@ -376,12 +376,12 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) // Focus to center // TODO: Move this function out of the module? - if (IsKeyDown('Z')) camera->target = (Vector3){ 0, 0, 0 }; + if (IsKeyDown('Z')) camera->target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera position update camera->position.x = sin(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.x; - if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y; + if (cameraAngle.y <= 0.0f) camera->position.y = sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y; else camera->position.y = -sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y; camera->position.z = cos(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.z; @@ -398,12 +398,12 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) if (cameraTargetDistance < THIRD_PERSON_DISTANCE_CLAMP) cameraTargetDistance = THIRD_PERSON_DISTANCE_CLAMP; // Focus to center - if (IsKeyDown('Z')) camera->target = (Vector3){ 0, 0, 0 }; + if (IsKeyDown('Z')) camera->target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera position update camera->position.x = sin(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.x; - if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y; + if (cameraAngle.y <= 0.0f) camera->position.y = sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y; else camera->position.y = -sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y; camera->position.z = cos(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.z; @@ -412,7 +412,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) case CAMERA_FIRST_PERSON: case CAMERA_THIRD_PERSON: { - int isMoving = 0; + bool isMoving = false; // Keyboard inputs if (IsKeyDown(cameraMoveControl[MOVE_FRONT])) @@ -422,7 +422,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) if (!cameraUseGravity) camera->position.y += sin(cameraAngle.y)/PLAYER_MOVEMENT_DIVIDER; - isMoving = 1; + isMoving = true; } else if (IsKeyDown(cameraMoveControl[MOVE_BACK])) { @@ -431,7 +431,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) if (!cameraUseGravity) camera->position.y -= sin(cameraAngle.y)/PLAYER_MOVEMENT_DIVIDER; - isMoving = 1; + isMoving = true; } if (IsKeyDown(cameraMoveControl[MOVE_LEFT])) @@ -439,23 +439,23 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) playerPosition->x -= cos(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER; playerPosition->z += sin(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER; - isMoving = 1; + isMoving = true; } else if (IsKeyDown(cameraMoveControl[MOVE_RIGHT])) { playerPosition->x += cos(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER; playerPosition->z -= sin(cameraAngle.x)/PLAYER_MOVEMENT_DIVIDER; - isMoving = 1; + isMoving = true; } if (IsKeyDown(cameraMoveControl[MOVE_UP])) { - if (!cameraUseGravity) playerPosition->y += 1/PLAYER_MOVEMENT_DIVIDER; + if (!cameraUseGravity) playerPosition->y += 1.0f/PLAYER_MOVEMENT_DIVIDER; } else if (IsKeyDown(cameraMoveControl[MOVE_DOWN])) { - if (!cameraUseGravity) playerPosition->y -= 1/PLAYER_MOVEMENT_DIVIDER; + if (!cameraUseGravity) playerPosition->y -= 1.0f/PLAYER_MOVEMENT_DIVIDER; } if (cameraMode == CAMERA_THIRD_PERSON) @@ -482,7 +482,7 @@ static void ProcessCamera(Camera *camera, Vector3 *playerPosition) // Camera position update camera->position.x = sin(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.x; - if (cameraAngle.y <= 0) camera->position.y = sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y; + if (cameraAngle.y <= 0.0f) camera->position.y = sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y; else camera->position.y = -sin(cameraAngle.y)*cameraTargetDistance*sin(cameraAngle.y) + camera->target.y; camera->position.z = cos(cameraAngle.x)*cameraTargetDistance*cos(cameraAngle.y) + camera->target.z; diff --git a/src/camera.h b/src/camera.h index ed85320a..9ad09c6f 100644 --- a/src/camera.h +++ b/src/camera.h @@ -28,8 +28,8 @@ #define PI 3.14159265358979323846 #endif -#define DEG2RAD (PI / 180.0f) -#define RAD2DEG (180.0f / PI) +#define DEG2RAD (PI/180.0f) +#define RAD2DEG (180.0f/PI) //---------------------------------------------------------------------------------- // Defines and Macros diff --git a/src/core.c b/src/core.c index 1c9e16ae..c872d43e 100644 --- a/src/core.c +++ b/src/core.c @@ -116,6 +116,7 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- +#define STORAGE_FILENAME "storage.data" //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -591,7 +592,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.1*tan(45.0*PI/360.0); double right = top*aspect; // NOTE: zNear and zFar values are important when computing depth buffer values @@ -630,7 +631,7 @@ void SetTargetFPS(int fps) // Returns current FPS float GetFPS(void) { - return (float)(1/frameTime); + return (float)(1.0/frameTime); } // Returns time in seconds for one frame @@ -791,10 +792,10 @@ void StorageSaveValue(int position, int value) FILE *storageFile = NULL; // Try open existing file to append data - storageFile = fopen("storage.data", "rb+"); + storageFile = fopen(STORAGE_FILENAME, "rb+"); // If file doesn't exist, create a new storage data file - if (!storageFile) storageFile = fopen("storage.data", "wb"); + if (!storageFile) storageFile = fopen(STORAGE_FILENAME, "wb"); if (!storageFile) TraceLog(WARNING, "Storage data file could not be created"); else @@ -822,7 +823,7 @@ int StorageLoadValue(int position) int value = 0; // Try open existing file to append data - FILE *storageFile = fopen("storage.data", "rb"); + FILE *storageFile = fopen(STORAGE_FILENAME, "rb"); if (!storageFile) TraceLog(WARNING, "Storage data file could not be found"); else @@ -889,8 +890,8 @@ Ray GetMouseRay(Vector2 mousePosition, Camera camera) MatrixInvert(&matProjView); // Calculate far and near points - Quaternion near = { deviceCoords.x, deviceCoords.y, 0, 1}; - Quaternion far = { deviceCoords.x, deviceCoords.y, 1, 1}; + Quaternion near = { deviceCoords.x, deviceCoords.y, 0.0f, 1.0f}; + Quaternion far = { deviceCoords.x, deviceCoords.y, 1.0f, 1.0f}; // Multiply points by unproject matrix QuaternionTransform(&near, matProjView); diff --git a/src/raylib.h b/src/raylib.h index c306518d..3d8100b3 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -81,8 +81,8 @@ #define PI 3.14159265358979323846 #endif -#define DEG2RAD (PI / 180.0f) -#define RAD2DEG (180.0f / PI) +#define DEG2RAD (PI/180.0f) +#define RAD2DEG (180.0f/PI) // raylib Config Flags #define FLAG_FULLSCREEN_MODE 1 diff --git a/src/rlgl.c b/src/rlgl.c index 48e6ac1b..6810cb4b 100644 --- a/src/rlgl.c +++ b/src/rlgl.c @@ -1406,7 +1406,7 @@ void rlglDrawPostpro(void) #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) glBindFramebuffer(GL_FRAMEBUFFER, 0); - rlglDrawModel(postproQuad, (Vector3){0,0,0}, (Vector3){0,0,0}, 0.0f, (Vector3){1.0f, 1.0f, 1.0f}, (Color){ 255, 255, 255, 255 }, false); + rlglDrawModel(postproQuad, (Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 0.0f }, 0.0f, (Vector3){1.0f, 1.0f, 1.0f}, (Color){ 255, 255, 255, 255 }, false); #endif } -- cgit v1.2.3 From a847df921f94a7fd118fcb608b23f11d8255c236 Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 10 Feb 2016 10:31:06 +0100 Subject: Reviewed gestures module --- src/core.c | 30 ++++++++++------ src/gestures.c | 110 +++++++++++++++++++++++++++++++++++---------------------- src/gestures.h | 1 + src/raylib.h | 9 ++--- 4 files changed, 94 insertions(+), 56 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index 699cc2b7..05ec0c0a 100644 --- a/src/core.c +++ b/src/core.c @@ -117,7 +117,8 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define STORAGE_FILENAME "storage.data" +#define STORAGE_FILENAME "storage.data" +#define MAX_TOUCH_POINTS 2 //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -182,7 +183,7 @@ static bool fullscreen = false; // Fullscreen mode (useful only for static Matrix downscaleView; // Matrix to downscale view (in case screen size bigger than display size) #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) -static Vector2 touchPosition; // Touch position on screen +static Vector2 touchPosition[MAX_TOUCH_POINTS]; // Touch position on screen #endif #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) @@ -1228,7 +1229,7 @@ bool IsGamepadButtonUp(int gamepad, int button) int GetTouchX(void) { #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) - return (int)touchPosition.x; + return (int)touchPosition[0].x; #else // PLATFORM_DESKTOP, PLATFORM_RPI return GetMouseX(); #endif @@ -1238,7 +1239,7 @@ int GetTouchX(void) int GetTouchY(void) { #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) - return (int)touchPosition.y; + return (int)touchPosition[0].y; #else // PLATFORM_DESKTOP, PLATFORM_RPI return GetMouseY(); #endif @@ -1246,10 +1247,13 @@ int GetTouchY(void) // Returns touch position XY // TODO: touch position should be scaled depending on display size and render size -Vector2 GetTouchPosition(void) +Vector2 GetTouchPosition(int index) { + Vector2 position = { -1.0f, -1.0f }; + #if defined(PLATFORM_ANDROID) || defined(PLATFORM_WEB) - Vector2 position = touchPosition; + if (index < MAX_TOUCH_POINTS) position = touchPosition[index]; + else TraceLog(WARNING, "Required touch point out of range (Max touch points: %i)", MAX_TOUCH_POINTS); if ((screenWidth > displayWidth) || (screenHeight > displayHeight)) { @@ -1263,7 +1267,7 @@ Vector2 GetTouchPosition(void) position.y = position.y*((float)renderHeight/(float)displayHeight) - renderOffsetY/2; } #else // PLATFORM_DESKTOP, PLATFORM_RPI - Vector2 position = GetMousePosition(); + if (index == 0) position = GetMousePosition(); #endif return position; @@ -1916,8 +1920,13 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) if (type == AINPUT_EVENT_TYPE_MOTION) { - touchPosition.x = AMotionEvent_getX(event, 0); - touchPosition.y = AMotionEvent_getY(event, 0); + // Get first touch position + touchPosition[0].x = AMotionEvent_getX(event, 0); + touchPosition[0].y = AMotionEvent_getY(event, 0); + + // Get second touch position + touchPosition[1].x = AMotionEvent_getX(event, 1); + touchPosition[1].y = AMotionEvent_getY(event, 1); } else if (type == AINPUT_EVENT_TYPE_KEY) { @@ -2535,7 +2544,8 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent 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]; + touchPosition[0] = gestureEvent.position[0]; + touchPosition[1] = gestureEvent.position[1]; // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); // Process obtained gestures data diff --git a/src/gestures.c b/src/gestures.c index 09c18fc4..e5a8eb9e 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -31,9 +31,7 @@ #include "raylib.h" // Required for typedef(s): Vector2, Gestures #endif -#include // malloc(), free() -#include // printf(), fprintf() -#include // Used for ... +#include // Used for: atan2(), sqrt() #include // Defines int32_t, int64_t #if defined(_WIN32) @@ -47,13 +45,12 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define FORCE_TO_SWIPE 20 +#define FORCE_TO_SWIPE 1 #define FORCE_TO_DRAG 20 #define FORCE_TO_PINCH 5 #define TAP_TIMEOUT 300 // Time in milliseconds #define PINCH_TIMEOUT 300 // Time in milliseconds #define DOUBLETAP_RANGE 30 -//#define MAX_TOUCH_POINTS 4 //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -64,30 +61,33 @@ // Global Variables Definition //---------------------------------------------------------------------------------- -// Drag gesture variables -static Vector2 dragVector = { 0.0f , 0.0f }; - // Touch gesture variables -static Vector2 touchDownPosition = { 0, 0 }; -static Vector2 touchDownPosition2 = { 0, 0 }; -static Vector2 touchUpPosition = { 0, 0 }; -static Vector2 moveDownPosition = { 0, 0 }; -static Vector2 moveDownPosition2 = { 0, 0 }; +static Vector2 touchDownPosition = { 0.0f, 0.0f }; +static Vector2 touchDownPosition2 = { 0.0f, 0.0f }; +static Vector2 touchDownDragPosition = { 0.0f, 0.0f }; +static Vector2 touchUpPosition = { 0.0f, 0.0f }; +static Vector2 moveDownPosition = { 0.0f, 0.0f }; +static Vector2 moveDownPosition2 = { 0.0f, 0.0f }; static int numTap = 0; static int numHold = 0; +static bool isMoving = false; +static float timeHold = 0.0f; static int pointCount = 0; static int touchId = -1; static double eventTime = 0.0; +static double swipeTime = 0.0; +// Drag gesture variables +static Vector2 dragVector = { 0.0f , 0.0f }; static float dragDistance = 0.0f; // DRAG distance (from initial touch point to current) -static float dragAngle = 0; // DRAG angle direction -static float dragIntensity = 0; // DRAG intensity, how far why did the DRAG (pixels per frame) -static int draggingTimeCounter = 0; // DRAG time // RAY: WTF!!! Counting... frames??? +static float dragAngle = 0.0f; // DRAG angle direction +static float dragIntensity = 0.0f; // DRAG intensity, how far why did the DRAG (pixels per frame) // Pinch gesture variables static float pinchDistance = 0.0f; // Pinch displacement distance // RAY: Not used! o__O +static float pinchAngle = 0.0f; // Pinch displacement distance // RAY: Not used! o__O // Detected gestures static int previousGesture = GESTURE_NONE; @@ -111,9 +111,6 @@ static double GetCurrentTime(); void ProcessGestureEvent(GestureEvent event) { // Reset required variables - dragVector = (Vector2){ 0.0f, 0.0f }; // RAY: Not used??? - pinchDistance = 0.0f; - previousGesture = currentGesture; pointCount = event.pointCount; // Required on UpdateGestures() @@ -139,9 +136,12 @@ void ProcessGestureEvent(GestureEvent event) } touchDownPosition = event.position[0]; + touchDownDragPosition = event.position[0]; touchUpPosition = touchDownPosition; eventTime = GetCurrentTime(); + + dragVector = (Vector2){ 0.0f, 0.0f }; } else if (event.touchAction == TOUCH_UP) { @@ -149,12 +149,15 @@ void ProcessGestureEvent(GestureEvent event) // Calculate for swipe dragDistance = Vector2Distance(touchDownPosition, touchUpPosition); - dragIntensity = dragDistance/(float)draggingTimeCounter; // RAY: WTF!!! Counting frames??? + dragIntensity = dragDistance/(float)((GetCurrentTime() - swipeTime)); + + isMoving = false; // Detect GESTURE_SWIPE if ((dragIntensity > FORCE_TO_SWIPE) && (touchId == 0)) // RAY: why check (touchId == 0)??? { - dragAngle = Vector2Angle(touchDownPosition, touchUpPosition); + // NOTE: Angle should be inverted in Y + dragAngle = 360.0f - Vector2Angle(touchDownPosition, touchUpPosition);; if ((dragAngle < 30) || (dragAngle > 330)) currentGesture = GESTURE_SWIPE_RIGHT; // Right else if ((dragAngle > 30) && (dragAngle < 120)) currentGesture = GESTURE_SWIPE_UP; // Up @@ -171,12 +174,18 @@ void ProcessGestureEvent(GestureEvent event) currentGesture = GESTURE_NONE; } - draggingTimeCounter = 0; + touchDownPosition = (Vector2){ 0.0f, 0.0f }; } else if (event.touchAction == TOUCH_MOVE) { if (Vector2Distance(moveDownPosition, event.position[0]) > 5) eventTime = GetCurrentTime(); + if (!isMoving) + { + swipeTime = GetCurrentTime(); + isMoving = true; + } + moveDownPosition = event.position[0]; if (currentGesture == GESTURE_HOLD) @@ -190,8 +199,9 @@ void ProcessGestureEvent(GestureEvent event) // Detect GESTURE_DRAG if (dragDistance >= FORCE_TO_DRAG) currentGesture = GESTURE_DRAG; } - - draggingTimeCounter++; // RAY: What do you count??? Move event actions? + + dragVector.x = moveDownPosition.x - touchDownDragPosition.x; + dragVector.y = moveDownPosition.y - touchDownDragPosition.y; } } else // Two touch points @@ -200,13 +210,15 @@ void ProcessGestureEvent(GestureEvent event) { touchDownPosition = event.position[0]; touchDownPosition2 = event.position[1]; + pinchDistance = Vector2Distance(touchDownPosition, touchDownPosition2); currentGesture = GESTURE_HOLD; + timeHold = GetCurrentTime(); } else if (event.touchAction == TOUCH_MOVE) { pinchDistance = Vector2Distance(moveDownPosition, moveDownPosition2); - + touchDownPosition = moveDownPosition; touchDownPosition2 = moveDownPosition2; @@ -220,12 +232,17 @@ void ProcessGestureEvent(GestureEvent event) } else { - currentGesture = GESTURE_HOLD; + currentGesture = GESTURE_HOLD; + timeHold = GetCurrentTime(); } + + // NOTE: Angle should be inverted in Y + pinchAngle = 360.0f - Vector2Angle(moveDownPosition, moveDownPosition2); } else if (event.touchAction == TOUCH_UP) { pinchDistance = 0.0f; + pinchAngle = 0.0f; currentGesture = GESTURE_NONE; } @@ -238,11 +255,16 @@ void UpdateGestures(void) // NOTE: Gestures are processed through system callbacks on touch events // Detect GESTURE_HOLD - if (((currentGesture == GESTURE_TAP) || (currentGesture == GESTURE_DOUBLETAP)) && pointCount < 2) currentGesture = GESTURE_HOLD; + if (((currentGesture == GESTURE_TAP) || (currentGesture == GESTURE_DOUBLETAP)) && (pointCount < 2)) + { + currentGesture = GESTURE_HOLD; + timeHold = GetCurrentTime(); + } - if ((GetCurrentTime() - eventTime) > TAP_TIMEOUT && (currentGesture == GESTURE_DRAG) && pointCount < 2) + if (((GetCurrentTime() - eventTime) > TAP_TIMEOUT) && (currentGesture == GESTURE_DRAG) && (pointCount < 2)) { currentGesture = GESTURE_HOLD; + timeHold = GetCurrentTime(); numHold = 1; } @@ -288,17 +310,19 @@ float GetGestureDragAngle(void) // Get drag vector (between initial and final position) Vector2 GetGestureDragVector(void) { - // TODO: Calculate DRAG vector - + // NOTE: Calculated in... return dragVector; } // Hold time measured in ms -int GetGestureHoldDuration(void) +float GetGestureHoldDuration(void) { - // TODO: Return last hold time in ms + float time = 0.0f; + + // DONE: Return last hold time in ms + if (currentGesture == GESTURE_HOLD) time = (float)GetCurrentTime() - timeHold; - return 0; + return time; } // Get distance between two pinch points @@ -307,32 +331,34 @@ float GetGesturePinchDelta(void) return pinchDistance; } +// Get number of touch points +int GetTouchPointsCount(void) +{ + return pointCount; +} + // Get angle beween two pinch points // NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise float GetGesturePinchAngle(void) { - // TODO: Calculate pinch angle + // NOTE: pinch angle is calculated on two touch points TOUCH_MOVE - return 0; + return pinchAngle; } //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- -// RAY: Do we really need magnitude??? why??? -// TODO: Remove magnitude dependency... +// Returns angle from two-points vector with X-axis static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition) { float angle; - - // RAY: review this (better) solution + angle = atan2(finalPosition.y - initialPosition.y, finalPosition.x - initialPosition.x); angle *= RAD2DEG; - if (angle < 0) angle += 360; - - // http://stackoverflow.com/questions/21483999/using-atan2-to-find-angle-between-two-vectors + if (angle < 0) angle += 360.0f; return angle; } diff --git a/src/gestures.h b/src/gestures.h index b5cf2767..52f778be 100644 --- a/src/gestures.h +++ b/src/gestures.h @@ -102,6 +102,7 @@ Vector2 GetGestureDragVector(void); // Get gesture drag vect int GetGestureHoldDuration(void); // Get gesture hold time in frames float GetGesturePinchDelta(void); // Get gesture pinch delta float GetGesturePinchAngle(void); // Get gesture pinch angle +int GetTouchPointsCount(void); // Get touch points count #ifdef __cplusplus } diff --git a/src/raylib.h b/src/raylib.h index 3d8100b3..55a68ad1 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -600,9 +600,9 @@ bool IsGamepadButtonReleased(int gamepad, int button); // Detect if a gamepad b bool IsGamepadButtonUp(int gamepad, int button); // Detect if a gamepad button is NOT being pressed #endif -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) +int GetTouchX(void); // Returns touch position X for touch point 0 (relative to screen size) +int GetTouchY(void); // Returns touch position Y for touch point 0 (relative to screen size) +Vector2 GetTouchPosition(int index) // Returns touch position XY for a touch point index (relative to screen size) #if defined(PLATFORM_ANDROID) bool IsButtonPressed(int button); // Detect if an android physic button has been pressed @@ -622,9 +622,10 @@ void ProcessGestureEvent(GestureEvent event); // Process gesture event float GetGestureDragIntensity(void); // Get gesture drag intensity float GetGestureDragAngle(void); // Get gesture drag angle Vector2 GetGestureDragVector(void); // Get gesture drag vector -int GetGestureHoldDuration(void); // Get gesture hold time in frames +float GetGestureHoldDuration(void); // Get gesture hold time in ms float GetGesturePinchDelta(void); // Get gesture pinch delta float GetGesturePinchAngle(void); // Get gesture pinch angle +int GetTouchPointsCount(void); // Get touch points count //------------------------------------------------------------------------------------ // Camera System Functions (Module: camera) -- cgit v1.2.3 From 84a6724b33efd9ddea9782c3df88855cff2d9d3a Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 10 Feb 2016 11:24:02 +0100 Subject: Fixed a bug --- src/raylib.h | 2 +- src_android/jni/Android.mk | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index 55a68ad1..a5dd6ad2 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -602,7 +602,7 @@ bool IsGamepadButtonUp(int gamepad, int button); // Detect if a gamepad b int GetTouchX(void); // Returns touch position X for touch point 0 (relative to screen size) int GetTouchY(void); // Returns touch position Y for touch point 0 (relative to screen size) -Vector2 GetTouchPosition(int index) // Returns touch position XY for a touch point index (relative to screen size) +Vector2 GetTouchPosition(int index); // Returns touch position XY for a touch point index (relative to screen size) #if defined(PLATFORM_ANDROID) bool IsButtonPressed(int button); // Detect if an android physic button has been pressed diff --git a/src_android/jni/Android.mk b/src_android/jni/Android.mk index f9c20e66..20073760 100644 --- a/src_android/jni/Android.mk +++ b/src_android/jni/Android.mk @@ -39,7 +39,6 @@ LOCAL_MODULE := raylib LOCAL_SRC_FILES :=\ ../../src/core.c \ ../../src/rlgl.c \ - ../../src/raymath.c \ ../../src/textures.c \ ../../src/text.c \ ../../src/shapes.c \ -- cgit v1.2.3 From 685273675bc9247e215c213939c017e506296a70 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Thu, 11 Feb 2016 15:51:04 +0100 Subject: Improved LoadHeightmap() --- examples/models_heightmap.c | 16 ++++++----- examples/models_heightmap.png | Bin 123602 -> 96976 bytes src/models.c | 60 +++++++++++++++++++----------------------- src/raylib.h | 2 +- 4 files changed, 37 insertions(+), 41 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/models_heightmap.c b/examples/models_heightmap.c index ac578c61..f1da3301 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.0f, 18.0f, 24.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }}; + Camera camera = {{ 18.0f, 16.0f, 18.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.0f, 0.0f, -16.0f }; // Set model position (depends on model scaling!) + Image image = LoadImage("resources/heightmap.png"); // Load heightmap image (RAM) + Texture2D texture = LoadTextureFromImage(image); // Convert image to texture (VRAM) + Model map = LoadHeightmap(image, (Vector3){ 16, 8, 16 }); // Load heightmap model with defined size + SetModelTexture(&map, texture); // Bind texture to model + Vector3 mapPosition = { -8.0f, 0.0f, -8.0f }; // Set model position (depends on model scaling!) UnloadImage(image); // Unload heightmap image from RAM, already uploaded to VRAM @@ -54,7 +54,9 @@ int main() Begin3dMode(camera); // NOTE: Model is scaled to 1/4 of its original size (128x128 units) - DrawModel(map, mapPosition, 1/4.0f, RED); + DrawModel(map, mapPosition, 1.0f, RED); + + DrawGrid(20, 1.0f); End3dMode(); diff --git a/examples/models_heightmap.png b/examples/models_heightmap.png index 9ed04586..6dcf01f0 100644 Binary files a/examples/models_heightmap.png and b/examples/models_heightmap.png differ diff --git a/src/models.c b/src/models.c index 91cb5813..94e61d84 100644 --- a/src/models.c +++ b/src/models.c @@ -55,7 +55,6 @@ extern unsigned int whiteTexture; //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- -static float GetHeightValue(Color pixel); static Mesh LoadOBJ(const char *fileName); //---------------------------------------------------------------------------------- @@ -608,17 +607,19 @@ Model LoadModelEx(Mesh data) } // Load a heightmap image as a 3d model -Model LoadHeightmap(Image heightmap, float maxHeight) +// NOTE: model map size is defined in generic units +Model LoadHeightmap(Image heightmap, Vector3 size) { + #define GRAY_VALUE(c) ((c.r+c.g+c.b)/3) + Mesh mesh; int mapX = heightmap.width; int mapZ = heightmap.height; - Color *heightmapPixels = GetImageData(heightmap); + Color *pixels = GetImageData(heightmap); // NOTE: One vertex per pixel - // TODO: Consider resolution when generating model data? int numTriangles = (mapX-1)*(mapZ-1)*2; // One quad every four pixels mesh.vertexCount = numTriangles*3; @@ -634,7 +635,7 @@ Model LoadHeightmap(Image heightmap, float maxHeight) int trisCounter = 0; - float scaleFactor = maxHeight/255; // TODO: Review scaleFactor calculation + Vector3 scaleFactor = { size.x/mapX, size.y/255.0f, size.z/mapZ }; for(int z = 0; z < mapZ-1; z++) { @@ -644,17 +645,17 @@ Model LoadHeightmap(Image heightmap, float maxHeight) //---------------------------------------------------------- // one triangle - 3 vertex - mesh.vertices[vCounter] = x; - mesh.vertices[vCounter + 1] = GetHeightValue(heightmapPixels[x + z*mapX])*scaleFactor; - mesh.vertices[vCounter + 2] = z; + mesh.vertices[vCounter] = (float)x*scaleFactor.x; + mesh.vertices[vCounter + 1] = (float)GRAY_VALUE(pixels[x + z*mapX])*scaleFactor.y; + mesh.vertices[vCounter + 2] = (float)z*scaleFactor.z; - mesh.vertices[vCounter + 3] = x; - mesh.vertices[vCounter + 4] = GetHeightValue(heightmapPixels[x + (z+1)*mapX])*scaleFactor; - mesh.vertices[vCounter + 5] = z+1; + mesh.vertices[vCounter + 3] = (float)x*scaleFactor.x; + mesh.vertices[vCounter + 4] = (float)GRAY_VALUE(pixels[x + (z + 1)*mapX])*scaleFactor.y; + mesh.vertices[vCounter + 5] = (float)(z + 1)*scaleFactor.z; - mesh.vertices[vCounter + 6] = x+1; - mesh.vertices[vCounter + 7] = GetHeightValue(heightmapPixels[(x+1) + z*mapX])*scaleFactor; - mesh.vertices[vCounter + 8] = z; + mesh.vertices[vCounter + 6] = (float)(x + 1)*scaleFactor.x; + mesh.vertices[vCounter + 7] = (float)GRAY_VALUE(pixels[(x + 1) + z*mapX])*scaleFactor.y; + mesh.vertices[vCounter + 8] = (float)z*scaleFactor.z; // another triangle - 3 vertex mesh.vertices[vCounter + 9] = mesh.vertices[vCounter + 6]; @@ -665,21 +666,21 @@ Model LoadHeightmap(Image heightmap, float maxHeight) mesh.vertices[vCounter + 13] = mesh.vertices[vCounter + 4]; mesh.vertices[vCounter + 14] = mesh.vertices[vCounter + 5]; - mesh.vertices[vCounter + 15] = x+1; - mesh.vertices[vCounter + 16] = GetHeightValue(heightmapPixels[(x+1) + (z+1)*mapX])*scaleFactor; - mesh.vertices[vCounter + 17] = z+1; + mesh.vertices[vCounter + 15] = (float)(x + 1)*scaleFactor.x; + mesh.vertices[vCounter + 16] = (float)GRAY_VALUE(pixels[(x + 1) + (z + 1)*mapX])*scaleFactor.y; + mesh.vertices[vCounter + 17] = (float)(z + 1)*scaleFactor.z; vCounter += 18; // 6 vertex, 18 floats // Fill texcoords array with data //-------------------------------------------------------------- - mesh.texcoords[tcCounter] = (float)x / (mapX-1); - mesh.texcoords[tcCounter + 1] = (float)z / (mapZ-1); + mesh.texcoords[tcCounter] = (float)x/(mapX - 1); + mesh.texcoords[tcCounter + 1] = (float)z/(mapZ - 1); - mesh.texcoords[tcCounter + 2] = (float)x / (mapX-1); - mesh.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); - mesh.texcoords[tcCounter + 4] = (float)(x+1) / (mapX-1); - mesh.texcoords[tcCounter + 5] = (float)z / (mapZ-1); + mesh.texcoords[tcCounter + 4] = (float)(x + 1)/(mapX - 1); + mesh.texcoords[tcCounter + 5] = (float)z/(mapZ - 1); mesh.texcoords[tcCounter + 6] = mesh.texcoords[tcCounter + 4]; mesh.texcoords[tcCounter + 7] = mesh.texcoords[tcCounter + 5]; @@ -687,13 +688,12 @@ Model LoadHeightmap(Image heightmap, float maxHeight) mesh.texcoords[tcCounter + 8] = mesh.texcoords[tcCounter + 2]; mesh.texcoords[tcCounter + 9] = mesh.texcoords[tcCounter + 3]; - mesh.texcoords[tcCounter + 10] = (float)(x+1) / (mapX-1); - mesh.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 //-------------------------------------------------------------- - // NOTE: Current Model implementation doe not use normals! for (int i = 0; i < 18; i += 3) { mesh.normals[nCounter + i] = 0.0f; @@ -709,7 +709,7 @@ Model LoadHeightmap(Image heightmap, float maxHeight) } } - free(heightmapPixels); + free(pixels); // Fill color data // NOTE: Not used any more... just one plain color defined at DrawModel() @@ -1688,12 +1688,6 @@ Vector3 ResolveCollisionCubicmap(Image cubicmap, Vector3 mapPosition, Vector3 *p // Module specific Functions Definition //---------------------------------------------------------------------------------- -// Get current vertex y altitude (proportional to pixel colors in grayscale) -static float GetHeightValue(Color pixel) -{ - return (((float)pixel.r + (float)pixel.g + (float)pixel.b)/3); -} - // Load OBJ mesh data static Mesh LoadOBJ(const char *fileName) { diff --git a/src/raylib.h b/src/raylib.h index a5dd6ad2..f9241533 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -759,7 +759,7 @@ void DrawGizmo(Vector3 position); Model LoadModel(const char *fileName); // Load a 3d model (.OBJ) 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 LoadHeightmap(Image heightmap, Vector3 size); // Load a heightmap image as a 3d model Model LoadCubicmap(Image cubicmap); // Load a map image as a 3d model (cubes based) void UnloadModel(Model model); // Unload 3d model from memory void SetModelTexture(Model *model, Texture2D texture); // Link a texture to a model -- cgit v1.2.3 From cbbe9485294032d680579809976f7035785d3694 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Fri, 12 Feb 2016 19:02:23 +0100 Subject: Some code tweaks --- examples/shaders_basic_lighting.c | 12 ++++++------ src/core.c | 5 ++++- src/raylib.h | 14 ++++++++------ 3 files changed, 18 insertions(+), 13 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/shaders_basic_lighting.c b/examples/shaders_basic_lighting.c index 649eab74..84bd1af4 100644 --- a/examples/shaders_basic_lighting.c +++ b/examples/shaders_basic_lighting.c @@ -77,9 +77,9 @@ int main() light.specIntensity = 1.0f; // Material initialization - matBlinn.diffuse = WHITE; - matBlinn.ambient = (Color){ 50, 50, 50, 255 }; - matBlinn.specular = WHITE; + matBlinn.colDiffuse = WHITE; + matBlinn.colAmbient = (Color){ 50, 50, 50, 255 }; + matBlinn.colSpecular = WHITE; matBlinn.glossiness = 50.0f; // Setup camera @@ -129,8 +129,8 @@ int main() 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, mAmbientLoc, ColorToFloat(matBlinn.colAmbient), 3); + SetShaderValue(shader, mSpecularLoc, ColorToFloat(matBlinn.colSpecular), 3); SetShaderValue(shader, mGlossLoc, &matBlinn.glossiness, 1); // Send camera and light transform values to shader @@ -146,7 +146,7 @@ int main() Begin3dMode(camera); - DrawModel(model, position, 4.0f, matBlinn.diffuse); + DrawModel(model, position, 4.0f, matBlinn.colDiffuse); DrawSphere(light.position, 0.5f, GOLD); DrawGrid(20, 1.0f); diff --git a/src/core.c b/src/core.c index 413006e4..cff90ba9 100644 --- a/src/core.c +++ b/src/core.c @@ -118,7 +118,6 @@ // Defines and Macros //---------------------------------------------------------------------------------- #define STORAGE_FILENAME "storage.data" -#define MAX_TOUCH_POINTS 2 //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -324,6 +323,10 @@ void InitWindow(int width, int height, const char *title) emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenInputCallback); emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenInputCallback); emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenInputCallback); + + // TODO: Add gamepad support (not provided by GLFW3 on emscripten) + //emscripten_set_gamepadconnected_callback(NULL, 1, EmscriptenInputCallback); + //emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenInputCallback); #endif mousePosition.x = (float)screenWidth/2.0f; diff --git a/src/raylib.h b/src/raylib.h index f9241533..c2067a0e 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -166,6 +166,9 @@ #define MOUSE_MIDDLE_BUTTON 2 #endif +// Touch points registered +#define MAX_TOUCH_POINTS 2 + // Gamepad Number #define GAMEPAD_PLAYER1 0 #define GAMEPAD_PLAYER2 1 @@ -348,9 +351,6 @@ typedef struct Shader { // Uniforms 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) @@ -448,15 +448,16 @@ typedef enum { GESTURE_PINCH_OUT = 512 } Gestures; +// Touch action (fingers or mouse) typedef enum { TOUCH_UP, TOUCH_DOWN, TOUCH_MOVE } TouchAction; // Gesture events -// NOTE: MAX_TOUCH_POINTS fixed to 4 +// NOTE: MAX_TOUCH_POINTS fixed to 2 typedef struct { int touchAction; int pointCount; - int pointerId[4]; - Vector2 position[4]; + int pointerId[MAX_TOUCH_POINTS]; + Vector2 position[MAX_TOUCH_POINTS]; } GestureEvent; // Camera system modes @@ -798,6 +799,7 @@ bool IsPosproShaderEnabled(void); // Check if int GetShaderLocation(Shader shader, const char *uniformName); // Get shader uniform location void SetShaderValue(Shader shader, int uniformLoc, float *value, int size); // Set shader uniform value (float) void SetShaderValuei(Shader shader, int uniformLoc, int *value, int size); // Set shader uniform value (int) +void SetShaderValueMatrix(Shader shader, int uniformLoc, Matrix mat); // Set shader uniform value (matrix 4x4) void SetShaderMapDiffuse(Shader *shader, Texture2D texture); // Default diffuse shader map texture assignment void SetShaderMapNormal(Shader *shader, const char *uniformName, Texture2D texture); // Normal map texture shader assignment void SetShaderMapSpecular(Shader *shader, const char *uniformName, Texture2D texture); // Specular map texture shader assignment -- cgit v1.2.3 From ed1906440560d5b6b6e2cb1c1927e53b28e302db Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 13 Feb 2016 17:09:53 +0100 Subject: Reviewed physics module A deeper revision required, not clear enough for the user Key: Create a PhysicObjects pool --- examples/physics_basic_rigidbody.c | 44 +++++++-------------------- examples/physics_rigidbody_force.c | 33 ++++++++------------- src/physac.c | 61 ++++++++++++++++++++++---------------- src/physac.h | 11 ++----- src/raylib.h | 13 ++------ 5 files changed, 64 insertions(+), 98 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/physics_basic_rigidbody.c b/examples/physics_basic_rigidbody.c index b82fe638..6c354eb7 100644 --- a/examples/physics_basic_rigidbody.c +++ b/examples/physics_basic_rigidbody.c @@ -2,20 +2,10 @@ * * 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) +* 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) 2015 Ramon Santamaria (@raysan5) +* Copyright (c) 2016 Victor Fisac and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -33,13 +23,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [physics] example - basic rigidbody"); - 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); + InitPhysics(3); // Initialize physics system with maximum physic objects // Object initialization Transform player = (Transform){(Vector2){(screenWidth - OBJECT_SIZE) / 2, (screenHeight - OBJECT_SIZE) / 2}, 0.0f, (Vector2){OBJECT_SIZE, OBJECT_SIZE}}; @@ -55,6 +39,8 @@ int main() float moveSpeed = 6.0f; float jumpForce = 5.0f; + bool physicsDebug = false; + SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -91,14 +77,7 @@ int main() } // Check debug mode toggle button input - if(IsKeyPressed(KEY_P)) - { - // Update program physics value - worldPhysics.debug = !worldPhysics.debug; - - // Update internal physics value - SetPhysics(worldPhysics); - } + if (IsKeyPressed(KEY_P)) physicsDebug = !physicsDebug; //---------------------------------------------------------------------------------- // Draw @@ -112,7 +91,7 @@ int main() 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) + if (physicsDebug) { // Draw every internal physics stored collider if it is active for (int i = 0; i < 2; i++) @@ -122,14 +101,11 @@ int main() DrawRectangleLines(GetCollider(i).bounds.x, GetCollider(i).bounds.y, GetCollider(i).bounds.width, GetCollider(i).bounds.height, GREEN); } } - } else { - // Draw player + // Draw player and floor 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); } @@ -138,7 +114,9 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- + UnloadPhysics(); // Unload physic objects + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/examples/physics_rigidbody_force.c b/examples/physics_rigidbody_force.c index 3ac560c5..74a88a97 100644 --- a/examples/physics_rigidbody_force.c +++ b/examples/physics_rigidbody_force.c @@ -2,10 +2,10 @@ * * raylib [physac] physics example - Rigidbody forces * -* This example has been created using raylib 1.3 (www.raylib.com) +* 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) +* Copyright (c) 2016 Victor Fisac and Ramon Santamaria (@raysan5) * ********************************************************************************************/ @@ -26,15 +26,9 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [physics] example - rigidbodies forces"); - InitPhysics(); // Initialize internal physics values (max rigidbodies/colliders available: 1024) + InitPhysics(MAX_OBJECTS + 1); // Initialize physics system with maximum physic objects - // Physics initialization - Physics worldPhysics = {true, false, (Vector2){0, -9.81f}}; - - // Set internal physics settings - SetPhysics(worldPhysics); - - // Objects initialization + // Physic Objects initialization Transform objects[MAX_OBJECTS]; for (int i = 0; i < MAX_OBJECTS; i++) @@ -49,6 +43,8 @@ int main() Transform floor = (Transform){(Vector2){0, screenHeight * 0.8f}, 0.0f, (Vector2){screenWidth, screenHeight * 0.2f}}; AddCollider(MAX_OBJECTS, (Collider){true, COLLIDER_RECTANGLE, (Rectangle){floor.position.x, floor.position.y, floor.scale.x, floor.scale.y}, 0}); + bool physicsDebug = false; + SetTargetFPS(60); //-------------------------------------------------------------------------------------- @@ -72,14 +68,7 @@ int main() } // Check debug mode toggle button input - if (IsKeyPressed(KEY_P)) - { - // Update program physics value - worldPhysics.debug = !worldPhysics.debug; - - // Update internal physics value - SetPhysics(worldPhysics); - } + if (IsKeyPressed(KEY_P)) physicsDebug = !physicsDebug; //---------------------------------------------------------------------------------- // Draw @@ -89,10 +78,10 @@ int main() ClearBackground(RAYWHITE); // Check if debug mode is enabled - if (worldPhysics.debug) + if (physicsDebug) { // Draw every internal physics stored collider if it is active (floor included) - for (int i = 0; i < MAX_OBJECTS + 1; i++) + for (int i = 0; i < MAX_OBJECTS; i++) { if (GetCollider(i).enabled) { @@ -136,7 +125,9 @@ int main() } // De-Initialization - //-------------------------------------------------------------------------------------- + //-------------------------------------------------------------------------------------- + UnloadPhysics(); // Unload physic objects + CloseWindow(); // Close window and OpenGL context //-------------------------------------------------------------------------------------- diff --git a/src/physac.c b/src/physac.c index 891f0123..4c50dd41 100644 --- a/src/physac.c +++ b/src/physac.c @@ -30,13 +30,12 @@ #endif #include -#include +#include // Required for: malloc(), free() //---------------------------------------------------------------------------------- // 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) +#define DECIMAL_FIX 0.26f // Decimal margin for collision checks (avoid rigidbodies shake) //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -46,10 +45,13 @@ //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- -static Physics physics; -static Collider colliders[MAX_ELEMENTS]; -static Rigidbody rigidbodies[MAX_ELEMENTS]; -static bool collisionChecker = false; +static Collider *colliders; // Colliders array, dynamically allocated at runtime +static Rigidbody *rigidbodies; // Rigitbody array, dynamically allocated at runtime +static bool collisionChecker; + +static int maxElements; // Max physic elements to compute +static bool enabled; // Physics enabled? (true by default) +static Vector2 gravity; // Gravity value used for physic calculations //---------------------------------------------------------------------------------- // Module specific Functions Declarations @@ -61,30 +63,39 @@ static void Vector2Normalize(Vector2 *vector); //---------------------------------------------------------------------------------- // Module Functions Definitions //---------------------------------------------------------------------------------- -void InitPhysics(void) -{ - for (int i = 0; i < MAX_ELEMENTS; i++) +void InitPhysics(int maxPhysicElements) +{ + maxElements = maxPhysicElements; + + colliders = (Collider *)malloc(maxElements*sizeof(Collider)); + rigidbodies = (Rigidbody *)malloc(maxElements*sizeof(Rigidbody)); + + for (int i = 0; i < maxElements; i++) { + colliders[i].enabled = false; + colliders[i].bounds = (Rectangle){ 0, 0, 0, 0 }; + colliders[i].radius = 0; + rigidbodies[i].enabled = false; rigidbodies[i].mass = 0.0f; - rigidbodies[i].velocity = (Vector2){0, 0}; - rigidbodies[i].acceleration = (Vector2){0, 0}; + rigidbodies[i].velocity = (Vector2){ 0.0f, 0.0f }; + rigidbodies[i].acceleration = (Vector2){ 0.0f, 0.0f }; 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; } + + collisionChecker = false; + enabled = true; + + // NOTE: To get better results, gravity needs to be 1:10 from original parameter + gravity = (Vector2){ 0.0f, -9.81f/10.0f }; // By default, standard gravity } -void SetPhysics(Physics settings) +void UnloadPhysics() { - 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}; + free(colliders); + free(rigidbodies); } void AddCollider(int index, Collider collider) @@ -159,8 +170,8 @@ void ApplyPhysics(int index, Vector2 *position) } // Apply gravity - rigidbodies[index].velocity.y += physics.gravity.y; - rigidbodies[index].velocity.x += physics.gravity.x; + rigidbodies[index].velocity.y += gravity.y; + rigidbodies[index].velocity.x += gravity.x; // Apply acceleration rigidbodies[index].velocity.y += rigidbodies[index].acceleration.y; @@ -177,7 +188,7 @@ void ApplyPhysics(int index, Vector2 *position) // Check collision with other colliders collisionChecker = false; rigidbodies[index].isContact = false; - for (int j = 0; j < MAX_ELEMENTS; j++) + for (int j = 0; j < maxElements; j++) { if (index != j) { @@ -269,7 +280,7 @@ void AddRigidbodyForce(int index, Vector2 force) void AddForceAtPosition(Vector2 position, float intensity, float radius) { - for(int i = 0; i < MAX_ELEMENTS; i++) + for(int i = 0; i < maxElements; i++) { if(rigidbodies[i].enabled) { diff --git a/src/physac.h b/src/physac.h index 12209987..9e1b0b88 100644 --- a/src/physac.h +++ b/src/physac.h @@ -35,13 +35,6 @@ // Collider types typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE, COLLIDER_CAPSULE } 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; @@ -77,8 +70,8 @@ extern "C" { // Prevents name mangling of functions //---------------------------------------------------------------------------------- // 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 InitPhysics(int maxPhysicElements); // Initialize all internal physics values +void UnloadPhysics(); // Unload physic elements arrays 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 diff --git a/src/raylib.h b/src/raylib.h index c2067a0e..43819b14 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -466,13 +466,6 @@ typedef enum { CAMERA_CUSTOM = 0, CAMERA_FREE, CAMERA_ORBITAL, CAMERA_FIRST_PERS // Collider types typedef enum { COLLIDER_CIRCLE, COLLIDER_RECTANGLE, COLLIDER_CAPSULE } 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; @@ -808,10 +801,10 @@ 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) +// Physics System Functions (engine-module: physac) //---------------------------------------------------------------------------------- -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 InitPhysics(int maxPhysicElements); // Initialize all internal physics values +void UnloadPhysics(); // Unload physic elements arrays 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 -- cgit v1.2.3 From 0018522031b8b06c447d49273bf288ec5e7a8a63 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sat, 13 Feb 2016 19:14:22 +0100 Subject: Updated show-logo and start reviewing RPI inputs --- examples/shapes_logo_raylib_anim.c | 30 ++++++------------------------ src/core.c | 32 ++++++++++---------------------- src/raylib.h | 2 +- 3 files changed, 17 insertions(+), 47 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/shapes_logo_raylib_anim.c b/examples/shapes_logo_raylib_anim.c index b1bdc3a8..c6d3796e 100644 --- a/examples/shapes_logo_raylib_anim.c +++ b/examples/shapes_logo_raylib_anim.c @@ -2,7 +2,7 @@ * * raylib [shapes] example - raylib logo animation * -* This example has been created using raylib 1.1 (www.raylib.com) +* 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) @@ -32,8 +32,6 @@ int main() int bottomSideRecWidth = 16; int rightSideRecHeight = 16; - char raylib[8] = " \0"; // raylib text array, max 8 letters - int state = 0; // Tracking animation states (State Machine) float alpha = 1.0f; // Useful for fading @@ -79,24 +77,13 @@ int main() framesCounter = 0; } - switch (lettersCount) - { - 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 (lettersCount >= 10) // When all letters have appeared, just fade out everything { - alpha -= 0.02; + alpha -= 0.02f; - if (alpha <= 0) + if (alpha <= 0.0f) { - alpha = 0; + alpha = 0.0f; state = 4; } } @@ -114,12 +101,7 @@ int main() bottomSideRecWidth = 16; rightSideRecHeight = 16; - for (int i = 0; i < 7; i++) raylib[i] = ' '; - - raylib[7] = '\0'; // Last character is end-of-line - - alpha = 1.0; - + alpha = 1.0f; state = 0; // Return to State 0 } } @@ -158,7 +140,7 @@ int main() DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); - DrawText(raylib, screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha)); + DrawText(SubText("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha)); } else if (state == 4) { diff --git a/src/core.c b/src/core.c index 7ecedee0..0c85ab26 100644 --- a/src/core.c +++ b/src/core.c @@ -151,7 +151,7 @@ pthread_t mouseThreadId; // Mouse reading thread id static int defaultKeyboardMode; // Used to store default keyboard mode static struct termios defaultKeyboardSettings; // Used to staore default keyboard settings -static int keyboardMode = 0; // Keyboard mode: 1 (KEYCODES), 2 (ASCII) +static int keyboardMode = 0; // Keyboard mode: 1 - KEYCODES, 2 - ASCII // This array maps Unix keycodes to ASCII equivalent and to GLFW3 equivalent for special function keys (>256) const short UnixKeycodeToASCII[128] = { 256, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 45, 61, 259, 9, 81, 87, 69, 82, 84, 89, 85, 73, 79, 80, 91, 93, 257, 341, 65, 83, 68, @@ -1128,7 +1128,7 @@ bool IsCursorHidden() { return cursorHidden; } -#endif +#endif //defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) // TODO: Enable gamepad usage on Rapsberry Pi // NOTE: emscripten not implemented @@ -2077,7 +2077,7 @@ static bool GetMouseButtonStatus(int button) // TODO: Check for virtual keyboard return false; #elif defined(PLATFORM_RPI) - // NOTE: mouse buttons array is filled on PollInputEvents() + // NOTE: Mouse buttons states are filled in PollInputEvents() return currentMouseState[button]; #endif } @@ -2099,8 +2099,7 @@ static void PollInputEvents(void) mousePosition.x = (float)mouseX; mousePosition.y = (float)mouseY; - // Keyboard polling - // Automatically managed by GLFW3 through callback + // Keyboard input polling (automatically managed by GLFW3 through callback) lastKeyPressed = -1; // Register previous keys states @@ -2157,7 +2156,7 @@ static void PollInputEvents(void) int key = keysBuffer[i]; - if (keyboardMode == 2) // scancodes + if (keyboardMode == 2) // ASCII chars (K_XLATE mode) { // 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 @@ -2215,8 +2214,7 @@ static void PollInputEvents(void) if (key == 0x01) windowShouldClose = true; } - - // Same fucnionality as GLFW3 KeyCallback() + // Same functionality as GLFW3 KeyCallback() /* if (asciiKey == exitKey) windowShouldClose = true; else if (key == GLFW_KEY_F12 && action == GLFW_PRESS) @@ -2356,7 +2354,7 @@ static void InitKeyboard(void) // Set new keyboard settings (change occurs immediately) tcsetattr(STDIN_FILENO, TCSANOW, &keyboardNewSettings); - // NOTE: Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE, we change that! + // NOTE: Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE, we change that! -> WHY??? // Save old keyboard mode to restore it at the end if (ioctl(STDIN_FILENO, KDGKBMODE, &defaultKeyboardMode) < 0) @@ -2374,6 +2372,8 @@ static void InitKeyboard(void) // - ASCII chars (K_XLATE) // - UNICODE chars (K_UNICODE) ioctl(STDIN_FILENO, KDSKBMODE, K_MEDIUMRAW); + + //http://lct.sourceforge.net/lct/x60.html keyboardMode = 1; // keycodes } @@ -2587,7 +2587,6 @@ static void LogoAnimation(void) int bottomSideRecWidth = 16; int rightSideRecHeight = 16; - char raylib[8] = " "; // raylib text array, max 8 letters int state = 0; // Tracking animation states (State Machine) float alpha = 1.0f; // Useful for fading @@ -2629,17 +2628,6 @@ static void LogoAnimation(void) framesCounter = 0; } - switch (lettersCount) - { - 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 (lettersCount >= 10) // When all letters have appeared, just fade out everything { alpha -= 0.02f; @@ -2686,7 +2674,7 @@ static void LogoAnimation(void) DrawRectangle(screenWidth/2 - 112, screenHeight/2 - 112, 224, 224, Fade(RAYWHITE, alpha)); - DrawText(raylib, screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha)); + DrawText(SubText("raylib", 0, lettersCount), screenWidth/2 - 44, screenHeight/2 + 48, 50, Fade(BLACK, alpha)); } EndDrawing(); diff --git a/src/raylib.h b/src/raylib.h index 43819b14..f5a3cc31 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -118,7 +118,7 @@ #define KEY_RIGHT_CONTROL 345 #define KEY_RIGHT_ALT 346 -// Keyboard Alhpa Numeric Keys +// Keyboard Alpha Numeric Keys #define KEY_ZERO 48 #define KEY_ONE 49 #define KEY_TWO 50 -- cgit v1.2.3 From afd2ffb74a84bf48b9129c613e1673ceae0bd46b Mon Sep 17 00:00:00 2001 From: Ray Date: Wed, 17 Feb 2016 13:00:48 +0100 Subject: Updated gestures module Using normalized [0..1] input points --- src/core.c | 28 +++++++++++- src/gestures.c | 134 ++++++++++++++++++++++++++++++--------------------------- src/gestures.h | 12 +++--- src/raylib.h | 11 +++-- 4 files changed, 109 insertions(+), 76 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index 0c85ab26..7b981097 100644 --- a/src/core.c +++ b/src/core.c @@ -1700,14 +1700,22 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int // Register touch actions if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_DOWN; - //else if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_MOVE; else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) gestureEvent.touchAction = TOUCH_UP; + // NOTE: TOUCH_MOVE event is registered in MouseCursorPosCallback() + + // Assign a pointer ID + gestureEvent.pointerId[0] = 0; + // Register touch points count gestureEvent.pointCount = 1; // Register touch points position, only one point registered gestureEvent.position[0] = GetMousePosition(); + + // Normalize gestureEvent.position[0] for screenWidth and screenHeight + gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].y /= (float)GetScreenHeight(); // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); @@ -1729,6 +1737,10 @@ static void MouseCursorPosCallback(GLFWwindow *window, double x, double y) // Register touch points position, only one point registered gestureEvent.position[0] = (Vector2){ (float)x, (float)y }; + + // Normalize gestureEvent.position[0] for screenWidth and screenHeight + gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].y /= (float)GetScreenHeight(); // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); @@ -1992,6 +2004,13 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) gestureEvent.position[0] = (Vector2){ AMotionEvent_getX(event, 0), AMotionEvent_getY(event, 0) }; gestureEvent.position[1] = (Vector2){ AMotionEvent_getX(event, 1), AMotionEvent_getY(event, 1) }; + // Normalize gestureEvent.position[x] for screenWidth and screenHeight + gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].y /= (float)GetScreenHeight(); + + gestureEvent.position[1].x /= (float)GetScreenWidth(); + gestureEvent.position[1].y /= (float)GetScreenHeight(); + // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); @@ -2564,6 +2583,13 @@ static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent touchPosition[0] = gestureEvent.position[0]; touchPosition[1] = gestureEvent.position[1]; + // Normalize gestureEvent.position[x] for screenWidth and screenHeight + gestureEvent.position[0].x /= (float)GetScreenWidth(); + gestureEvent.position[0].y /= (float)GetScreenHeight(); + + gestureEvent.position[1].x /= (float)GetScreenWidth(); + gestureEvent.position[1].y /= (float)GetScreenHeight(); + // Gesture data is sent to gestures system for processing ProcessGestureEvent(gestureEvent); // Process obtained gestures data diff --git a/src/gestures.c b/src/gestures.c index 16442e45..af92ba3d 100644 --- a/src/gestures.c +++ b/src/gestures.c @@ -45,12 +45,12 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define FORCE_TO_SWIPE 1 // Time in milliseconds -#define FORCE_TO_DRAG 20 -#define FORCE_TO_PINCH 5 -#define TAP_TIMEOUT 300 // Time in milliseconds -#define PINCH_TIMEOUT 300 // Time in milliseconds -#define DOUBLETAP_RANGE 30 +#define FORCE_TO_SWIPE 0.0005f // Measured in normalized pixels / time +#define MINIMUM_DRAG 0.015f // Measured in normalized pixels [0..1] +#define MINIMUM_PINCH 0.005f // Measured in normalized pixels [0..1] +#define TAP_TIMEOUT 300 // Time in milliseconds +#define PINCH_TIMEOUT 300 // Time in milliseconds +#define DOUBLETAP_RANGE 0.03f //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -68,26 +68,29 @@ static Vector2 touchDownDragPosition = { 0.0f, 0.0f }; static Vector2 touchUpPosition = { 0.0f, 0.0f }; static Vector2 moveDownPosition = { 0.0f, 0.0f }; static Vector2 moveDownPosition2 = { 0.0f, 0.0f }; - static int numTap = 0; -static int numHold = 0; -static bool isMoving = false; -static float timeHold = 0.0f; + static int pointCount = 0; static int touchId = -1; static double eventTime = 0.0; static double swipeTime = 0.0; +// Hold gesture variables +static int numHold = 0; +static float timeHold = 0.0f; + // Drag gesture variables static Vector2 dragVector = { 0.0f , 0.0f }; // DRAG vector (between initial and current position) -static float dragDistance = 0.0f; // DRAG distance (from initial touch point to final) for SWIPE GESTURE -static float dragAngle = 0.0f; // DRAG angle direction for SWIPE GESTURE -static float dragIntensity = 0.0f; // DRAG intensity, how far why did the DRAG (pixels per frame) for SWIPE GESTURE +static float dragAngle = 0.0f; // DRAG angle (relative to x-axis) +static float dragDistance = 0.0f; // DRAG distance (from initial touch point to final) (normalized [0..1]) +static float dragIntensity = 0.0f; // DRAG intensity, how far why did the DRAG (pixels per frame) +static bool startMoving = false; // SWIPE used to define when start measuring swipeTime // Pinch gesture variables -static float pinchDistance = 0.0f; // Pinch displacement distance -static float pinchAngle = 0.0f; // Pinch displacement distance +static Vector2 pinchVector = { 0.0f , 0.0f }; // PINCH vector (between first and second touch points) +static float pinchAngle = 0.0f; // PINCH angle (relative to x-axis) +static float pinchDistance = 0.0f; // PINCH displacement distance (normalized [0..1]) // Detected gestures static int previousGesture = GESTURE_NONE; @@ -101,7 +104,7 @@ static unsigned int enabledGestures = 0b0000001111111111; //---------------------------------------------------------------------------------- static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition); static float Vector2Distance(Vector2 v1, Vector2 v2); -static double GetCurrentTime(); +static double GetCurrentTime(void); //---------------------------------------------------------------------------------- // Module Functions Definition @@ -147,17 +150,19 @@ void ProcessGestureEvent(GestureEvent event) { if (currentGesture == GESTURE_DRAG) touchUpPosition = event.position[0]; - // Calculate for swipe + // NOTE: dragIntensity dependend on the resolution of the screen dragDistance = Vector2Distance(touchDownPosition, touchUpPosition); dragIntensity = dragDistance/(float)((GetCurrentTime() - swipeTime)); + + // TODO: Make getures detection resolution independant - isMoving = false; + startMoving = false; // Detect GESTURE_SWIPE if ((dragIntensity > FORCE_TO_SWIPE) && (touchId == 0)) // RAY: why check (touchId == 0)??? { // NOTE: Angle should be inverted in Y - dragAngle = 360.0f - Vector2Angle(touchDownPosition, touchUpPosition);; + dragAngle = 360.0f - Vector2Angle(touchDownPosition, touchUpPosition); if ((dragAngle < 30) || (dragAngle > 330)) currentGesture = GESTURE_SWIPE_RIGHT; // Right else if ((dragAngle > 30) && (dragAngle < 120)) currentGesture = GESTURE_SWIPE_UP; // Up @@ -178,26 +183,28 @@ void ProcessGestureEvent(GestureEvent event) } else if (event.touchAction == TOUCH_MOVE) { - if (Vector2Distance(moveDownPosition, event.position[0]) > 5) eventTime = GetCurrentTime(); + if ((currentGesture == GESTURE_DRAG)) eventTime = GetCurrentTime(); - if (!isMoving) + if (!startMoving) { swipeTime = GetCurrentTime(); - isMoving = true; + startMoving = true; } moveDownPosition = event.position[0]; - if (currentGesture == GESTURE_HOLD) + if (currentGesture == GESTURE_HOLD) { if (numHold == 1) touchDownPosition = event.position[0]; numHold = 2; - - dragDistance = Vector2Distance(touchDownPosition, moveDownPosition); // Detect GESTURE_DRAG - if (dragDistance >= FORCE_TO_DRAG) currentGesture = GESTURE_DRAG; + if (Vector2Distance(touchDownPosition, moveDownPosition) >= MINIMUM_DRAG) + { + eventTime = GetCurrentTime(); + currentGesture = GESTURE_DRAG; + } } dragVector.x = moveDownPosition.x - touchDownDragPosition.x; @@ -210,7 +217,11 @@ void ProcessGestureEvent(GestureEvent event) { touchDownPosition = event.position[0]; touchDownPosition2 = event.position[1]; - pinchDistance = Vector2Distance(touchDownPosition, touchDownPosition2); + + //pinchDistance = Vector2Distance(touchDownPosition, touchDownPosition2); + + pinchVector.x = touchDownPosition2.x - touchDownPosition.x; + pinchVector.y = touchDownPosition2.y - touchDownPosition.y; currentGesture = GESTURE_HOLD; timeHold = GetCurrentTime(); @@ -218,22 +229,25 @@ void ProcessGestureEvent(GestureEvent event) else if (event.touchAction == TOUCH_MOVE) { pinchDistance = Vector2Distance(moveDownPosition, moveDownPosition2); - + touchDownPosition = moveDownPosition; touchDownPosition2 = moveDownPosition2; moveDownPosition = event.position[0]; moveDownPosition2 = event.position[1]; - if ((Vector2Distance(touchDownPosition, moveDownPosition) > FORCE_TO_PINCH) || (Vector2Distance(touchDownPosition2, moveDownPosition2) > FORCE_TO_PINCH)) + pinchVector.x = moveDownPosition2.x - moveDownPosition.x; + pinchVector.y = moveDownPosition2.y - moveDownPosition.y; + + if ((Vector2Distance(touchDownPosition, moveDownPosition) >= MINIMUM_PINCH) || (Vector2Distance(touchDownPosition2, moveDownPosition2) >= MINIMUM_PINCH)) { if ((Vector2Distance(moveDownPosition, moveDownPosition2) - pinchDistance) < 0) currentGesture = GESTURE_PINCH_IN; else currentGesture = GESTURE_PINCH_OUT; } - else + else { - currentGesture = GESTURE_HOLD; - timeHold = GetCurrentTime(); + currentGesture = GESTURE_HOLD; + timeHold = GetCurrentTime(); } // NOTE: Angle should be inverted in Y @@ -243,6 +257,7 @@ void ProcessGestureEvent(GestureEvent event) { pinchDistance = 0.0f; pinchAngle = 0.0f; + pinchVector = (Vector2){ 0.0f, 0.0f }; currentGesture = GESTURE_NONE; } @@ -289,26 +304,30 @@ int GetGestureType(void) return (enabledGestures & currentGesture); } -void SetGesturesEnabled(unsigned int gestureFlags) +// Get number of touch points +int GetTouchPointsCount(void) { - enabledGestures = gestureFlags; + // NOTE: point count is calculated when ProcessGestureEvent(GestureEvent event) is called + + return pointCount; } -// Get drag dragIntensity (pixels per frame) -float GetGestureDragdragIntensity(void) +// Enable only desired getures to be detected +void SetGesturesEnabled(unsigned int gestureFlags) { - // NOTE: drag intensity is calculated on one touch points TOUCH_UP - - return dragIntensity; + enabledGestures = gestureFlags; } -// Get drag angle -// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise -float GetGestureDragAngle(void) +// Hold time measured in ms +float GetGestureHoldDuration(void) { - // NOTE: drag angle is calculated on one touch points TOUCH_UP + // NOTE: time is calculated on current gesture HOLD - return dragAngle; + float time = 0.0f; + + if (currentGesture == GESTURE_HOLD) time = (float)GetCurrentTime() - timeHold; + + return time; } // Get drag vector (between initial touch point to current) @@ -319,33 +338,22 @@ Vector2 GetGestureDragVector(void) return dragVector; } -// Hold time measured in ms -float GetGestureHoldDuration(void) +// Get drag angle +// NOTE: Angle in degrees, horizontal-right is 0, counterclock-wise +float GetGestureDragAngle(void) { - // NOTE: time is calculated on current gesture HOLD - - float time = 0.0f; - - if (currentGesture == GESTURE_HOLD) time = (float)GetCurrentTime() - timeHold; + // NOTE: drag angle is calculated on one touch points TOUCH_UP - return time; + return dragAngle; } // Get distance between two pinch points -float GetGesturePinchDelta(void) +Vector2 GetGesturePinchVector(void) { // NOTE: The position values used for pinchDistance are not modified like the position values of [core.c]-->GetTouchPosition(int index) // NOTE: pinch distance is calculated on two touch points TOUCH_MOVE - return pinchDistance; -} - -// Get number of touch points -int GetTouchPointsCount(void) -{ - // NOTE: point count is calculated when ProcessGestureEvent(GestureEvent event) is called - - return pointCount; + return pinchVector; } // Get angle beween two pinch points @@ -388,7 +396,7 @@ static float Vector2Distance(Vector2 v1, Vector2 v2) } // Time measure returned are milliseconds -static double GetCurrentTime() +static double GetCurrentTime(void) { double time = 0; diff --git a/src/gestures.h b/src/gestures.h index 52f778be..5468eb54 100644 --- a/src/gestures.h +++ b/src/gestures.h @@ -90,19 +90,19 @@ extern "C" { // Prevents name mangling of functions //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- +void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into 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 +int GetTouchPointsCount(void); // Get touch points count -float GetGestureDragIntensity(void); // Get gesture drag intensity -float GetGestureDragAngle(void); // Get gesture drag angle +float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds Vector2 GetGestureDragVector(void); // Get gesture drag vector -int GetGestureHoldDuration(void); // Get gesture hold time in frames -float GetGesturePinchDelta(void); // Get gesture pinch delta +float GetGestureDragAngle(void); // Get gesture drag angle +Vector2 GetGesturePinchVector(void); // Get gesture pinch delta float GetGesturePinchAngle(void); // Get gesture pinch angle -int GetTouchPointsCount(void); // Get touch points count + #ifdef __cplusplus } diff --git a/src/raylib.h b/src/raylib.h index f5a3cc31..def56ee2 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -607,19 +607,18 @@ bool IsButtonReleased(int button); // Detect if an android //------------------------------------------------------------------------------------ // Gestures and Touch Handling Functions (Module: gestures) //------------------------------------------------------------------------------------ +void ProcessGestureEvent(GestureEvent event); // Process gesture event and translate it into 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 +int GetTouchPointsCount(void); // Get touch points count -float GetGestureDragIntensity(void); // Get gesture drag intensity -float GetGestureDragAngle(void); // Get gesture drag angle +float GetGestureHoldDuration(void); // Get gesture hold time in milliseconds Vector2 GetGestureDragVector(void); // Get gesture drag vector -float GetGestureHoldDuration(void); // Get gesture hold time in ms -float GetGesturePinchDelta(void); // Get gesture pinch delta +float GetGestureDragAngle(void); // Get gesture drag angle +Vector2 GetGesturePinchVector(void); // Get gesture pinch delta float GetGesturePinchAngle(void); // Get gesture pinch angle -int GetTouchPointsCount(void); // Get touch points count //------------------------------------------------------------------------------------ // Camera System Functions (Module: camera) -- cgit v1.2.3 From 8aab52aeda47ce283d1446be27a7e2e20f027434 Mon Sep 17 00:00:00 2001 From: Ray San Date: Thu, 18 Feb 2016 14:05:48 +0100 Subject: Redesigned RPI input system -IN PROGRESS- --- examples/core_input_mouse.c | 14 +- examples/makefile | 10 +- src/core.c | 421 +++++++++++++++++++++++++++----------------- src/makefile | 8 +- src/raylib.h | 2 - 5 files changed, 279 insertions(+), 176 deletions(-) (limited to 'src/raylib.h') diff --git a/examples/core_input_mouse.c b/examples/core_input_mouse.c index 358b5fd6..24d2dfcd 100644 --- a/examples/core_input_mouse.c +++ b/examples/core_input_mouse.c @@ -21,6 +21,7 @@ int main() InitWindow(screenWidth, screenHeight, "raylib [core] example - mouse input"); Vector2 ballPosition = { -100.0f, -100.0f }; + Color ballColor = DARKBLUE; SetTargetFPS(60); //--------------------------------------------------------------------------------------- @@ -30,10 +31,11 @@ int main() { // Update //---------------------------------------------------------------------------------- - if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) - { - ballPosition = GetMousePosition(); - } + ballPosition = GetMousePosition(); + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) ballColor = MAROON; + else if (IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) ballColor = LIME; + else if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) ballColor = DARKBLUE; //---------------------------------------------------------------------------------- // Draw @@ -42,9 +44,9 @@ int main() ClearBackground(RAYWHITE); - DrawCircleV(ballPosition, 40, GOLD); + DrawCircleV(ballPosition, 40, ballColor); - DrawText("mouse click to draw the ball", 10, 10, 20, DARKGRAY); + DrawText("move ball with mouse and click mouse button to change color", 10, 10, 20, DARKGRAY); EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/examples/makefile b/examples/makefile index 62428155..2a9e88ba 100644 --- a/examples/makefile +++ b/examples/makefile @@ -227,10 +227,10 @@ core_mouse_wheel: core_mouse_wheel.c # compile [core] example - gamepad input core_input_gamepad: core_input_gamepad.c -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(PLATFORM), $(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_RPI)) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) else - @echo core_input_gamepad: Only supported on desktop platform + @echo core_input_gamepad: Example not supported on PLATFORM_ANDROID or PLATFORM_WEB endif # compile [core] example - generate random values @@ -246,15 +246,15 @@ core_drop_files: core_drop_files.c ifeq ($(PLATFORM),PLATFORM_DESKTOP) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) else - @echo core_drop_files: Only supported on desktop platform + @echo core_drop_files: Example not supported on PLATFORM_ANDROID or PLATFORM_WEB or PLATFORM_RPI endif # compile [core] example - storage values core_storage_values: core_storage_values.c -ifeq ($(PLATFORM),PLATFORM_DESKTOP) +ifeq ($(PLATFORM), $(filter $(PLATFORM),PLATFORM_DESKTOP PLATFORM_RPI)) $(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS) -D$(PLATFORM) $(WINFLAGS) else - @echo core_storage_values: Only supported on desktop platform + @echo core_storage_values: Example not supported on PLATFORM_ANDROID or PLATFORM_WEB endif # compile [core] example - gestures detection diff --git a/src/core.c b/src/core.c index 7b981097..c7d93355 100644 --- a/src/core.c +++ b/src/core.c @@ -102,11 +102,16 @@ #include "EGL/egl.h" // Khronos EGL library - Native platform display device control functions #include "EGL/eglext.h" // Khronos EGL library - Extensions #include "GLES2/gl2.h" // Khronos OpenGL ES 2.0 library + + // Old device inputs system + #define DEFAULT_KEYBOARD_DEV STDIN_FILENO // Standard input + #define DEFAULT_MOUSE_DEV "/dev/input/mouse0" + #define DEFAULT_GAMEPAD_DEV "/dev/input/js0" - #define DEFAULT_KEYBOARD_DEV "/dev/input/event0" // Not used, keyboard inputs are read raw from stdin - #define DEFAULT_MOUSE_DEV "/dev/input/event1" - //#define DEFAULT_MOUSE_DEV "/dev/input/mouse0" - #define DEFAULT_GAMEPAD_DEV "/dev/input/js0" + // New device input events (evdev) (must be detected) + //#define DEFAULT_KEYBOARD_DEV "/dev/input/eventN" + //#define DEFAULT_MOUSE_DEV "/dev/input/eventN" + //#define DEFAULT_GAMEPAD_DEV "/dev/input/eventN" #endif #if defined(PLATFORM_WEB) @@ -142,16 +147,11 @@ static int currentButtonState[128] = { 1 }; // Required to check if button p #elif defined(PLATFORM_RPI) static EGL_DISPMANX_WINDOW_T nativeWindow; // Native window (graphic device) -// Input variables (mouse/keyboard) -static int mouseStream = -1; // Mouse device file descriptor -static bool mouseReady = false; // Flag to know if mouse is ready -pthread_t mouseThreadId; // Mouse reading thread id - +// Keyboard input variables // NOTE: For keyboard we will use the standard input (but reconfigured...) +static struct termios defaultKeyboardSettings; // Used to store default keyboard settings static int defaultKeyboardMode; // Used to store default keyboard mode -static struct termios defaultKeyboardSettings; // Used to staore default keyboard settings - -static int keyboardMode = 0; // Keyboard mode: 1 - KEYCODES, 2 - ASCII +static int keyboardMode = 0; // Register Keyboard mode: 1 - KEYCODES, 2 - ASCII // This array maps Unix keycodes to ASCII equivalent and to GLFW3 equivalent for special function keys (>256) const short UnixKeycodeToASCII[128] = { 256, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 45, 61, 259, 9, 81, 87, 69, 82, 84, 89, 85, 73, 79, 80, 91, 93, 257, 341, 65, 83, 68, @@ -159,7 +159,15 @@ const short UnixKeycodeToASCII[128] = { 256, 49, 50, 51, 52, 53, 54, 55, 56, 57, 297, 298, 299, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 257, 345, 47, -1, 346, -1, -1, 265, -1, 263, 262, -1, 264, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; +// Mouse input variables +static int mouseStream = -1; // Mouse device file descriptor +static bool mouseReady = false; // Flag to know if mouse is ready +pthread_t mouseThreadId; // Mouse reading thread id + +// Gamepad input variables static int gamepadStream = -1; // Gamepad device file descriptor +static bool gamepadReady = false; // Flag to know if gamepad is ready +pthread_t gamepadThreadId; // Gamepad reading thread id #endif #if defined(PLATFORM_ANDROID) || defined(PLATFORM_RPI) @@ -244,11 +252,13 @@ static void LogoAnimation(void); // Plays raylib logo app static void SetupFramebufferSize(int displayWidth, int displayHeight); #if defined(PLATFORM_RPI) -static void InitMouse(void); // Mouse initialization (including mouse thread) -static void *MouseThread(void *arg); // Mouse reading thread static void InitKeyboard(void); // Init raw keyboard system (standard input reading) +static void ProcessKeyboard(void); // Process keyboard events static void RestoreKeyboard(void); // Restore keyboard system +static void InitMouse(void); // Mouse initialization (including mouse thread) +static void *MouseThread(void *arg); // Mouse reading thread static void InitGamepad(void); // Init raw gamepad input +static void *GamepadThread(void *arg); // Mouse reading thread #endif #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) @@ -1128,18 +1138,21 @@ bool IsCursorHidden() { return cursorHidden; } -#endif //defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) -// TODO: Enable gamepad usage on Rapsberry Pi -// NOTE: emscripten not implemented -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) +// NOTE: Gamepad support not implemented in emscripten GLFW3 (PLATFORM_WEB) + // Detect if a gamepad is available bool IsGamepadAvailable(int gamepad) { - int result = glfwJoystickPresent(gamepad); + bool result = false; + +#if defined(PLATFORM_RPI) + if (gamepadReady && (gamepad == 0)) result = true; +#else + if (glfwJoystickPresent(gamepad) == 1) result = true; +#endif - if (result == 1) return true; - else return false; + return result; } // Return axis movement vector for a gamepad @@ -1148,10 +1161,14 @@ Vector2 GetGamepadMovement(int gamepad) Vector2 vec = { 0, 0 }; const float *axes; - int axisCount; - + int axisCount = 0; + +#if defined(PLATFORM_RPI) + // TODO: Get gamepad axis information +#else axes = glfwGetJoystickAxes(gamepad, &axisCount); - +#endif + if (axisCount >= 2) { vec.x = axes[0]; // Left joystick X @@ -1184,16 +1201,20 @@ bool IsGamepadButtonPressed(int gamepad, int button) // Detect if a gamepad button is being pressed bool IsGamepadButtonDown(int gamepad, int button) { + bool result = false; const unsigned char *buttons; int buttonsCount; - + +#if defined(PLATFORM_RPI) + // TODO: Get gamepad buttons information +#else buttons = glfwGetJoystickButtons(gamepad, &buttonsCount); - if ((buttons != NULL) && (buttons[button] == GLFW_PRESS)) - { - return true; - } - else return false; + if ((buttons != NULL) && (buttons[button] == GLFW_PRESS)) result = true; + else result = false; +#endif + + return result; } // Detect if a gamepad button has NOT been pressed once @@ -1216,19 +1237,23 @@ bool IsGamepadButtonReleased(int gamepad, int button) // Detect if a mouse button is NOT being pressed bool IsGamepadButtonUp(int gamepad, int button) { + bool result = false; const unsigned char *buttons; int buttonsCount; +#if defined(PLATFORM_RPI) + // TODO: Get gamepad buttons information +#else buttons = glfwGetJoystickButtons(gamepad, &buttonsCount); - if ((buttons != NULL) && (buttons[button] == GLFW_RELEASE)) - { - return true; - } - else return false; -} + if ((buttons != NULL) && (buttons[button] == GLFW_RELEASE)) result = true; + else result = false; #endif + return result; +} +#endif //defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) || defined(PLATFORM_WEB) + // Returns touch position X int GetTouchX(void) { @@ -2157,7 +2182,68 @@ static void PollInputEvents(void) // NOTE: Keyboard reading could be done using input_event(s) reading or just read from stdin, // we use method 2 (stdin) but maybe in a future we should change to method 1... + ProcessKeyboard(); + + // NOTE: Gamepad (Joystick) input events polling is done asynchonously in another pthread - GamepadThread() + +#endif +} +#if defined(PLATFORM_RPI) +// Initialize Keyboard system (using standard input) +static void InitKeyboard(void) +{ + // NOTE: We read directly from Standard Input (stdin) - STDIN_FILENO file descriptor + + // Make stdin non-blocking (not enough, need to configure to non-canonical mode) + int flags = fcntl(STDIN_FILENO, F_GETFL, 0); // F_GETFL: Get the file access mode and the file status flags + fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK); // F_SETFL: Set the file status flags to the value specified + + // Save terminal keyboard settings and reconfigure terminal with new settings + struct termios keyboardNewSettings; + tcgetattr(STDIN_FILENO, &defaultKeyboardSettings); // Get current keyboard settings + keyboardNewSettings = defaultKeyboardSettings; + + // New terminal settings for keyboard: turn off buffering (non-canonical mode), echo and key processing + // NOTE: ISIG controls if ^C and ^Z generate break signals or not + keyboardNewSettings.c_lflag &= ~(ICANON | ECHO | ISIG); + //keyboardNewSettings.c_iflag &= ~(ISTRIP | INLCR | ICRNL | IGNCR | IXON | IXOFF); + keyboardNewSettings.c_cc[VMIN] = 1; + keyboardNewSettings.c_cc[VTIME] = 0; + + // Set new keyboard settings (change occurs immediately) + tcsetattr(STDIN_FILENO, TCSANOW, &keyboardNewSettings); + + // NOTE: Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE, we change that! -> WHY??? + + // Save old keyboard mode to restore it at the end + if (ioctl(STDIN_FILENO, KDGKBMODE, &defaultKeyboardMode) < 0) + { + // NOTE: It could mean we are using a remote keyboard through ssh! + TraceLog(WARNING, "Could not change keyboard mode (SSH keyboard?)"); + + keyboardMode = 2; // ASCII + } + else + { + // We reconfigure keyboard mode to get: + // - scancodes (K_RAW) + // - keycodes (K_MEDIUMRAW) + // - ASCII chars (K_XLATE) + // - UNICODE chars (K_UNICODE) + ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE); + + //http://lct.sourceforge.net/lct/x60.html + + keyboardMode = 2; // keycodes + } + + // Register keyboard restore when program finishes + atexit(RestoreKeyboard); +} + +static void ProcessKeyboard(void) +{ // Keyboard input polling (fill keys[256] array with status) int numKeysBuffer = 0; // Keys available on buffer char keysBuffer[32]; // Max keys to be read at a time @@ -2242,45 +2328,18 @@ static void PollInputEvents(void) } */ } +} - // TODO: Gamepad support (use events, easy!) -/* - struct js_event gamepadEvent; - - read(gamepadStream, &gamepadEvent, sizeof(struct js_event)); - - if (gamepadEvent.type == JS_EVENT_BUTTON) - { - switch (gamepadEvent.number) - { - case 0: // 1st Axis X - case 1: // 1st Axis Y - case 2: // 2st Axis X - case 3: // 2st Axis Y - case 4: - { - if (gamepadEvent.value == 1) // Button pressed, 0 release - - } break; - // Buttons is similar, variable for every joystick - } - } - else if (gamepadEvent.type == JS_EVENT_AXIS) - { - switch (gamepadEvent.number) - { - case 0: // 1st Axis X - case 1: // 1st Axis Y - case 2: // 2st Axis X - case 3: // 2st Axis Y - // Buttons is similar, variable for every joystick - } - } -*/ -#endif +// Restore default keyboard input +static void RestoreKeyboard(void) +{ + // Reset to default keyboard settings + tcsetattr(STDIN_FILENO, TCSANOW, &defaultKeyboardSettings); + + // Reconfigure keyboard to default mode + ioctl(STDIN_FILENO, KDSKBMODE, defaultKeyboardMode); } -#if defined(PLATFORM_RPI) // Mouse initialization (including mouse thread) static void InitMouse(void) { @@ -2305,118 +2364,156 @@ static void InitMouse(void) // if too much time passes between reads, queue gets full and new events override older ones... static void *MouseThread(void *arg) { - struct input_event mouseEvent; + const unsigned char XSIGN = 1<<4, YSIGN = 1<<5; + + typedef struct { + char buttons; + char dx, dy; + } MouseEvent; + + MouseEvent mouse; + + int mouseRelX = 0; + int mouseRelY = 0; while(1) { - // NOTE: read() will return -1 if the events queue is empty - read(mouseStream, &mouseEvent, sizeof(struct input_event)); - - // Check event types - if (mouseEvent.type == EV_REL) // Relative motion event + if (read(mouseStream, &mouse, sizeof(MouseEvent)) == (int)sizeof(MouseEvent)) { - if (mouseEvent.code == REL_X) - { - mousePosition.x += (float)mouseEvent.value; - - // Screen limits X check - if (mousePosition.x < 0) mousePosition.x = 0; - if (mousePosition.x > screenWidth) mousePosition.x = screenWidth; - } - - if (mouseEvent.code == REL_Y) - { - mousePosition.y += (float)mouseEvent.value; - - // Screen limits Y check - if (mousePosition.y < 0) mousePosition.y = 0; - if (mousePosition.y > screenHeight) mousePosition.y = screenHeight; - } + if ((mouse.buttons & 0x08) == 0) break; // This bit should always be set + + // Check Left button pressed + if ((mouse.buttons & 0x01) > 0) currentMouseState[0] = 1; + else currentMouseState[0] = 0; - if (mouseEvent.code == REL_WHEEL) - { - // mouseEvent.value give 1 or -1 (direction) - } - } - else if (mouseEvent.type == EV_KEY) // Mouse button event - { - if (mouseEvent.code == BTN_LEFT) currentMouseState[0] = mouseEvent.value; - if (mouseEvent.code == BTN_RIGHT) currentMouseState[1] = mouseEvent.value; - if (mouseEvent.code == BTN_MIDDLE) currentMouseState[2] = mouseEvent.value; - } + // Check Right button pressed + if ((mouse.buttons & 0x02) > 0) currentMouseState[1] = 1; + else currentMouseState[1] = 0; + + // Check Middle button pressed + if ((mouse.buttons & 0x04) > 0) currentMouseState[2] = 1; + else currentMouseState[2] = 0; + + mouseRelX = (int)mouse.dx; + mouseRelY = (int)mouse.dy; + + if ((mouse.buttons & XSIGN) > 0) mouseRelX = -1*(255 - mouseRelX); + if ((mouse.buttons & YSIGN) > 0) mouseRelY = -1*(255 - mouseRelY); + + mousePosition.x += (float)mouseRelX; + mousePosition.y -= (float)mouseRelY; + + if (mousePosition.x < 0) mousePosition.x = 0; + if (mousePosition.y < 0) mousePosition.y = 0; + + if (mousePosition.x > screenWidth) mousePosition.x = screenWidth; + if (mousePosition.y > screenHeight) mousePosition.y = screenHeight; + } + //else read(mouseStream, &mouse, 1); // Try to sync up again } return NULL; } -// Initialize Keyboard system (using standard input) -static void InitKeyboard(void) +// Init gamepad system +static void InitGamepad(void) { - // NOTE: We read directly from Standard Input (stdin) - STDIN_FILENO file descriptor - - // Make stdin non-blocking (not enough, need to configure to non-canonical mode) - int flags = fcntl(STDIN_FILENO, F_GETFL, 0); // F_GETFL: Get the file access mode and the file status flags - fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK); // F_SETFL: Set the file status flags to the value specified - - // Save terminal keyboard settings and reconfigure terminal with new settings - struct termios keyboardNewSettings; - tcgetattr(STDIN_FILENO, &defaultKeyboardSettings); // Get current keyboard settings - keyboardNewSettings = defaultKeyboardSettings; - - // New terminal settings for keyboard: turn off buffering (non-canonical mode), echo and key processing - // NOTE: ISIG controls if ^C and ^Z generate break signals or not - keyboardNewSettings.c_lflag &= ~(ICANON | ECHO | ISIG); - //keyboardNewSettings.c_iflag &= ~(ISTRIP | INLCR | ICRNL | IGNCR | IXON | IXOFF); - keyboardNewSettings.c_cc[VMIN] = 1; - keyboardNewSettings.c_cc[VTIME] = 0; - - // Set new keyboard settings (change occurs immediately) - tcsetattr(STDIN_FILENO, TCSANOW, &keyboardNewSettings); - - // NOTE: Reading directly from stdin will give chars already key-mapped by kernel to ASCII or UNICODE, we change that! -> WHY??? - - // Save old keyboard mode to restore it at the end - if (ioctl(STDIN_FILENO, KDGKBMODE, &defaultKeyboardMode) < 0) + if ((gamepadStream = open(DEFAULT_GAMEPAD_DEV, O_RDONLY|O_NONBLOCK)) < 0) { - // NOTE: It could mean we are using a remote keyboard through ssh! - TraceLog(WARNING, "Could not change keyboard mode (SSH keyboard?)"); - - keyboardMode = 2; // ASCII + TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available"); } else { - // We reconfigure keyboard mode to get: - // - scancodes (K_RAW) - // - keycodes (K_MEDIUMRAW) - // - ASCII chars (K_XLATE) - // - UNICODE chars (K_UNICODE) - ioctl(STDIN_FILENO, KDSKBMODE, K_MEDIUMRAW); - - //http://lct.sourceforge.net/lct/x60.html + gamepadReady = true; - keyboardMode = 1; // keycodes - } + int error = pthread_create(&gamepadThreadId, NULL, &GamepadThread, NULL); - // Register keyboard restore when program finishes - atexit(RestoreKeyboard); + if (error != 0) TraceLog(WARNING, "Error creating gamepad input event thread"); + else TraceLog(INFO, "Gamepad device initialized successfully"); + } } -// Restore default keyboard input -static void RestoreKeyboard(void) +// Process Gamepad (/dev/input/js0) +static void *GamepadThread(void *arg) { - // Reset to default keyboard settings - tcsetattr(STDIN_FILENO, TCSANOW, &defaultKeyboardSettings); + #define JS_EVENT_BUTTON 0x01 // Button pressed/released + #define JS_EVENT_AXIS 0x02 // Joystick axis moved + #define JS_EVENT_INIT 0x80 // Initial state of device + + struct js_event { + unsigned int time; // event timestamp in milliseconds + short value; // event value + unsigned char type; // event type + unsigned char number; // event axis/button number + }; + + // These values are sensible on Logitech Dual Action Rumble and Xbox360 controller + const int joystickAxisX = 0; + const int joystickAxisY = 1; + + // Read gamepad event + struct js_event gamepadEvent; + int bytes; - // Reconfigure keyboard to default mode - ioctl(STDIN_FILENO, KDSKBMODE, defaultKeyboardMode); -} + int buttons[11]; + int stickX; + int stickY; + + while (1) + { + if (read(gamepadStream, &gamepadEvent, sizeof(struct js_event)) == (int)sizeof(struct js_event)) + { + gamepadEvent.type &= ~JS_EVENT_INIT; // Ignore synthetic events + + // Process gamepad events by type + if (gamepadEvent.type == JS_EVENT_BUTTON) + { + if (gamepadEvent.number < 11) + { + switch (gamepadEvent.value) + { + case 0: + case 1: buttons[gamepadEvent.number] = gamepadEvent.value; break; + default: break; + } + } + /* + switch (gamepadEvent.number) + { + case 0: // 1st Axis X + case 1: // 1st Axis Y + case 2: // 2st Axis X + case 3: // 2st Axis Y + case 4: + { + if (gamepadEvent.value == 1) // Button pressed, 0 release + { + + } -// Init gamepad system -static void InitGamepad(void) -{ - // TODO: Add Gamepad support - if ((gamepadStream = open(DEFAULT_GAMEPAD_DEV, O_RDONLY|O_NONBLOCK)) < 0) TraceLog(WARNING, "Gamepad device could not be opened, no gamepad available"); - else TraceLog(INFO, "Gamepad device initialized successfully"); + } break; + // Buttons is similar, variable for every joystick + } + */ + } + else if (gamepadEvent.type == JS_EVENT_AXIS) + { + if (gamepadEvent.number == joystickAxisX) stickX = gamepadEvent.value; + if (gamepadEvent.number == joystickAxisY) stickY = gamepadEvent.value; + /* + switch (gamepadEvent.number) + { + case 0: // 1st Axis X + case 1: // 1st Axis Y + case 2: // 2st Axis X + case 3: // 2st Axis Y + // Buttons is similar, variable for every joystick + } + */ + } + } + else read(gamepadStream, &gamepadEvent, 1); // Try to sync up again + } } #endif diff --git a/src/makefile b/src/makefile index 4f65c440..2d73e646 100644 --- a/src/makefile +++ b/src/makefile @@ -91,7 +91,13 @@ else endif # define all object files required -OBJS = core.o rlgl.o glad.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o stb_vorbis.o +ifeq ($(PLATFORM),PLATFORM_DESKTOP) + OBJS = core.o rlgl.o glad.o shapes.o text.o textures.o models.o audio.o utils.o camera.o gestures.o stb_vorbis.o +else + #GLAD only required on desktop platform + OBJS = core.o rlgl.o shapes.o text.o textures.o models.o audio.o stb_vorbis.o utils.o camera.o gestures.o +endif + # typing 'make' will invoke the first target entry in the file, # in this case, the 'default' target entry is raylib diff --git a/src/raylib.h b/src/raylib.h index def56ee2..0dc8c6df 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -583,9 +583,7 @@ void HideCursor(void); // Hides cursor void EnableCursor(void); // Enables cursor void DisableCursor(void); // Disables cursor bool IsCursorHidden(void); // Returns true if cursor is not visible -#endif -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) bool IsGamepadAvailable(int gamepad); // Detect if a gamepad is available Vector2 GetGamepadMovement(int gamepad); // Return axis movement vector for a gamepad bool IsGamepadButtonPressed(int gamepad, int button); // Detect if a gamepad button has been pressed once -- cgit v1.2.3 From 98c60838fed28958519144840a21f012995d6799 Mon Sep 17 00:00:00 2001 From: Ray San Date: Fri, 19 Feb 2016 19:57:25 +0100 Subject: Reviewed RPI inputs --- src/core.c | 206 ++++++++++++++++++++++++++++------------------------------- src/raylib.h | 2 + 2 files changed, 98 insertions(+), 110 deletions(-) (limited to 'src/raylib.h') diff --git a/src/core.c b/src/core.c index 3bd36d08..dbcfa6bc 100644 --- a/src/core.c +++ b/src/core.c @@ -125,7 +125,7 @@ //#define DEFAULT_MOUSE_DEV "/dev/input/eventN" //#define DEFAULT_GAMEPAD_DEV "/dev/input/eventN" - #define MOUSE_SENSITIVITY 1.0f + #define MOUSE_SENSITIVITY 0.8f #define MAX_GAMEPAD_BUTTONS 11 #endif @@ -156,13 +156,6 @@ static EGL_DISPMANX_WINDOW_T nativeWindow; // Native window (graphic device // NOTE: For keyboard we will use the standard input (but reconfigured...) static struct termios defaultKeyboardSettings; // Used to store default keyboard settings static int defaultKeyboardMode; // Used to store default keyboard mode -static int keyboardMode = 0; // Register Keyboard mode: 1 - KEYCODES, 2 - ASCII - -// This array maps Unix keycodes to ASCII equivalent and to GLFW3 equivalent for special function keys (>256) -const short UnixKeycodeToASCII[128] = { 256, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 45, 61, 259, 9, 81, 87, 69, 82, 84, 89, 85, 73, 79, 80, 91, 93, 257, 341, 65, 83, 68, - 70, 71, 72, 74, 75, 76, 59, 39, 96, 340, 92, 90, 88, 67, 86, 66, 78, 77, 44, 46, 47, 344, -1, 342, 32, -1, 290, 291, 292, 293, 294, 295, 296, - 297, 298, 299, -1, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 257, 345, 47, -1, - 346, -1, -1, 265, -1, 263, 262, -1, 264, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; // Mouse input variables static int mouseStream = -1; // Mouse device file descriptor @@ -227,7 +220,9 @@ static int exitKey = KEY_ESCAPE; // Default exit key (ESC) static int lastKeyPressed = -1; // Register last key pressed static bool cursorHidden; // Track if cursor is hidden +#endif +#if defined(PLATFORM_DESKTOP) static char **dropFilesPath; // Store dropped files paths as strings static int dropFilesCount = 0; // Count stored strings #endif @@ -781,7 +776,7 @@ void ShowLogo(void) showLogo = true; } -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) +#if defined(PLATFORM_DESKTOP) // Check if a file have been dropped into window bool IsFileDropped(void) { @@ -1212,14 +1207,15 @@ bool IsGamepadButtonPressed(int gamepad, int button) bool IsGamepadButtonDown(int gamepad, int button) { bool result = false; - const unsigned char *buttons; - int buttonsCount; #if defined(PLATFORM_RPI) // Get gamepad buttons information if ((gamepad == 0) && (gamepadButtons[button] == 1)) result = true; else result = false; #else + const unsigned char *buttons; + int buttonsCount; + buttons = glfwGetJoystickButtons(gamepad, &buttonsCount); if ((buttons != NULL) && (buttons[button] == GLFW_PRESS)) result = true; @@ -1250,14 +1246,15 @@ bool IsGamepadButtonReleased(int gamepad, int button) bool IsGamepadButtonUp(int gamepad, int button) { bool result = false; - const unsigned char *buttons; - int buttonsCount; #if defined(PLATFORM_RPI) // Get gamepad buttons information if ((gamepad == 0) && (gamepadButtons[button] == 0)) result = true; else result = false; #else + const unsigned char *buttons; + int buttonsCount; + buttons = glfwGetJoystickButtons(gamepad, &buttonsCount); if ((buttons != NULL) && (buttons[button] == GLFW_RELEASE)) result = true; @@ -2235,8 +2232,6 @@ static void InitKeyboard(void) { // NOTE: It could mean we are using a remote keyboard through ssh! TraceLog(WARNING, "Could not change keyboard mode (SSH keyboard?)"); - - keyboardMode = 2; // ASCII } else { @@ -2246,102 +2241,108 @@ static void InitKeyboard(void) // - ASCII chars (K_XLATE) // - UNICODE chars (K_UNICODE) ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE); - - //http://lct.sourceforge.net/lct/x60.html - - keyboardMode = 2; // keycodes } // Register keyboard restore when program finishes atexit(RestoreKeyboard); } +// Process keyboard inputs +// TODO: Most probably input reading and processing should be in a separate thread static void ProcessKeyboard(void) { + #define MAX_KEYBUFFER_SIZE 32 // Max size in bytes to read + // Keyboard input polling (fill keys[256] array with status) - int numKeysBuffer = 0; // Keys available on buffer - char keysBuffer[32]; // Max keys to be read at a time + int bufferByteCount = 0; // Bytes available on the buffer + char keysBuffer[MAX_KEYBUFFER_SIZE]; // Max keys to be read at a time // Reset pressed keys array for (int i = 0; i < 512; i++) currentKeyState[i] = 0; // Read availables keycodes from stdin - numKeysBuffer = read(STDIN_FILENO, keysBuffer, 32); // POSIX system call + bufferByteCount = read(STDIN_FILENO, keysBuffer, MAX_KEYBUFFER_SIZE); // POSIX system call - // Fill array with pressed keys - for (int i = 0; i < numKeysBuffer; i++) + // Fill all read bytes (looking for keys) + for (int i = 0; i < bufferByteCount; i++) { - //TraceLog(INFO, "Bytes on keysBuffer: %i", numKeysBuffer); - - int key = keysBuffer[i]; + TraceLog(DEBUG, "Bytes on keysBuffer: %i", bufferByteCount); + + //printf("Key(s) bytes: "); + //for (int i = 0; i < bufferByteCount; i++) printf("0x%02x ", keysBuffer[i]); + //printf("\n"); - if (keyboardMode == 2) // ASCII chars (K_XLATE mode) + // 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 + if (keysBuffer[i] == 0x1b) { - // 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 - if (key == 0x1b) + // Detect ESC to stop program + if (bufferByteCount == 1) currentKeyState[256] = 1; // raylib key: KEY_ESCAPE + else { - if (keysBuffer[i+1] == 0x5b) // Special function key + if (keysBuffer[i + 1] == 0x5b) // Special function key { - switch (keysBuffer[i+2]) + if ((keysBuffer[i + 2] == 0x5b) || (keysBuffer[i + 2] == 0x31) || (keysBuffer[i + 2] == 0x32)) { - case 0x41: currentKeyState[265] = 1; break; - case 0x42: currentKeyState[264] = 1; break; - case 0x43: currentKeyState[262] = 1; break; - case 0x44: currentKeyState[263] = 1; break; - default: break; + // Process special function keys (F1 - F12) + switch (keysBuffer[i + 3]) + { + case 0x41: currentKeyState[290] = 1; break; // raylib KEY_F1 + case 0x42: currentKeyState[291] = 1; break; // raylib KEY_F2 + case 0x43: currentKeyState[292] = 1; break; // raylib KEY_F3 + case 0x44: currentKeyState[293] = 1; break; // raylib KEY_F4 + case 0x45: currentKeyState[294] = 1; break; // raylib KEY_F5 + case 0x37: currentKeyState[295] = 1; break; // raylib KEY_F6 + case 0x38: currentKeyState[296] = 1; break; // raylib KEY_F7 + case 0x39: currentKeyState[297] = 1; break; // raylib KEY_F8 + case 0x30: currentKeyState[298] = 1; break; // raylib KEY_F9 + case 0x31: currentKeyState[299] = 1; break; // raylib KEY_F10 + case 0x33: currentKeyState[300] = 1; break; // raylib KEY_F11 + case 0x34: currentKeyState[301] = 1; break; // raylib KEY_F12 + default: break; + } + + if (keysBuffer[i + 2] == 0x5b) i += 4; + else if ((keysBuffer[i + 2] == 0x31) || (keysBuffer[i + 2] == 0x32)) i += 5; } + else + { + switch (keysBuffer[i + 2]) + { + case 0x41: currentKeyState[265] = 1; break; // raylib KEY_UP + case 0x42: currentKeyState[264] = 1; break; // raylib KEY_DOWN + case 0x43: currentKeyState[262] = 1; break; // raylib KEY_RIGHT + case 0x44: currentKeyState[263] = 1; break; // raylib KEY_LEFT + default: break; + } - i += 2; // Jump to next key - - // NOTE: Other special function keys (F1, F2...) are not contempled for this keyboardMode... - // ...or they are just not directly keymapped (CTRL, ALT, SHIFT) + i += 3; // Jump to next key + } + + // NOTE: Some keys are not directly keymapped (CTRL, ALT, SHIFT) } } - else if (key == 0x0a) currentKeyState[257] = 1; // raylib KEY_ENTER (don't mix with KEY_*) - else if (key == 0x7f) currentKeyState[259] = 1; - else - { - TraceLog(DEBUG, "Pressed key (ASCII): 0x%02x", key); - - currentKeyState[key] = 1; - } - - // Detect ESC to stop program - if ((key == 0x1b) && (numKeysBuffer == 1)) windowShouldClose = true; } - else if (keyboardMode == 1) // keycodes (K_MEDIUMRAW mode) + else if (keysBuffer[i] == 0x0a) currentKeyState[257] = 1; // raylib KEY_ENTER (don't mix with KEY_*) + else if (keysBuffer[i] == 0x7f) currentKeyState[259] = 1; // raylib KEY_BACKSPACE + else { - 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) + TraceLog(DEBUG, "Pressed key (ASCII): 0x%02x", keysBuffer[i]); - // TODO: Review (or rewrite) this code... not clear... replace by events! - - int asciiKey = -1; - - // Convert keycode to some recognized key (ASCII or GLFW3 equivalent) - if (key < 128) asciiKey = (int)UnixKeycodeToASCII[key]; - - // Record equivalent key state - if ((asciiKey >= 0) && (asciiKey < 512)) currentKeyState[asciiKey] = 1; - - // In case of letter, we also activate lower case version - if ((asciiKey >= 65) && (asciiKey <=90)) currentKeyState[asciiKey + 32] = 1; - - // Detect KEY_ESC to stop program - if (key == 0x01) windowShouldClose = true; - } - - // Same functionality as GLFW3 KeyCallback() - /* - if (asciiKey == exitKey) windowShouldClose = true; - else if (key == GLFW_KEY_F12 && action == GLFW_PRESS) - { - TakeScreenshot(); + // Translate lowercase a-z letters to A-Z + if ((keysBuffer[i] >= 97) && (keysBuffer[i] <= 122)) + { + currentKeyState[(int)keysBuffer[i] - 32] = 1; + } + else currentKeyState[(int)keysBuffer[i]] = 1; } - */ } + + // Check exit key (same functionality as GLFW3 KeyCallback()) + if (currentKeyState[exitKey] == 1) windowShouldClose = true; + + // Check screen capture key + if (currentKeyState[301] == 1) TakeScreenshot(); // raylib key: KEY_F12 (GLFW_KEY_F12) } // Restore default keyboard input @@ -2414,10 +2415,12 @@ static void *MouseThread(void *arg) if ((mouse.buttons & XSIGN) > 0) mouseRelX = -1*(255 - mouseRelX); if ((mouse.buttons & YSIGN) > 0) mouseRelY = -1*(255 - mouseRelY); - // TODO: Mouse movement should not depend on screenWidth and screenHeight, normalize! - - mousePosition.x += (float)mouseRelX/MOUSE_SENSITIVITY; - mousePosition.y -= (float)mouseRelY/MOUSE_SENSITIVITY; + // NOTE: Mouse movement is normalized to not be screen resolution dependant + // We suppose 2*255 (max relative movement) is equivalent to screenWidth (max pixels width) + // Result after normalization is multiplied by MOUSE_SENSITIVITY factor + + mousePosition.x += (float)mouseRelX*((float)screenWidth/(2*255))*MOUSE_SENSITIVITY; + mousePosition.y -= (float)mouseRelY*((float)screenHeight/(2*255))*MOUSE_SENSITIVITY; if (mousePosition.x < 0) mousePosition.x = 0; if (mousePosition.y < 0) mousePosition.y = 0; @@ -2479,36 +2482,18 @@ static void *GamepadThread(void *arg) // Process gamepad events by type if (gamepadEvent.type == JS_EVENT_BUTTON) { + TraceLog(DEBUG, "Gamepad button: %i, value: %i", gamepadEvent.number, gamepadEvent.value); + if (gamepadEvent.number < MAX_GAMEPAD_BUTTONS) { - switch (gamepadEvent.value) - { - case 0: - case 1: gamepadButtons[gamepadEvent.number] = (int)gamepadEvent.value; break; - default: break; - } + // 1 - button pressed, 0 - button released + gamepadButtons[gamepadEvent.number] = (int)gamepadEvent.value; } - /* - switch (gamepadEvent.number) - { - case 0: // 1st Axis X - case 1: // 1st Axis Y - case 2: // 2st Axis X - case 3: // 2st Axis Y - case 4: - { - if (gamepadEvent.value == 1) // Button pressed, 0 release - { - - } - - } break; - // Buttons is similar, variable for every joystick - } - */ } else if (gamepadEvent.type == JS_EVENT_AXIS) { + TraceLog(DEBUG, "Gamepad axis: %i, value: %i", gamepadEvent.number, gamepadEvent.value); + if (gamepadEvent.number == joystickAxisX) gamepadAxisX = (int)gamepadEvent.value; if (gamepadEvent.number == joystickAxisY) gamepadAxisY = (int)gamepadEvent.value; /* @@ -2518,12 +2503,13 @@ static void *GamepadThread(void *arg) case 1: // 1st Axis Y case 2: // 2st Axis X case 3: // 2st Axis Y - // Buttons is similar, variable for every joystick } */ } } } + + return NULL; } #endif diff --git a/src/raylib.h b/src/raylib.h index 0dc8c6df..c4d4392d 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -111,6 +111,8 @@ #define KEY_F8 297 #define KEY_F9 298 #define KEY_F10 299 +#define KEY_F11 300 +#define KEY_F12 301 #define KEY_LEFT_SHIFT 340 #define KEY_LEFT_CONTROL 341 #define KEY_LEFT_ALT 342 -- cgit v1.2.3 From 2cc05e5e9243645aad810fee86465d4e84c81816 Mon Sep 17 00:00:00 2001 From: raysan5 Date: Sun, 21 Feb 2016 16:19:31 +0100 Subject: Corrected typo --- src/raylib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/raylib.h') diff --git a/src/raylib.h b/src/raylib.h index c4d4392d..c598ec30 100644 --- a/src/raylib.h +++ b/src/raylib.h @@ -697,7 +697,7 @@ void ImageFlipVertical(Image *image); 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 ImageColorGrayscale(Image *image); // Modify image 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 -- cgit v1.2.3