h-raylib 4.5.0.4 → 4.5.0.5
raw patch · 14 files changed
+683/−255 lines, 14 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Raylib: c'drawTexturePoly :: Ptr Texture -> Ptr Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CInt -> Ptr Color -> IO ()
- Raylib: c'drawTextureQuad :: Ptr Texture -> Ptr Vector2 -> Ptr Vector2 -> Ptr Rectangle -> Ptr Color -> IO ()
- Raylib: c'drawTextureTiled :: Ptr Texture -> Ptr Rectangle -> Ptr Rectangle -> Ptr Vector2 -> CFloat -> CFloat -> Ptr Color -> IO ()
- Raylib: drawTexturePoly :: Texture -> Vector2 -> [Vector2] -> [Vector2] -> Color -> IO ()
- Raylib: drawTextureQuad :: Texture -> Vector2 -> Vector2 -> Rectangle -> Color -> IO ()
- Raylib: drawTextureTiled :: Texture -> Rectangle -> Rectangle -> Vector2 -> Float -> Float -> Color -> IO ()
- Raylib: p'drawTexturePoly :: FunPtr (Texture -> Vector2 -> Ptr Vector2 -> Ptr Vector2 -> CInt -> Color -> IO ())
- Raylib: p'drawTextureQuad :: FunPtr (Texture -> Vector2 -> Vector2 -> Rectangle -> Color -> IO ())
- Raylib: p'drawTextureTiled :: FunPtr (Texture -> Rectangle -> Rectangle -> Vector2 -> CFloat -> CFloat -> Color -> IO ())
- Raylib.Types: [raycollision'distance] :: RayCollision -> CFloat
- Raylib.Types: [raycollision'hit] :: RayCollision -> CInt
+ Raylib: c'drawCapsule :: Ptr Vector3 -> Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()
+ Raylib: c'drawCapsuleWires :: Ptr Vector3 -> Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO ()
+ Raylib: c'genImageText :: CInt -> CInt -> CString -> IO (Ptr Image)
+ Raylib: c'imageBlurGaussian :: Ptr Image -> CInt -> IO ()
+ Raylib: drawCapsule :: Vector3 -> Vector3 -> CFloat -> CInt -> CInt -> Color -> IO ()
+ Raylib: drawCapsuleWires :: Vector3 -> Vector3 -> CFloat -> CInt -> CInt -> Color -> IO ()
+ Raylib: genImageText :: Int -> Int -> String -> IO Image
+ Raylib: imageBlurGaussian :: Image -> Int -> IO Image
+ Raylib: p'drawCapsule :: FunPtr (Vector3 -> Vector3 -> CFloat -> CInt -> CInt -> Color -> IO ())
+ Raylib: p'drawCapsuleWires :: FunPtr (Vector3 -> Vector3 -> CFloat -> CInt -> CInt -> Color -> IO ())
+ Raylib: p'genImageText :: FunPtr (CInt -> CInt -> CString -> IO Image)
+ Raylib: p'imageBlurGaussian :: FunPtr (Ptr Image -> CInt -> IO ())
+ Raylib.Types: [rayCollision'distance] :: RayCollision -> CFloat
+ Raylib.Types: [rayCollision'hit] :: RayCollision -> CBool
- Raylib: c'exportDataAsCode :: CString -> CUInt -> CString -> IO CBool
+ Raylib: c'exportDataAsCode :: Ptr CUChar -> CUInt -> CString -> IO CBool
- Raylib: exportDataAsCode :: String -> Integer -> String -> IO Bool
+ Raylib: exportDataAsCode :: [Integer] -> Integer -> String -> IO Bool
- Raylib.Types: RayCollision :: CInt -> CFloat -> Vector3 -> Vector3 -> RayCollision
+ Raylib.Types: RayCollision :: CBool -> CFloat -> Vector3 -> Vector3 -> RayCollision
- Raylib.Types: p'RayCollision'hit :: Ptr RayCollision -> Ptr CInt
+ Raylib.Types: p'RayCollision'hit :: Ptr RayCollision -> Ptr CBool
Files
- CHANGELOG.md +7/−2
- h-raylib.cabal +1/−1
- lib/bindings.c +17/−15
- lib/bindings.h +6/−6
- raylib/src/external/miniaudio.h too large to diff
- raylib/src/external/vox_loader.h +6/−11
- raylib/src/raylib.h +11/−10
- raylib/src/rcore.c +16/−13
- raylib/src/rmodels.c +294/−15
- raylib/src/rshapes.c +97/−16
- raylib/src/rtextures.c +179/−131
- raylib/src/utils.c +1/−1
- src/Raylib.hs +43/−30
- src/Raylib/Types.hs +5/−4
CHANGELOG.md view
@@ -2,5 +2,10 @@ ## Version 4.5.0.4 _13 November 2022_ -- Replaced CInt with CBool for functions that return booleans -- Removed Xext dependency (it is no longer required for Nix builds)+- Replaced `CInt` with `CBool` for functions that return booleans +- Removed `Xext` dependency (it is no longer required for Nix builds) + +## Version 4.5.0.5 +_19 November 2022_ +- Replaced `CInt` with `CBool` in `RayCollision` +- Updated raylib to the master branch
h-raylib.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: h-raylib -version: 4.5.0.4 +version: 4.5.0.5 synopsis: Raylib bindings for Haskell category: graphics description:
lib/bindings.c view
@@ -599,6 +599,13 @@ return ptr; } +Image *GenImageText_(int a, int b, char *c) +{ + Image *ptr = (Image *)malloc(sizeof(Image)); + *ptr = GenImageText(a, b, c); + return ptr; +} + Image *ImageCopy_(Image *a) { Image *ptr = (Image *)malloc(sizeof(Image)); @@ -844,16 +851,6 @@ DrawTextureRec(*a, *b, *c, *d); } -void DrawTextureQuad_(Texture *a, Vector2 *b, Vector2 *c, Rectangle *d, Color *e) -{ - DrawTextureQuad(*a, *b, *c, *d, *e); -} - -void DrawTextureTiled_(Texture *a, Rectangle *b, Rectangle *c, Vector2 *d, float e, float f, Color *g) -{ - DrawTextureTiled(*a, *b, *c, *d, e, f, *g); -} - void DrawTexturePro_(Texture *a, Rectangle *b, Rectangle *c, Vector2 *d, float e, Color *f) { DrawTexturePro(*a, *b, *c, *d, e, *f); @@ -864,11 +861,6 @@ DrawTextureNPatch(*a, *b, *c, *d, e, *f); } -void DrawTexturePoly_(Texture *a, Vector2 *b, Vector2 *c, Vector2 *d, int e, Color *f) -{ - DrawTexturePoly(*a, *b, c, d, e, *f); -} - Color *Fade_(Color *a, float b) { Color *ptr = (Color *)malloc(sizeof(Color)); @@ -1133,6 +1125,16 @@ void DrawCylinderWiresEx_(Vector3 *a, Vector3 *b, float c, float d, int e, Color *f) { DrawCylinderWiresEx(*a, *b, c, d, e, *f); +} + +void DrawCapsule_(Vector3 *a, Vector3 *b, float c, int d, int e, Color *f) +{ + DrawCapsule(*a, *b, c, d, e, *f); +} + +void DrawCapsuleWires_(Vector3 *a, Vector3 *b, float c, int d, int e, Color *f) +{ + DrawCapsuleWires(*a, *b, c, d, e, *f); } void DrawPlane_(Vector3 *a, Vector2 *b, Color *c)
lib/bindings.h view
@@ -218,6 +218,8 @@ Image *GenImageCellular_(int a, int b, int c); +Image *GenImageText_(int a, int b, char *c); + Image *ImageCopy_(Image *a); Image *ImageFromImage_(Image *a, Rectangle *b); @@ -308,16 +310,10 @@ void DrawTextureRec_(Texture *a, Rectangle *b, Vector2 *c, Color *d); -void DrawTextureQuad_(Texture *a, Vector2 *b, Vector2 *c, Rectangle *d, Color *e); - -void DrawTextureTiled_(Texture *a, Rectangle *b, Rectangle *c, Vector2 *d, float e, float f, Color *g); - void DrawTexturePro_(Texture *a, Rectangle *b, Rectangle *c, Vector2 *d, float e, Color *f); void DrawTextureNPatch_(Texture *a, NPatchInfo *b, Rectangle *c, Vector2 *d, float e, Color *f); -void DrawTexturePoly_(Texture *a, Vector2 *b, Vector2 *c, Vector2 *d, int e, Color *f); - Color *Fade_(Color *a, float b); int ColorToInt_(Color *a); @@ -409,6 +405,10 @@ void DrawCylinderWires_(Vector3 *a, float b, float c, float d, int e, Color *f); void DrawCylinderWiresEx_(Vector3 *a, Vector3 *b, float c, float d, int e, Color *f); + +void DrawCapsule_(Vector3 *a, Vector3 *b, float c, int d, int e, Color *f); + +void DrawCapsuleEx_(Vector3 *a, Vector3 *b, float c, int d, int e, Color *f); void DrawPlane_(Vector3 *a, Vector2 *b, Color *c);
raylib/src/external/miniaudio.h view
file too large to diff
raylib/src/external/vox_loader.h view
@@ -67,7 +67,7 @@ #define VOX_SUCCESS (0) #define VOX_ERROR_FILE_NOT_FOUND (-1) #define VOX_ERROR_INVALID_FORMAT (-2) -#define VOX_ERROR_FILE_VERSION_TOO_OLD (-3) +#define VOX_ERROR_FILE_VERSION_NOT_MATCH (-3) // VoxColor, 4 components, R8G8B8A8 (32bit) typedef struct { @@ -538,31 +538,26 @@ // @raysan5: Reviewed (unsigned long) -> (unsigned int), possible issue with Ubuntu 18.04 64bit // @raysan5: reviewed signature loading - unsigned char signature[4] = { 0 }; unsigned char* fileData = pvoxData; unsigned char* fileDataPtr = fileData; unsigned char* endfileDataPtr = fileData + voxDataSize; - signature[0] = fileDataPtr[0]; - signature[1] = fileDataPtr[1]; - signature[2] = fileDataPtr[2]; - signature[3] = fileDataPtr[3]; - fileDataPtr += 4; - - if ((signature[0] != 'V') && (signature[0] != 'O') && (signature[0] != 'X') && (signature[0] != ' ')) + if (strncmp((char*)fileDataPtr, "VOX ", 4) != 0) { return VOX_ERROR_INVALID_FORMAT; //"Not an MagicaVoxel File format" } + fileDataPtr += 4; + // @raysan5: reviewed version loading unsigned int version = 0; version = ((unsigned int*)fileDataPtr)[0]; fileDataPtr += 4; - if (version < 150) + if (version != 150) { - return VOX_ERROR_FILE_VERSION_TOO_OLD; //"MagicaVoxel version too old" + return VOX_ERROR_FILE_VERSION_NOT_MATCH; //"MagicaVoxel version doesn't match" }
raylib/src/raylib.h view
@@ -364,7 +364,7 @@ float params[4]; // Material generic parameters (if required) } Material; -// Transform, vectex transformation data +// Transform, vertex transformation data typedef struct Transform { Vector3 translation; // Translation Quaternion rotation; // Rotation @@ -1058,7 +1058,7 @@ RLAPI unsigned char *LoadFileData(const char *fileName, unsigned int *bytesRead); // Load file data as byte array (read) RLAPI void UnloadFileData(unsigned char *data); // Unload file data allocated by LoadFileData() RLAPI bool SaveFileData(const char *fileName, void *data, unsigned int bytesToWrite); // Save data to file from byte array (write), returns true on success -RLAPI bool ExportDataAsCode(const char *data, unsigned int size, const char *fileName); // Export data to code (.h), returns true on success +RLAPI bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *fileName); // Export data to code (.h), returns true on success RLAPI char *LoadFileText(const char *fileName); // Load text data from file (read), returns a '\0' terminated string RLAPI void UnloadFileText(char *text); // Unload file text data allocated by LoadFileText() RLAPI bool SaveFileText(const char *fileName, char *text); // Save text data to file (write), string must be '\0' terminated, returns true on success @@ -1244,6 +1244,7 @@ RLAPI Image GenImageWhiteNoise(int width, int height, float factor); // Generate image: white noise RLAPI Image GenImagePerlinNoise(int width, int height, int offsetX, int offsetY, float scale); // Generate image: perlin noise RLAPI Image GenImageCellular(int width, int height, int tileSize); // Generate image: cellular algorithm, bigger tileSize means bigger cells +RLAPI Image GenImageText(int width, int height, const char *text); // Generate image: grayscale image from text data // Image manipulation functions RLAPI Image ImageCopy(Image image); // Create an image duplicate (useful for transformations) @@ -1257,6 +1258,7 @@ RLAPI void ImageAlphaClear(Image *image, Color color, float threshold); // Clear alpha channel to desired color RLAPI void ImageAlphaMask(Image *image, Image alphaMask); // Apply alpha mask to image RLAPI void ImageAlphaPremultiply(Image *image); // Premultiply alpha channel +RLAPI void ImageBlurGaussian(Image *image, int blurSize); // Apply Gaussian blur using a box blur approximation RLAPI void ImageResize(Image *image, int newWidth, int newHeight); // Resize image (Bicubic scaling algorithm) RLAPI void ImageResizeNN(Image *image, int newWidth,int newHeight); // Resize image (Nearest-Neighbor scaling algorithm) RLAPI void ImageResizeCanvas(Image *image, int newWidth, int newHeight, int offsetX, int offsetY, Color fill); // Resize canvas and fill with color @@ -1319,11 +1321,8 @@ RLAPI void DrawTextureV(Texture2D texture, Vector2 position, Color tint); // Draw a Texture2D with position defined as Vector2 RLAPI void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, float scale, Color tint); // Draw a Texture2D with extended parameters RLAPI void DrawTextureRec(Texture2D texture, Rectangle source, Vector2 position, Color tint); // Draw a part of a texture defined by a rectangle -RLAPI void DrawTextureQuad(Texture2D texture, Vector2 tiling, Vector2 offset, Rectangle quad, Color tint); // Draw texture quad with tiling and offset parameters -RLAPI void DrawTextureTiled(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, float scale, Color tint); // Draw part of a texture (defined by a rectangle) with rotation and scale tiled into dest. -RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters -RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely -RLAPI void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2 *texcoords, int pointCount, Color tint); // Draw a textured polygon +RLAPI void DrawTexturePro(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draw a part of a texture defined by a rectangle with 'pro' parameters +RLAPI void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint); // Draws a texture (or part of it) that stretches or shrinks nicely // Color/pixel related functions RLAPI Color Fade(Color color, float alpha); // Get color with alpha applied, alpha goes from 0.0f to 1.0f @@ -1422,6 +1421,8 @@ RLAPI void DrawCylinderEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder with base at startPos and top at endPos RLAPI void DrawCylinderWires(Vector3 position, float radiusTop, float radiusBottom, float height, int slices, Color color); // Draw a cylinder/cone wires RLAPI void DrawCylinderWiresEx(Vector3 startPos, Vector3 endPos, float startRadius, float endRadius, int sides, Color color); // Draw a cylinder wires with base at startPos and top at endPos +RLAPI void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw a capsule with the center of its sphere caps at startPos and endPos +RLAPI void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color); // Draw capsule wireframe with the center of its sphere caps at startPos and endPos RLAPI void DrawPlane(Vector3 centerPos, Vector2 size, Color color); // Draw a plane XZ RLAPI void DrawRay(Ray ray, Color color); // Draw a ray line RLAPI void DrawGrid(int slices, float spacing); // Draw a grid (centered at (0, 0, 0)) @@ -1438,11 +1439,11 @@ RLAPI BoundingBox GetModelBoundingBox(Model model); // Compute model bounding box limits (considers all meshes) // Model drawing functions -RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) +RLAPI void DrawModel(Model model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set) RLAPI void DrawModelEx(Model model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters -RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) +RLAPI void DrawModelWires(Model model, Vector3 position, float scale, Color tint); // Draw a model wires (with texture if set) RLAPI 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 -RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) +RLAPI void DrawBoundingBox(BoundingBox box, Color color); // Draw bounding box (wires) RLAPI void DrawBillboard(Camera camera, Texture2D texture, Vector3 position, float size, Color tint); // Draw a billboard texture RLAPI void DrawBillboardRec(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector2 size, Color tint); // Draw a billboard texture defined by source RLAPI void DrawBillboardPro(Camera camera, Texture2D texture, Rectangle source, Vector3 position, Vector3 up, Vector2 size, Vector2 origin, float rotation, Color tint); // Draw a billboard texture defined by source and rotation
raylib/src/rcore.c view
@@ -1937,18 +1937,6 @@ #endif } -// Enable waiting for events on EndDrawing(), no automatic event polling -void EnableEventWaiting(void) -{ - CORE.Window.eventWaiting = true; -} - -// Disable waiting for events on EndDrawing(), automatic events polling -void DisableEventWaiting(void) -{ - CORE.Window.eventWaiting = false; -} - // Get clipboard text content // NOTE: returned string is allocated and freed by GLFW const char *GetClipboardText(void) @@ -1962,6 +1950,18 @@ return NULL; } +// Enable waiting for events on EndDrawing(), no automatic event polling +void EnableEventWaiting(void) +{ + CORE.Window.eventWaiting = true; +} + +// Disable waiting for events on EndDrawing(), automatic events polling +void DisableEventWaiting(void) +{ + CORE.Window.eventWaiting = false; +} + // Show mouse cursor void ShowCursor(void) { @@ -3288,6 +3288,9 @@ // Decompress data from a valid DEFLATE stream data = RL_CALLOC(MAX_DECOMPRESSION_SIZE*1024*1024, 1); int length = sinflate(data, MAX_DECOMPRESSION_SIZE*1024*1024, compData, compDataSize); + + // WARNING: RL_REALLOC can make (and leave) data copies in memory, be careful with sensitive compressed data! + // TODO: Use a different approach, create another buffer, copy data manually to it and wipe original buffer memory unsigned char *temp = RL_REALLOC(data, length); if (temp != NULL) data = temp; @@ -3411,7 +3414,7 @@ else { #if defined(PLATFORM_DESKTOP) - char *cmd = (char *)RL_CALLOC(strlen(url) + 10, sizeof(char)); + char *cmd = (char *)RL_CALLOC(strlen(url) + 32, sizeof(char)); #if defined(_WIN32) sprintf(cmd, "explorer \"%s\"", url); #endif
raylib/src/rmodels.c view
@@ -817,6 +817,284 @@ rlEnd(); } +// Draw a capsule with the center of its sphere caps at startPos and endPos +void DrawCapsule(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color) +{ + if (slices < 3) slices = 3; + + Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z }; + + // draw a sphere if start and end points are the same + bool sphereCase = (direction.x == 0) && (direction.y == 0) && (direction.z == 0); + if (sphereCase) direction = (Vector3){0.0f, 1.0f, 0.0f}; + + // Construct a basis of the base and the caps: + Vector3 b0 = Vector3Normalize(direction); + Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction)); + Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction)); + Vector3 capCenter = endPos; + + float baseSliceAngle = (2.0f*PI)/slices; + float baseRingAngle = PI * 0.5 / rings; + + rlBegin(RL_TRIANGLES); + rlColor4ub(color.r, color.g, color.b, color.a); + + // render both caps + for (int c = 0; c < 2; c++) + { + for (int i = 0; i < rings; i++) + { + for (int j = 0; j < slices; j++) + { + + // we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier + + // as we iterate through the rings they must be placed higher above the center, the height we need is sin(angle(i)) + // as we iterate through the rings they must get smaller by the cos(angle(i)) + + // compute the four vertices + float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 )); + float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 )); + Vector3 w1 = (Vector3){ + capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin1*b1.x + ringCos1*b2.x) * radius, + capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y) * radius, + capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin1*b1.z + ringCos1*b2.z) * radius + }; + float ringSin2 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 )); + float ringCos2 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 )); + Vector3 w2 = (Vector3){ + capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x) * radius, + capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y) * radius, + capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z) * radius + }; + + float ringSin3 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 )); + float ringCos3 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 )); + Vector3 w3 = (Vector3){ + capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x) * radius, + capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y) * radius, + capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z) * radius + }; + float ringSin4 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 )); + float ringCos4 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 )); + Vector3 w4 = (Vector3){ + capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x) * radius, + capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y) * radius, + capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z) * radius + }; + + // make sure cap triangle normals are facing outwards + if(c == 0) + { + rlVertex3f(w1.x, w1.y, w1.z); + rlVertex3f(w2.x, w2.y, w2.z); + rlVertex3f(w3.x, w3.y, w3.z); + + rlVertex3f(w2.x, w2.y, w2.z); + rlVertex3f(w4.x, w4.y, w4.z); + rlVertex3f(w3.x, w3.y, w3.z); + } + else + { + rlVertex3f(w1.x, w1.y, w1.z); + rlVertex3f(w3.x, w3.y, w3.z); + rlVertex3f(w2.x, w2.y, w2.z); + + rlVertex3f(w2.x, w2.y, w2.z); + rlVertex3f(w3.x, w3.y, w3.z); + rlVertex3f(w4.x, w4.y, w4.z); + } + } + } + capCenter = startPos; + b0 = Vector3Scale(b0, -1.0f); + } + // render middle + if (!sphereCase) + { + for (int j = 0; j < slices; j++) + { + // compute the four vertices + float ringSin1 = sinf(baseSliceAngle*(j + 0))*radius; + float ringCos1 = cosf(baseSliceAngle*(j + 0))*radius; + Vector3 w1 = { + startPos.x + ringSin1*b1.x + ringCos1*b2.x, + startPos.y + ringSin1*b1.y + ringCos1*b2.y, + startPos.z + ringSin1*b1.z + ringCos1*b2.z + }; + float ringSin2 = sinf(baseSliceAngle*(j + 1))*radius; + float ringCos2 = cosf(baseSliceAngle*(j + 1))*radius; + Vector3 w2 = { + startPos.x + ringSin2*b1.x + ringCos2*b2.x, + startPos.y + ringSin2*b1.y + ringCos2*b2.y, + startPos.z + ringSin2*b1.z + ringCos2*b2.z + }; + + float ringSin3 = sinf(baseSliceAngle*(j + 0))*radius; + float ringCos3 = cosf(baseSliceAngle*(j + 0))*radius; + Vector3 w3 = { + endPos.x + ringSin3*b1.x + ringCos3*b2.x, + endPos.y + ringSin3*b1.y + ringCos3*b2.y, + endPos.z + ringSin3*b1.z + ringCos3*b2.z + }; + float ringSin4 = sinf(baseSliceAngle*(j + 1))*radius; + float ringCos4 = cosf(baseSliceAngle*(j + 1))*radius; + Vector3 w4 = { + endPos.x + ringSin4*b1.x + ringCos4*b2.x, + endPos.y + ringSin4*b1.y + ringCos4*b2.y, + endPos.z + ringSin4*b1.z + ringCos4*b2.z + }; + // w2 x.-----------x startPos + rlVertex3f(w1.x, w1.y, w1.z); // | |\'. T0 / + rlVertex3f(w2.x, w2.y, w2.z); // T1 | \ '. / + rlVertex3f(w3.x, w3.y, w3.z); // | |T \ '. / + // | 2 \ T 'x w1 + rlVertex3f(w2.x, w2.y, w2.z); // | w4 x.---\-1-|---x endPos + rlVertex3f(w4.x, w4.y, w4.z); // T2 '. \ |T3/ + rlVertex3f(w3.x, w3.y, w3.z); // | '. \ | / + // '.\|/ + // 'x w3 + } + } + rlEnd(); +} + +// Draw capsule wires with the center of its sphere caps at startPos and endPos +void DrawCapsuleWires(Vector3 startPos, Vector3 endPos, float radius, int slices, int rings, Color color) +{ + if (slices < 3) slices = 3; + + Vector3 direction = { endPos.x - startPos.x, endPos.y - startPos.y, endPos.z - startPos.z }; + + // draw a sphere if start and end points are the same + bool sphereCase = (direction.x == 0) && (direction.y == 0) && (direction.z == 0); + if (sphereCase) direction = (Vector3){0.0f, 1.0f, 0.0f}; + + // Construct a basis of the base and the caps: + Vector3 b0 = Vector3Normalize(direction); + Vector3 b1 = Vector3Normalize(Vector3Perpendicular(direction)); + Vector3 b2 = Vector3Normalize(Vector3CrossProduct(b1, direction)); + Vector3 capCenter = endPos; + + float baseSliceAngle = (2.0f*PI)/slices; + float baseRingAngle = PI * 0.5 / rings; + + rlBegin(RL_LINES); + rlColor4ub(color.r, color.g, color.b, color.a); + + // render both caps + for (int c = 0; c < 2; c++) + { + for (int i = 0; i < rings; i++) + { + for (int j = 0; j < slices; j++) + { + + // we build up the rings from capCenter in the direction of the 'direction' vector we computed earlier + + // as we iterate through the rings they must be placed higher above the center, the height we need is sin(angle(i)) + // as we iterate through the rings they must get smaller by the cos(angle(i)) + + // compute the four vertices + float ringSin1 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 )); + float ringCos1 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 0 )); + Vector3 w1 = (Vector3){ + capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin1*b1.x + ringCos1*b2.x) * radius, + capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin1*b1.y + ringCos1*b2.y) * radius, + capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin1*b1.z + ringCos1*b2.z) * radius + }; + float ringSin2 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 )); + float ringCos2 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 0 )); + Vector3 w2 = (Vector3){ + capCenter.x + (sinf(baseRingAngle * ( i + 0 ))*b0.x + ringSin2*b1.x + ringCos2*b2.x) * radius, + capCenter.y + (sinf(baseRingAngle * ( i + 0 ))*b0.y + ringSin2*b1.y + ringCos2*b2.y) * radius, + capCenter.z + (sinf(baseRingAngle * ( i + 0 ))*b0.z + ringSin2*b1.z + ringCos2*b2.z) * radius + }; + + float ringSin3 = sinf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 )); + float ringCos3 = cosf(baseSliceAngle*(j + 0))*cosf(baseRingAngle * ( i + 1 )); + Vector3 w3 = (Vector3){ + capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin3*b1.x + ringCos3*b2.x) * radius, + capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin3*b1.y + ringCos3*b2.y) * radius, + capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin3*b1.z + ringCos3*b2.z) * radius + }; + float ringSin4 = sinf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 )); + float ringCos4 = cosf(baseSliceAngle*(j + 1))*cosf(baseRingAngle * ( i + 1 )); + Vector3 w4 = (Vector3){ + capCenter.x + (sinf(baseRingAngle * ( i + 1 ))*b0.x + ringSin4*b1.x + ringCos4*b2.x) * radius, + capCenter.y + (sinf(baseRingAngle * ( i + 1 ))*b0.y + ringSin4*b1.y + ringCos4*b2.y) * radius, + capCenter.z + (sinf(baseRingAngle * ( i + 1 ))*b0.z + ringSin4*b1.z + ringCos4*b2.z) * radius + }; + + rlVertex3f(w1.x, w1.y, w1.z); + rlVertex3f(w2.x, w2.y, w2.z); + + rlVertex3f(w2.x, w2.y, w2.z); + rlVertex3f(w3.x, w3.y, w3.z); + + rlVertex3f(w1.x, w1.y, w1.z); + rlVertex3f(w3.x, w3.y, w3.z); + + rlVertex3f(w2.x, w2.y, w2.z); + rlVertex3f(w4.x, w4.y, w4.z); + + rlVertex3f(w3.x, w3.y, w3.z); + rlVertex3f(w4.x, w4.y, w4.z); + } + } + capCenter = startPos; + b0 = Vector3Scale(b0, -1.0f); + } + // render middle + if (!sphereCase) + { + for (int j = 0; j < slices; j++) + { + // compute the four vertices + float ringSin1 = sinf(baseSliceAngle*(j + 0))*radius; + float ringCos1 = cosf(baseSliceAngle*(j + 0))*radius; + Vector3 w1 = { + startPos.x + ringSin1*b1.x + ringCos1*b2.x, + startPos.y + ringSin1*b1.y + ringCos1*b2.y, + startPos.z + ringSin1*b1.z + ringCos1*b2.z + }; + float ringSin2 = sinf(baseSliceAngle*(j + 1))*radius; + float ringCos2 = cosf(baseSliceAngle*(j + 1))*radius; + Vector3 w2 = { + startPos.x + ringSin2*b1.x + ringCos2*b2.x, + startPos.y + ringSin2*b1.y + ringCos2*b2.y, + startPos.z + ringSin2*b1.z + ringCos2*b2.z + }; + + float ringSin3 = sinf(baseSliceAngle*(j + 0))*radius; + float ringCos3 = cosf(baseSliceAngle*(j + 0))*radius; + Vector3 w3 = { + endPos.x + ringSin3*b1.x + ringCos3*b2.x, + endPos.y + ringSin3*b1.y + ringCos3*b2.y, + endPos.z + ringSin3*b1.z + ringCos3*b2.z + }; + float ringSin4 = sinf(baseSliceAngle*(j + 1))*radius; + float ringCos4 = cosf(baseSliceAngle*(j + 1))*radius; + Vector3 w4 = { + endPos.x + ringSin4*b1.x + ringCos4*b2.x, + endPos.y + ringSin4*b1.y + ringCos4*b2.y, + endPos.z + ringSin4*b1.z + ringCos4*b2.z + }; + + rlVertex3f(w1.x, w1.y, w1.z); + rlVertex3f(w3.x, w3.y, w3.z); + + rlVertex3f(w2.x, w2.y, w2.z); + rlVertex3f(w4.x, w4.y, w4.z); + + rlVertex3f(w2.x, w2.y, w2.z); + rlVertex3f(w3.x, w3.y, w3.z); + } + } + rlEnd(); +} + // Draw a plane void DrawPlane(Vector3 centerPos, Vector2 size, Color color) { @@ -1839,13 +2117,14 @@ for (int m = 0; m < model.meshCount; m++) { Mesh mesh = model.meshes[m]; + if (mesh.boneIds == NULL || mesh.boneWeights == NULL) { - TRACELOG(LOG_WARNING, "MODEL: UpdateModelAnimation Mesh %i has no connection to bones",m); + TRACELOG(LOG_WARNING, "MODEL: UpdateModelAnimation(): Mesh %i has no connection to bones", m); continue; } - bool updated = false; // set to true when anim vertex information is updated + bool updated = false; // Flag to check when anim vertex information is updated Vector3 animVertex = { 0 }; Vector3 animNormal = { 0 }; @@ -1862,13 +2141,13 @@ float boneWeight = 0.0; const int vValues = mesh.vertexCount*3; - for (int vCounter = 0; vCounter < vValues; vCounter+=3) + for (int vCounter = 0; vCounter < vValues; vCounter += 3) { mesh.animVertices[vCounter] = 0; mesh.animVertices[vCounter + 1] = 0; mesh.animVertices[vCounter + 2] = 0; - if (mesh.animNormals!=NULL) + if (mesh.animNormals != NULL) { mesh.animNormals[vCounter] = 0; mesh.animNormals[vCounter + 1] = 0; @@ -1879,16 +2158,15 @@ for (int j = 0; j < 4; j++, boneCounter++) { boneWeight = mesh.boneWeights[boneCounter]; - // early stop when no transformation will be applied - if (boneWeight == 0.0f) - { - continue; - } + + // Early stop when no transformation will be applied + if (boneWeight == 0.0f) continue; + boneId = mesh.boneIds[boneCounter]; //int boneIdParent = model.bones[boneId].parent; inTranslation = model.bindPose[boneId].translation; inRotation = model.bindPose[boneId].rotation; - // inScale = model.bindPose[boneId].scale; + //inScale = model.bindPose[boneId].scale; outTranslation = anim.framePoses[frame][boneId].translation; outRotation = anim.framePoses[frame][boneId].rotation; outScale = anim.framePoses[frame][boneId].scale; @@ -1900,7 +2178,7 @@ animVertex = Vector3Subtract(animVertex, inTranslation); animVertex = Vector3RotateByQuaternion(animVertex, QuaternionMultiply(outRotation, QuaternionInvert(inRotation))); animVertex = Vector3Add(animVertex, outTranslation); -// animVertex = Vector3Transform(animVertex, model.transform); + //animVertex = Vector3Transform(animVertex, model.transform); mesh.animVertices[vCounter] += animVertex.x*boneWeight; mesh.animVertices[vCounter + 1] += animVertex.y*boneWeight; mesh.animVertices[vCounter + 2] += animVertex.z*boneWeight; @@ -1920,10 +2198,11 @@ } // Upload new vertex data to GPU for model drawing - // Only update data when values changed. - if (updated){ - rlUpdateVertexBuffer(mesh.vboId[0], mesh.animVertices, mesh.vertexCount*3*sizeof(float), 0); // Update vertex position - rlUpdateVertexBuffer(mesh.vboId[2], mesh.animNormals, mesh.vertexCount*3*sizeof(float), 0); // Update vertex normals + // NOTE: Only update data when values changed + if (updated) + { + rlUpdateVertexBuffer(mesh.vboId[0], mesh.animVertices, mesh.vertexCount*3*sizeof(float), 0); // Update vertex position + rlUpdateVertexBuffer(mesh.vboId[2], mesh.animNormals, mesh.vertexCount*3*sizeof(float), 0); // Update vertex normals } } }
raylib/src/rshapes.c view
@@ -58,6 +58,7 @@ #include <math.h> // Required for: sinf(), asinf(), cosf(), acosf(), sqrtf(), fabsf() #include <float.h> // Required for: FLT_EPSILON +#include <stdlib.h> // Required for: RL_FREE //---------------------------------------------------------------------------------- // Defines and Macros @@ -104,21 +105,50 @@ // Draw a pixel void DrawPixel(int posX, int posY, Color color) { - rlBegin(RL_LINES); - rlColor4ub(color.r, color.g, color.b, color.a); - rlVertex2f(posX, posY); - rlVertex2f(posX + 1, posY + 1); - rlEnd(); + DrawPixelV((Vector2){ posX, posY }, color); } // Draw a pixel (Vector version) void DrawPixelV(Vector2 position, Color color) { - rlBegin(RL_LINES); +#if defined(SUPPORT_QUADS_DRAW_MODE) + rlSetTexture(texShapes.id); + + rlBegin(RL_QUADS); + + rlNormal3f(0.0f, 0.0f, 1.0f); rlColor4ub(color.r, color.g, color.b, color.a); + + rlTexCoord2f(texShapesRec.x/texShapes.width, texShapesRec.y/texShapes.height); rlVertex2f(position.x, position.y); - rlVertex2f(position.x + 1.0f, position.y + 1.0f); + + rlTexCoord2f(texShapesRec.x/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height); + rlVertex2f(position.x, position.y + 1); + + rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, (texShapesRec.y + texShapesRec.height)/texShapes.height); + rlVertex2f(position.x + 1, position.y + 1); + + rlTexCoord2f((texShapesRec.x + texShapesRec.width)/texShapes.width, texShapesRec.y/texShapes.height); + rlVertex2f(position.x + 1, position.y); + rlEnd(); + + rlSetTexture(0); +#else + rlBegin(RL_TRIANGLES); + + rlColor4ub(color.r, color.g, color.b, color.a); + + rlVertex2f(position.x, position.y); + rlVertex2f(position.x, position.y + 1); + rlVertex2f(position.x + 1, position.y); + + rlVertex2f(position.x + 1, position.y); + rlVertex2f(position.x, position.y + 1); + rlVertex2f(position.x + 1, position.y + 1); + + rlEnd(); +#endif } // Draw a line @@ -168,6 +198,8 @@ Vector2 previous = startPos; Vector2 current = { 0 }; + Vector2 points[2*BEZIER_LINE_DIVISIONS + 2] = { 0 }; + for (int i = 1; i <= BEZIER_LINE_DIVISIONS; i++) { // Cubic easing in-out @@ -175,12 +207,27 @@ current.y = EaseCubicInOut((float)i, startPos.y, endPos.y - startPos.y, (float)BEZIER_LINE_DIVISIONS); current.x = previous.x + (endPos.x - startPos.x)/ (float)BEZIER_LINE_DIVISIONS; - // TODO: Avoid drawing the line by pieces, it generates gaps for big thicks, - // Custom "triangle-strip" implementation should be used, check DrawTriangleStrip() for reference - DrawLineEx(previous, current, thick, color); + float dy = current.y-previous.y; + float dx = current.x-previous.x; + float size = 0.5*thick/sqrt(dx*dx+dy*dy); + if (i==1) + { + points[0].x = previous.x+dy*size; + points[0].y = previous.y-dx*size; + points[1].x = previous.x-dy*size; + points[1].y = previous.y+dx*size; + } + + points[2*i+1].x = current.x-dy*size; + points[2*i+1].y = current.y+dx*size; + points[2*i].x = current.x+dy*size; + points[2*i].y = current.y-dx*size; + previous = current; } + + DrawTriangleStrip(points, 2*BEZIER_LINE_DIVISIONS+2, color); } // Draw line using quadratic bezier curves with a control point @@ -192,6 +239,8 @@ Vector2 current = { 0 }; float t = 0.0f; + Vector2 points[2*BEZIER_LINE_DIVISIONS + 2] = { 0 }; + for (int i = 0; i <= BEZIER_LINE_DIVISIONS; i++) { t = step*i; @@ -203,12 +252,27 @@ current.y = a*startPos.y + b*controlPos.y + c*endPos.y; current.x = a*startPos.x + b*controlPos.x + c*endPos.x; - // TODO: Avoid drawing the line by pieces, it generates gaps for big thicks, - // Custom "triangle-strip" implementation should be used, check DrawTriangleStrip() for reference - DrawLineEx(previous, current, thick, color); + float dy = current.y-previous.y; + float dx = current.x-previous.x; + float size = 0.5*thick/sqrt(dx*dx+dy*dy); + if (i==1) + { + points[0].x = previous.x+dy*size; + points[0].y = previous.y-dx*size; + points[1].x = previous.x-dy*size; + points[1].y = previous.y+dx*size; + } + + points[2*i+1].x = current.x-dy*size; + points[2*i+1].y = current.y+dx*size; + points[2*i].x = current.x+dy*size; + points[2*i].y = current.y-dx*size; + previous = current; } + + DrawTriangleStrip(points, 2*BEZIER_LINE_DIVISIONS+2, color); } // Draw line using cubic bezier curves with 2 control points @@ -220,6 +284,8 @@ Vector2 current = { 0 }; float t = 0.0f; + Vector2 points[2*BEZIER_LINE_DIVISIONS + 2] = { 0 }; + for (int i = 0; i <= BEZIER_LINE_DIVISIONS; i++) { t = step*i; @@ -231,12 +297,27 @@ current.y = a*startPos.y + b*startControlPos.y + c*endControlPos.y + d*endPos.y; current.x = a*startPos.x + b*startControlPos.x + c*endControlPos.x + d*endPos.x; - // TODO: Avoid drawing the line by pieces, it generates gaps for big thicks, - // Custom "triangle-strip" implementation should be used, check DrawTriangleStrip() for reference - DrawLineEx(previous, current, thick, color); + float dy = current.y-previous.y; + float dx = current.x-previous.x; + float size = 0.5*thick/sqrt(dx*dx+dy*dy); + + if (i==1) + { + points[0].x = previous.x+dy*size; + points[0].y = previous.y-dx*size; + points[1].x = previous.x-dy*size; + points[1].y = previous.y+dx*size; + } + points[2*i+1].x = current.x-dy*size; + points[2*i+1].y = current.y+dx*size; + points[2*i].x = current.x+dy*size; + points[2*i].y = current.y-dx*size; + previous = current; } + + DrawTriangleStrip(points, 2*BEZIER_LINE_DIVISIONS+2, color); } // Draw lines sequence
raylib/src/rtextures.c view
@@ -194,6 +194,10 @@ #define PIXELFORMAT_UNCOMPRESSED_R5G5B5A1_ALPHA_THRESHOLD 50 // Threshold over 255 to set alpha as 0 #endif +#ifndef GAUSSIAN_BLUR_ITERATIONS + #define GAUSSIAN_BLUR_ITERATIONS 4 // Number of box blur iterations to approximate gaussian blur +#endif + //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- @@ -893,6 +897,25 @@ return image; } + +// Generate image: grayscale image from text data +Image GenImageText(int width, int height, const char *text) +{ + Image image = { 0 }; + + int textLength = TextLength(text); + int imageViewSize = width*height; + + image.width = width; + image.height = height; + image.format = PIXELFORMAT_UNCOMPRESSED_GRAYSCALE; + image.data = RL_CALLOC(imageViewSize, 1); + image.mipmaps = 1; + + memcpy(image.data, text, (textLength > imageViewSize)? imageViewSize : textLength); + + return image; +} #endif // SUPPORT_IMAGE_GENERATION //------------------------------------------------------------------------------------ @@ -1229,6 +1252,7 @@ // NOTE: Text image is generated at font base size, later scaled to desired font size Vector2 imSize = MeasureTextEx(font, text, (float)font.baseSize, spacing); // WARNING: Module required: rtext + Vector2 textSize = MeasureTextEx(font, text, fontSize, spacing); // Create image to store text imText = GenImageColor((int)imSize.x, (int)imSize.y, BLANK); @@ -1267,12 +1291,13 @@ } // Scale image depending on text size - if (fontSize > imSize.y) + if (textSize.y != imSize.y) { - float scaleFactor = fontSize/imSize.y; + float scaleFactor = textSize.y / imSize.y; TRACELOG(LOG_INFO, "IMAGE: Text scaled by factor: %f", scaleFactor); // Using nearest-neighbor scaling algorithm for default font + // TODO: Allow defining the preferred scaling mechanism externally // WARNING: Module required: rtext if (font.texture.id == GetFontDefault().texture.id) ImageResizeNN(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor)); else ImageResize(&imText, (int)(imSize.x*scaleFactor), (int)(imSize.y*scaleFactor)); @@ -1474,6 +1499,158 @@ ImageFormat(image, format); } +// Apply box blur +void ImageBlurGaussian(Image *image, int blurSize) { + // Security check to avoid program crash + if ((image->data == NULL) || (image->width == 0) || (image->height == 0)) return; + + ImageAlphaPremultiply(image); + + Color *pixels = LoadImageColors(*image); + + // Loop switches between pixelsCopy1 and pixelsCopy2 + Vector4 *pixelsCopy1 = RL_MALLOC((image->height)*(image->width)*sizeof(Vector4)); + Vector4 *pixelsCopy2 = RL_MALLOC((image->height)*(image->width)*sizeof(Vector4)); + + for (int i = 0; i < (image->height)*(image->width); i++) { + pixelsCopy1[i].x = pixels[i].r; + pixelsCopy1[i].y = pixels[i].g; + pixelsCopy1[i].z = pixels[i].b; + pixelsCopy1[i].w = pixels[i].a; + } + + // Repeated convolution of rectangular window signal by itself converges to a gaussian distribution + for (int j = 0; j < GAUSSIAN_BLUR_ITERATIONS; j++) { + // Horizontal motion blur + for (int row = 0; row < image->height; row++) + { + float avgR = 0.0f; + float avgG = 0.0f; + float avgB = 0.0f; + float avgAlpha = 0.0f; + int convolutionSize = blurSize+1; + + for (int i = 0; i < blurSize+1; i++) + { + avgR += pixelsCopy1[row*image->width + i].x; + avgG += pixelsCopy1[row*image->width + i].y; + avgB += pixelsCopy1[row*image->width + i].z; + avgAlpha += pixelsCopy1[row*image->width + i].w; + } + + pixelsCopy2[row*image->width].x = avgR/convolutionSize; + pixelsCopy2[row*image->width].y = avgG/convolutionSize; + pixelsCopy2[row*image->width].z = avgB/convolutionSize; + pixelsCopy2[row*image->width].w = avgAlpha/convolutionSize; + + for (int x = 1; x < image->width; x++) + { + if (x-blurSize >= 0) + { + avgR -= pixelsCopy1[row*image->width + x-blurSize].x; + avgG -= pixelsCopy1[row*image->width + x-blurSize].y; + avgB -= pixelsCopy1[row*image->width + x-blurSize].z; + avgAlpha -= pixelsCopy1[row*image->width + x-blurSize].w; + convolutionSize--; + } + + if (x+blurSize < image->width) + { + avgR += pixelsCopy1[row*image->width + x+blurSize].x; + avgG += pixelsCopy1[row*image->width + x+blurSize].y; + avgB += pixelsCopy1[row*image->width + x+blurSize].z; + avgAlpha += pixelsCopy1[row*image->width + x+blurSize].w; + convolutionSize++; + } + + pixelsCopy2[row*image->width + x].x = avgR/convolutionSize; + pixelsCopy2[row*image->width + x].y = avgG/convolutionSize; + pixelsCopy2[row*image->width + x].z = avgB/convolutionSize; + pixelsCopy2[row*image->width + x].w = avgAlpha/convolutionSize; + } + } + + // Vertical motion blur + for (int col = 0; col < image->width; col++) + { + float avgR = 0.0f; + float avgG = 0.0f; + float avgB = 0.0f; + float avgAlpha = 0.0f; + int convolutionSize = blurSize+1; + + for (int i = 0; i < blurSize+1; i++) + { + avgR += pixelsCopy2[i*image->width + col].x; + avgG += pixelsCopy2[i*image->width + col].y; + avgB += pixelsCopy2[i*image->width + col].z; + avgAlpha += pixelsCopy2[i*image->width + col].w; + } + + pixelsCopy1[col].x = (unsigned char) (avgR/convolutionSize); + pixelsCopy1[col].y = (unsigned char) (avgG/convolutionSize); + pixelsCopy1[col].z = (unsigned char) (avgB/convolutionSize); + pixelsCopy1[col].w = (unsigned char) (avgAlpha/convolutionSize); + + for (int y = 1; y < image->height; y++) + { + if (y-blurSize >= 0) + { + avgR -= pixelsCopy2[(y-blurSize)*image->width + col].x; + avgG -= pixelsCopy2[(y-blurSize)*image->width + col].y; + avgB -= pixelsCopy2[(y-blurSize)*image->width + col].z; + avgAlpha -= pixelsCopy2[(y-blurSize)*image->width + col].w; + convolutionSize--; + } + if (y+blurSize < image->height) + { + avgR += pixelsCopy2[(y+blurSize)*image->width + col].x; + avgG += pixelsCopy2[(y+blurSize)*image->width + col].y; + avgB += pixelsCopy2[(y+blurSize)*image->width + col].z; + avgAlpha += pixelsCopy2[(y+blurSize)*image->width + col].w; + convolutionSize++; + } + + pixelsCopy1[y*image->width + col].x = (unsigned char) (avgR/convolutionSize); + pixelsCopy1[y*image->width + col].y = (unsigned char) (avgG/convolutionSize); + pixelsCopy1[y*image->width + col].z = (unsigned char) (avgB/convolutionSize); + pixelsCopy1[y*image->width + col].w = (unsigned char) (avgAlpha/convolutionSize); + } + } + } + + + // Reverse premultiply + for (int i = 0; i < (image->width)*(image->height); i++) + { + if (pixelsCopy1[i].w == 0.0f) + { + pixels[i].r = 0; + pixels[i].g = 0; + pixels[i].b = 0; + pixels[i].a = 0; + } + else if (pixelsCopy1[i].w <= 255.0f) + { + float alpha = (float)pixelsCopy1[i].w/255.0f; + pixels[i].r = (unsigned char)((float)pixelsCopy1[i].x/alpha); + pixels[i].g = (unsigned char)((float)pixelsCopy1[i].y/alpha); + pixels[i].b = (unsigned char)((float)pixelsCopy1[i].z/alpha); + pixels[i].a = (unsigned char) pixelsCopy1[i].w; + } + } + + int format = image->format; + RL_FREE(image->data); + RL_FREE(pixelsCopy1); + RL_FREE(pixelsCopy2); + + image->data = pixels; + image->format = PIXELFORMAT_UNCOMPRESSED_R8G8B8A8; + + ImageFormat(image, format); +} + // Resize and image to new size // NOTE: Uses stb default scaling filters (both bicubic): // STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM @@ -3435,104 +3612,6 @@ } } -// Draw texture quad with tiling and offset parameters -// NOTE: Tiling and offset should be provided considering normalized texture values [0..1] -// i.e tiling = { 1.0f, 1.0f } refers to all texture, offset = { 0.5f, 0.5f } moves texture origin to center -void DrawTextureQuad(Texture2D texture, Vector2 tiling, Vector2 offset, Rectangle quad, Color tint) -{ - // WARNING: This solution only works if TEXTURE_WRAP_REPEAT is supported, - // NPOT textures supported is required and OpenGL ES 2.0 could not support it - Rectangle source = { offset.x*texture.width, offset.y*texture.height, tiling.x*texture.width, tiling.y*texture.height }; - Vector2 origin = { 0.0f, 0.0f }; - - DrawTexturePro(texture, source, quad, origin, 0.0f, tint); -} - -// Draw part of a texture (defined by a rectangle) with rotation and scale tiled into dest. -// NOTE: For tilling a whole texture DrawTextureQuad() is better -void DrawTextureTiled(Texture2D texture, Rectangle source, Rectangle dest, Vector2 origin, float rotation, float scale, Color tint) -{ - if ((texture.id <= 0) || (scale <= 0.0f)) return; // Wanna see a infinite loop?!...just delete this line! - if ((source.width == 0) || (source.height == 0)) return; - - int tileWidth = (int)(source.width*scale), tileHeight = (int)(source.height*scale); - if ((dest.width < tileWidth) && (dest.height < tileHeight)) - { - // Can fit only one tile - DrawTexturePro(texture, (Rectangle){source.x, source.y, ((float)dest.width/tileWidth)*source.width, ((float)dest.height/tileHeight)*source.height}, - (Rectangle){dest.x, dest.y, dest.width, dest.height}, origin, rotation, tint); - } - else if (dest.width <= tileWidth) - { - // Tiled vertically (one column) - int dy = 0; - for (;dy+tileHeight < dest.height; dy += tileHeight) - { - DrawTexturePro(texture, (Rectangle){source.x, source.y, ((float)dest.width/tileWidth)*source.width, source.height}, (Rectangle){dest.x, dest.y + dy, dest.width, (float)tileHeight}, origin, rotation, tint); - } - - // Fit last tile - if (dy < dest.height) - { - DrawTexturePro(texture, (Rectangle){source.x, source.y, ((float)dest.width/tileWidth)*source.width, ((float)(dest.height - dy)/tileHeight)*source.height}, - (Rectangle){dest.x, dest.y + dy, dest.width, dest.height - dy}, origin, rotation, tint); - } - } - else if (dest.height <= tileHeight) - { - // Tiled horizontally (one row) - int dx = 0; - for (;dx+tileWidth < dest.width; dx += tileWidth) - { - DrawTexturePro(texture, (Rectangle){source.x, source.y, source.width, ((float)dest.height/tileHeight)*source.height}, (Rectangle){dest.x + dx, dest.y, (float)tileWidth, dest.height}, origin, rotation, tint); - } - - // Fit last tile - if (dx < dest.width) - { - DrawTexturePro(texture, (Rectangle){source.x, source.y, ((float)(dest.width - dx)/tileWidth)*source.width, ((float)dest.height/tileHeight)*source.height}, - (Rectangle){dest.x + dx, dest.y, dest.width - dx, dest.height}, origin, rotation, tint); - } - } - else - { - // Tiled both horizontally and vertically (rows and columns) - int dx = 0; - for (;dx+tileWidth < dest.width; dx += tileWidth) - { - int dy = 0; - for (;dy+tileHeight < dest.height; dy += tileHeight) - { - DrawTexturePro(texture, source, (Rectangle){dest.x + dx, dest.y + dy, (float)tileWidth, (float)tileHeight}, origin, rotation, tint); - } - - if (dy < dest.height) - { - DrawTexturePro(texture, (Rectangle){source.x, source.y, source.width, ((float)(dest.height - dy)/tileHeight)*source.height}, - (Rectangle){dest.x + dx, dest.y + dy, (float)tileWidth, dest.height - dy}, origin, rotation, tint); - } - } - - // Fit last column of tiles - if (dx < dest.width) - { - int dy = 0; - for (;dy+tileHeight < dest.height; dy += tileHeight) - { - DrawTexturePro(texture, (Rectangle){source.x, source.y, ((float)(dest.width - dx)/tileWidth)*source.width, source.height}, - (Rectangle){dest.x + dx, dest.y + dy, dest.width - dx, (float)tileHeight}, origin, rotation, tint); - } - - // Draw final tile in the bottom right corner - if (dy < dest.height) - { - DrawTexturePro(texture, (Rectangle){source.x, source.y, ((float)(dest.width - dx)/tileWidth)*source.width, ((float)(dest.height - dy)/tileHeight)*source.height}, - (Rectangle){dest.x + dx, dest.y + dy, dest.width - dx, dest.height - dy}, origin, rotation, tint); - } - } - } -} - // Draws a texture (or part of it) that stretches or shrinks nicely using n-patch info void DrawTextureNPatch(Texture2D texture, NPatchInfo nPatchInfo, Rectangle dest, Vector2 origin, float rotation, Color tint) { @@ -3728,37 +3807,6 @@ rlSetTexture(0); } -} - -// Draw textured polygon, defined by vertex and texturecoordinates -// NOTE: Polygon center must have straight line path to all points -// without crossing perimeter, points must be in anticlockwise order -void DrawTexturePoly(Texture2D texture, Vector2 center, Vector2 *points, Vector2 *texcoords, int pointCount, Color tint) -{ - rlSetTexture(texture.id); - - // Texturing is only supported on RL_QUADS - rlBegin(RL_QUADS); - - rlColor4ub(tint.r, tint.g, tint.b, tint.a); - - for (int i = 0; i < pointCount - 1; i++) - { - rlTexCoord2f(0.5f, 0.5f); - rlVertex2f(center.x, center.y); - - rlTexCoord2f(texcoords[i].x, texcoords[i].y); - rlVertex2f(points[i].x + center.x, points[i].y + center.y); - - rlTexCoord2f(texcoords[i + 1].x, texcoords[i + 1].y); - rlVertex2f(points[i + 1].x + center.x, points[i + 1].y + center.y); - - rlTexCoord2f(texcoords[i + 1].x, texcoords[i + 1].y); - rlVertex2f(points[i + 1].x + center.x, points[i + 1].y + center.y); - } - rlEnd(); - - rlSetTexture(0); } // Get color with alpha applied, alpha goes from 0.0f to 1.0f
raylib/src/utils.c view
@@ -270,7 +270,7 @@ } // Export data to code (.h), returns true on success -bool ExportDataAsCode(const char *data, unsigned int size, const char *fileName) +bool ExportDataAsCode(const unsigned char *data, unsigned int size, const char *fileName) { bool success = false;
src/Raylib.hs view
@@ -1198,11 +1198,11 @@ foreign import ccall safe "raylib.h ExportDataAsCode" c'exportDataAsCode :: - CString -> CUInt -> CString -> IO CBool + Ptr CUChar -> CUInt -> CString -> IO CBool -exportDataAsCode :: String -> Integer -> String -> IO Bool +exportDataAsCode :: [Integer] -> Integer -> String -> IO Bool exportDataAsCode contents size fileName = - toBool <$> withCString contents (\c -> withCString fileName (c'exportDataAsCode c (fromIntegral size))) + toBool <$> withArray (map fromInteger contents) (\c -> withCString fileName (c'exportDataAsCode c (fromIntegral size))) foreign import ccall safe "raylib.h &ExportDataAsCode" p'exportDataAsCode :: @@ -2844,6 +2844,16 @@ p'genImageCellular :: FunPtr (CInt -> CInt -> CInt -> IO Raylib.Types.Image) +foreign import ccall safe "bindings.h GenImageText_" c'genImageText :: CInt -> CInt -> CString -> IO (Ptr Raylib.Types.Image) + +genImageText :: Int -> Int -> String -> IO Raylib.Types.Image +genImageText width height text = + withCString text (c'genImageText (fromIntegral width) (fromIntegral height)) >>= pop + +foreign import ccall safe "raylib.h &GenImageText" + p'genImageText :: + FunPtr (CInt -> CInt -> CString -> IO Raylib.Types.Image) + foreign import ccall safe "bindings.h ImageCopy_" c'imageCopy :: Ptr Raylib.Types.Image -> IO (Ptr Raylib.Types.Image) imageCopy :: Raylib.Types.Image -> IO Raylib.Types.Image @@ -2952,6 +2962,18 @@ p'imageAlphaPremultiply :: FunPtr (Ptr Raylib.Types.Image -> IO ()) + +foreign import ccall safe "raylib.h ImageBlurGaussian" + c'imageBlurGaussian :: + Ptr Raylib.Types.Image -> CInt -> IO () + +imageBlurGaussian :: Raylib.Types.Image -> Int -> IO Raylib.Types.Image +imageBlurGaussian image blurSize = with image (\i -> c'imageBlurGaussian i (fromIntegral blurSize) >> peek i) + +foreign import ccall safe "raylib.h &ImageBlurGaussian" + p'imageBlurGaussian :: + FunPtr (Ptr Raylib.Types.Image -> CInt -> IO ()) + foreign import ccall safe "raylib.h ImageResize" c'imageResize :: Ptr Raylib.Types.Image -> CInt -> CInt -> IO () @@ -3469,24 +3491,6 @@ p'drawTextureRec :: FunPtr (Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> Raylib.Types.Color -> IO ()) -foreign import ccall safe "bindings.h DrawTextureQuad_" c'drawTextureQuad :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Color -> IO () - -drawTextureQuad :: Raylib.Types.Texture -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Rectangle -> Raylib.Types.Color -> IO () -drawTextureQuad texture tiling offset quad tint = with texture (\t -> with tiling (\ti -> with offset (\o -> with quad (with tint . c'drawTextureQuad t ti o)))) - -foreign import ccall safe "raylib.h &DrawTextureQuad" - p'drawTextureQuad :: - FunPtr (Raylib.Types.Texture -> Raylib.Types.Vector2 -> Raylib.Types.Vector2 -> Raylib.Types.Rectangle -> Raylib.Types.Color -> IO ()) - -foreign import ccall safe "bindings.h DrawTextureTiled_" c'drawTextureTiled :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector2 -> CFloat -> CFloat -> Ptr Raylib.Types.Color -> IO () - -drawTextureTiled :: Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> Float -> Float -> Raylib.Types.Color -> IO () -drawTextureTiled texture source dest origin rotation scale tint = with texture (\t -> with source (\s -> with dest (\d -> with origin (\o -> with tint (c'drawTextureTiled t s d o (realToFrac rotation) (realToFrac scale)))))) - -foreign import ccall safe "raylib.h &DrawTextureTiled" - p'drawTextureTiled :: - FunPtr (Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> CFloat -> CFloat -> Raylib.Types.Color -> IO ()) - foreign import ccall safe "bindings.h DrawTexturePro_" c'drawTexturePro :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Rectangle -> Ptr Raylib.Types.Vector2 -> CFloat -> Ptr Raylib.Types.Color -> IO () drawTexturePro :: Raylib.Types.Texture -> Raylib.Types.Rectangle -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> Float -> Raylib.Types.Color -> IO () @@ -3505,15 +3509,6 @@ p'drawTextureNPatch :: FunPtr (Raylib.Types.Texture -> Raylib.Types.NPatchInfo -> Raylib.Types.Rectangle -> Raylib.Types.Vector2 -> CFloat -> Raylib.Types.Color -> IO ()) -foreign import ccall safe "bindings.h DrawTexturePoly_" c'drawTexturePoly :: Ptr Raylib.Types.Texture -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CInt -> Ptr Raylib.Types.Color -> IO () - -drawTexturePoly :: Raylib.Types.Texture -> Raylib.Types.Vector2 -> [Raylib.Types.Vector2] -> [Raylib.Types.Vector2] -> Raylib.Types.Color -> IO () -drawTexturePoly texture center points texcoords tint = with texture (\t -> with center (\c -> withArrayLen points (\numPoints pArr -> withArray texcoords (\tc -> with tint (c'drawTexturePoly t c pArr tc (fromIntegral numPoints)))))) - -foreign import ccall safe "raylib.h &DrawTexturePoly" - p'drawTexturePoly :: - FunPtr (Raylib.Types.Texture -> Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Vector2 -> CInt -> Raylib.Types.Color -> IO ()) - foreign import ccall safe "bindings.h Fade_" c'fade :: Ptr Raylib.Types.Color -> CFloat -> IO (Ptr Raylib.Types.Color) fade :: Raylib.Types.Color -> Float -> Raylib.Types.Color @@ -4255,6 +4250,24 @@ foreign import ccall safe "raylib.h &DrawCylinderWiresEx" p'drawCylinderWiresEx :: FunPtr (Raylib.Types.Vector3 -> Raylib.Types.Vector3 -> CFloat -> CFloat -> CInt -> Raylib.Types.Color -> IO ()) + +foreign import ccall safe "bindings.h DrawCapsule_" c'drawCapsule :: Ptr Vector3 -> Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO () + +drawCapsule :: Vector3 -> Vector3 -> CFloat -> CInt -> CInt -> Color -> IO () +drawCapsule start end radius slices rings color = with start (\s -> with end (\e -> with color (c'drawCapsule s e (realToFrac radius) (fromIntegral slices) (fromIntegral rings)))) + +foreign import ccall safe "raylib.h &DrawCapsule" + p'drawCapsule :: + FunPtr (Vector3 -> Vector3 -> CFloat -> CInt -> CInt -> Color -> IO ()) + +foreign import ccall safe "bindings.h DrawCapsuleWires_" c'drawCapsuleWires :: Ptr Vector3 -> Ptr Vector3 -> CFloat -> CInt -> CInt -> Ptr Color -> IO () + +drawCapsuleWires :: Vector3 -> Vector3 -> CFloat -> CInt -> CInt -> Color -> IO () +drawCapsuleWires start end radius slices rings color = with start (\s -> with end (\e -> with color (c'drawCapsuleWires s e (realToFrac radius) (fromIntegral slices) (fromIntegral rings)))) + +foreign import ccall safe "raylib.h &DrawCapsuleWires" + p'drawCapsuleWires :: + FunPtr (Vector3 -> Vector3 -> CFloat -> CInt -> CInt -> Color -> IO ()) foreign import ccall safe "bindings.h DrawPlane_" c'drawPlane :: Ptr Raylib.Types.Vector3 -> Ptr Raylib.Types.Vector2 -> Ptr Raylib.Types.Color -> IO ()
src/Raylib/Types.hs view
@@ -3,8 +3,9 @@ -- This file includes Haskell counterparts to the structs defined in raylib +-- This file includes Haskell counterparts to the structs defined in raylib import Foreign.C - ( CString, CChar, CUShort, CUInt, CInt, CUChar, CFloat ) + ( CString, CChar, CUShort, CUInt, CInt, CUChar, CFloat, CBool ) import Foreign ( Ptr, plusPtr, @@ -1225,8 +1226,8 @@ _Bool hit; float distance; Vector3 point; Vector3 normal; } RayCollision; -} data RayCollision = RayCollision - { raycollision'hit :: CInt, - raycollision'distance :: CFloat, + { rayCollision'hit :: CBool, + rayCollision'distance :: CFloat, rayCollision'point :: Vector3, rayCollision'normal :: Vector3 } @@ -1234,7 +1235,7 @@ p'RayCollision'hit p = plusPtr p 0 -p'RayCollision'hit :: Ptr RayCollision -> Ptr CInt +p'RayCollision'hit :: Ptr RayCollision -> Ptr CBool p'RayCollision'distance p = plusPtr p 4