diff --git a/examples/core/vr_simulator/main.go b/examples/core/vr_simulator/main.go new file mode 100644 index 0000000..bec3bb4 --- /dev/null +++ b/examples/core/vr_simulator/main.go @@ -0,0 +1,58 @@ +package main + +import ( + "github.com/gen2brain/raylib-go/raylib" +) + +func main() { + screenWidth := int32(1080) + screenHeight := int32(600) + + // NOTE: screenWidth/screenHeight should match VR device aspect ratio + + raylib.InitWindow(screenWidth, screenHeight, "raylib [core] example - vr simulator") + + // NOTE: default device (simulator) + raylib.InitVrSimulator(raylib.HmdOculusRiftCv1) // Init VR device (Oculus Rift CV1) + + camera := raylib.Camera{} + camera.Position = raylib.NewVector3(5.0, 2.0, 5.0) // Camera position + camera.Target = raylib.NewVector3(0.0, 2.0, 0.0) // Camera looking at point + camera.Up = raylib.NewVector3(0.0, 1.0, 0.0) // Camera up vector (rotation towards target) + camera.Fovy = 60.0 // Camera field-of-view Y + + cubePosition := raylib.NewVector3(0.0, 0.0, 0.0) + + raylib.SetCameraMode(camera, raylib.CameraFirstPerson) // Set first person camera mode + + raylib.SetTargetFPS(90) + + for !raylib.WindowShouldClose() { + raylib.UpdateCamera(&camera) // Update camera (simulator mode) + + raylib.BeginDrawing() + + raylib.ClearBackground(raylib.RayWhite) + + raylib.BeginVrDrawing() + + raylib.Begin3dMode(camera) + + raylib.DrawCube(cubePosition, 2.0, 2.0, 2.0, raylib.Red) + raylib.DrawCubeWires(cubePosition, 2.0, 2.0, 2.0, raylib.Maroon) + + raylib.DrawGrid(40, 1.0) + + raylib.End3dMode() + + raylib.EndVrDrawing() + + raylib.DrawFPS(10, 10) + + raylib.EndDrawing() + } + + raylib.CloseVrSimulator() // Close VR simulator + + raylib.CloseWindow() +} diff --git a/examples/shaders/shapes_textures/fudesumi.png b/examples/shaders/shapes_textures/fudesumi.png new file mode 100644 index 0000000..9d9038f Binary files /dev/null and b/examples/shaders/shapes_textures/fudesumi.png differ diff --git a/examples/shaders/shapes_textures/main.go b/examples/shaders/shapes_textures/main.go index 81b514f..51afc06 100644 --- a/examples/shaders/shapes_textures/main.go +++ b/examples/shaders/shapes_textures/main.go @@ -10,7 +10,7 @@ func main() { raylib.InitWindow(screenWidth, screenHeight, "raylib [shaders] example - shapes and texture shaders") - sonic := raylib.LoadTexture("sonic.png") + fudesumi := raylib.LoadTexture("fudesumi.png") // NOTE: Using GLSL 330 shader version, on OpenGL ES 2.0 use GLSL 100 shader version shader := raylib.LoadShader("glsl330/base.vs", "glsl330/grayscale.fs") @@ -57,16 +57,18 @@ func main() { // Activate our custom shader to be applied on next shapes/textures drawings raylib.BeginShaderMode(shader) - raylib.DrawTexture(sonic, 380, -10, raylib.White) // Using custom shader + raylib.DrawTexture(fudesumi, 500, -30, raylib.White) // Using custom shader // Activate our default shader for next drawings raylib.EndShaderMode() + raylib.DrawText("(c) Fudesumi sprite by Eiden Marsal", 380, screenHeight-20, 10, raylib.Gray) + raylib.EndDrawing() } - raylib.UnloadShader(shader) // Unload shader - raylib.UnloadTexture(sonic) // Unload texture + raylib.UnloadShader(shader) // Unload shader + raylib.UnloadTexture(fudesumi) // Unload texture raylib.CloseWindow() // Close window and OpenGL context } diff --git a/examples/shaders/shapes_textures/sonic.png b/examples/shaders/shapes_textures/sonic.png deleted file mode 100644 index 7a09684..0000000 Binary files a/examples/shaders/shapes_textures/sonic.png and /dev/null differ diff --git a/examples/shapes/lines_bezier/main.go b/examples/shapes/lines_bezier/main.go new file mode 100644 index 0000000..7ca9377 --- /dev/null +++ b/examples/shapes/lines_bezier/main.go @@ -0,0 +1,36 @@ +package main + +import ( + "github.com/gen2brain/raylib-go/raylib" +) + +func main() { + screenWidth := int32(800) + screenHeight := int32(450) + + raylib.InitWindow(screenWidth, screenHeight, "raylib [shapes] example - cubic-bezier lines") + + start := raylib.NewVector2(0, 0) + end := raylib.NewVector2(float32(screenWidth), float32(screenHeight)) + + raylib.SetTargetFPS(60) + + for !raylib.WindowShouldClose() { + if raylib.IsMouseButtonDown(raylib.MouseLeftButton) { + start = raylib.GetMousePosition() + } else if raylib.IsMouseButtonDown(raylib.MouseRightButton) { + end = raylib.GetMousePosition() + } + + raylib.BeginDrawing() + raylib.ClearBackground(raylib.RayWhite) + + raylib.DrawText("USE MOUSE LEFT-RIGHT CLICK to DEFINE LINE START and END POINTS", 15, 20, 20, raylib.Gray) + + raylib.DrawLineBezier(start, end, 2.0, raylib.Red) + + raylib.EndDrawing() + } + + raylib.CloseWindow() +} diff --git a/examples/text/font_select/fonts/alagard.rbmf b/examples/text/font_select/fonts/alagard.rbmf deleted file mode 100644 index 8c9b68d..0000000 Binary files a/examples/text/font_select/fonts/alagard.rbmf and /dev/null differ diff --git a/examples/text/font_select/fonts/alpha_beta.rbmf b/examples/text/font_select/fonts/alpha_beta.rbmf deleted file mode 100644 index bdb2e75..0000000 Binary files a/examples/text/font_select/fonts/alpha_beta.rbmf and /dev/null differ diff --git a/examples/text/font_select/fonts/jupiter_crash.rbmf b/examples/text/font_select/fonts/jupiter_crash.rbmf deleted file mode 100644 index d797e0d..0000000 Binary files a/examples/text/font_select/fonts/jupiter_crash.rbmf and /dev/null differ diff --git a/examples/text/font_select/fonts/mecha.rbmf b/examples/text/font_select/fonts/mecha.rbmf deleted file mode 100644 index 0266a06..0000000 Binary files a/examples/text/font_select/fonts/mecha.rbmf and /dev/null differ diff --git a/examples/text/font_select/fonts/pixantiqua.rbmf b/examples/text/font_select/fonts/pixantiqua.rbmf deleted file mode 100644 index 04ef0e2..0000000 Binary files a/examples/text/font_select/fonts/pixantiqua.rbmf and /dev/null differ diff --git a/examples/text/font_select/fonts/pixelplay.rbmf b/examples/text/font_select/fonts/pixelplay.rbmf deleted file mode 100644 index 31d1403..0000000 Binary files a/examples/text/font_select/fonts/pixelplay.rbmf and /dev/null differ diff --git a/examples/text/font_select/fonts/romulus.rbmf b/examples/text/font_select/fonts/romulus.rbmf deleted file mode 100644 index be9da01..0000000 Binary files a/examples/text/font_select/fonts/romulus.rbmf and /dev/null differ diff --git a/examples/text/font_select/fonts/setback.rbmf b/examples/text/font_select/fonts/setback.rbmf deleted file mode 100644 index 0957221..0000000 Binary files a/examples/text/font_select/fonts/setback.rbmf and /dev/null differ diff --git a/examples/text/font_select/main.go b/examples/text/font_select/main.go deleted file mode 100644 index a6fc138..0000000 --- a/examples/text/font_select/main.go +++ /dev/null @@ -1,140 +0,0 @@ -package main - -import ( - "github.com/gen2brain/raylib-go/raylib" -) - -func main() { - screenWidth := int32(800) - screenHeight := int32(450) - - raylib.InitWindow(screenWidth, screenHeight, "raylib [text] example - font selector") - - // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) - fonts := make([]raylib.SpriteFont, 8) // SpriteFont array - - fonts[0] = raylib.LoadSpriteFont("fonts/alagard.rbmf") // SpriteFont loading - fonts[1] = raylib.LoadSpriteFont("fonts/pixelplay.rbmf") // SpriteFont loading - fonts[2] = raylib.LoadSpriteFont("fonts/mecha.rbmf") // SpriteFont loading - fonts[3] = raylib.LoadSpriteFont("fonts/setback.rbmf") // SpriteFont loading - fonts[4] = raylib.LoadSpriteFont("fonts/romulus.rbmf") // SpriteFont loading - fonts[5] = raylib.LoadSpriteFont("fonts/pixantiqua.rbmf") // SpriteFont loading - fonts[6] = raylib.LoadSpriteFont("fonts/alpha_beta.rbmf") // SpriteFont loading - fonts[7] = raylib.LoadSpriteFont("fonts/jupiter_crash.rbmf") // SpriteFont loading - - currentFont := 0 // Selected font - - colors := [8]raylib.Color{raylib.Maroon, raylib.Orange, raylib.DarkGreen, raylib.DarkBlue, raylib.DarkPurple, raylib.Lime, raylib.Gold, raylib.Red} - - fontNames := [8]string{"[0] Alagard", "[1] PixelPlay", "[2] MECHA", "[3] Setback", "[4] Romulus", "[5] PixAntiqua", "[6] Alpha Beta", "[7] Jupiter Crash"} - - text := "THIS is THE FONT you SELECTED!" // Main text - - textSize := raylib.MeasureTextEx(fonts[currentFont], text, float32(fonts[currentFont].BaseSize)*3, 1) - - mousePoint := raylib.Vector2{} - - btnNextOutColor := raylib.DarkBlue // Button color (outside line) - btnNextInColor := raylib.SkyBlue // Button color (inside) - - framesCounter := 0 // Useful to count frames button is 'active' = clicked - - positionY := int32(180) // Text selector and button Y position - - btnNextRec := raylib.NewRectangle(673, positionY, 109, 44) // Button rectangle (useful for collision) - - raylib.SetTargetFPS(60) - - for !raylib.WindowShouldClose() { - // Update - - // Keyboard-based font selection (easy) - if raylib.IsKeyPressed(raylib.KeyRight) { - if currentFont < 7 { - currentFont++ - } - } - - if raylib.IsKeyPressed(raylib.KeyLeft) { - if currentFont > 0 { - currentFont-- - } - } - - if raylib.IsKeyPressed('0') { - currentFont = 0 - } else if raylib.IsKeyPressed('1') { - currentFont = 1 - } else if raylib.IsKeyPressed('2') { - currentFont = 2 - } else if raylib.IsKeyPressed('3') { - currentFont = 3 - } else if raylib.IsKeyPressed('4') { - currentFont = 4 - } else if raylib.IsKeyPressed('5') { - currentFont = 5 - } else if raylib.IsKeyPressed('6') { - currentFont = 6 - } else if raylib.IsKeyPressed('7') { - currentFont = 7 - } - - // Mouse-based font selection (NEXT button logic) - mousePoint = raylib.GetMousePosition() - - if raylib.CheckCollisionPointRec(mousePoint, btnNextRec) { - // Mouse hover button logic - if framesCounter == 0 { - btnNextOutColor = raylib.DarkPurple - btnNextInColor = raylib.Purple - } - - if raylib.IsMouseButtonDown(raylib.MouseLeftButton) { - framesCounter = 20 // Frames button is 'active' - btnNextOutColor = raylib.Maroon - btnNextInColor = raylib.Red - } - } else { - // Mouse not hover button - btnNextOutColor = raylib.DarkBlue - btnNextInColor = raylib.SkyBlue - } - - if framesCounter > 0 { - framesCounter-- - } - - if framesCounter == 1 { // We change font on frame 1 - currentFont++ - if currentFont > 7 { - currentFont = 0 - } - } - - // Text measurement for better positioning on screen - textSize = raylib.MeasureTextEx(fonts[currentFont], text, float32(fonts[currentFont].BaseSize)*3, 1) - - // Draw - raylib.BeginDrawing() - - raylib.ClearBackground(raylib.RayWhite) - - raylib.DrawText("font selector - use arroys, button or numbers", 160, 80, 20, raylib.DarkGray) - raylib.DrawLine(120, 120, 680, 120, raylib.DarkGray) - - raylib.DrawRectangle(18, positionY, 644, 44, raylib.DarkGray) - raylib.DrawRectangle(20, positionY+2, 640, 40, raylib.LightGray) - raylib.DrawText(fontNames[currentFont], 30, positionY+13, 20, raylib.Black) - raylib.DrawText("< >", 610, positionY+8, 30, raylib.Black) - - raylib.DrawRectangleRec(btnNextRec, btnNextOutColor) - raylib.DrawRectangle(675, positionY+2, 105, 40, btnNextInColor) - raylib.DrawText("NEXT", 700, positionY+13, 20, btnNextOutColor) - - raylib.DrawTextEx(fonts[currentFont], text, raylib.NewVector2(float32(screenWidth)/2-textSize.X/2, 260+(70-textSize.Y)/2), float32(fonts[currentFont].BaseSize*3), 1, colors[currentFont]) - - raylib.EndDrawing() - } - - raylib.CloseWindow() -} diff --git a/examples/text/raylib_fonts/fonts/alagard.png b/examples/text/raylib_fonts/fonts/alagard.png new file mode 100644 index 0000000..3ac4bf1 Binary files /dev/null and b/examples/text/raylib_fonts/fonts/alagard.png differ diff --git a/examples/text/raylib_fonts/fonts/alpha_beta.png b/examples/text/raylib_fonts/fonts/alpha_beta.png new file mode 100644 index 0000000..c362bfb Binary files /dev/null and b/examples/text/raylib_fonts/fonts/alpha_beta.png differ diff --git a/examples/text/raylib_fonts/fonts/jupiter_crash.png b/examples/text/raylib_fonts/fonts/jupiter_crash.png new file mode 100644 index 0000000..1f5172f Binary files /dev/null and b/examples/text/raylib_fonts/fonts/jupiter_crash.png differ diff --git a/examples/text/raylib_fonts/fonts/mecha.png b/examples/text/raylib_fonts/fonts/mecha.png new file mode 100644 index 0000000..8022d18 Binary files /dev/null and b/examples/text/raylib_fonts/fonts/mecha.png differ diff --git a/examples/text/raylib_fonts/fonts/pixantiqua.png b/examples/text/raylib_fonts/fonts/pixantiqua.png new file mode 100644 index 0000000..ce422e7 Binary files /dev/null and b/examples/text/raylib_fonts/fonts/pixantiqua.png differ diff --git a/examples/text/raylib_fonts/fonts/pixelplay.png b/examples/text/raylib_fonts/fonts/pixelplay.png new file mode 100644 index 0000000..bf8f881 Binary files /dev/null and b/examples/text/raylib_fonts/fonts/pixelplay.png differ diff --git a/examples/text/raylib_fonts/fonts/romulus.png b/examples/text/raylib_fonts/fonts/romulus.png new file mode 100644 index 0000000..46ccc32 Binary files /dev/null and b/examples/text/raylib_fonts/fonts/romulus.png differ diff --git a/examples/text/raylib_fonts/fonts/setback.png b/examples/text/raylib_fonts/fonts/setback.png new file mode 100644 index 0000000..086f3e2 Binary files /dev/null and b/examples/text/raylib_fonts/fonts/setback.png differ diff --git a/examples/text/rbmf_fonts/main.go b/examples/text/raylib_fonts/main.go similarity index 66% rename from examples/text/rbmf_fonts/main.go rename to examples/text/raylib_fonts/main.go index fdd7a70..10023b5 100644 --- a/examples/text/rbmf_fonts/main.go +++ b/examples/text/raylib_fonts/main.go @@ -4,21 +4,23 @@ import ( "github.com/gen2brain/raylib-go/raylib" ) +const maxFonts = 8 + func main() { screenWidth := int32(800) screenHeight := int32(450) - raylib.InitWindow(screenWidth, screenHeight, "raylib [text] example - rBMF fonts") + raylib.InitWindow(screenWidth, screenHeight, "raylib [text] example - raylib fonts") - fonts := make([]raylib.SpriteFont, 8) - fonts[0] = raylib.LoadSpriteFont("fonts/alagard.rbmf") - fonts[1] = raylib.LoadSpriteFont("fonts/pixelplay.rbmf") - fonts[2] = raylib.LoadSpriteFont("fonts/mecha.rbmf") - fonts[3] = raylib.LoadSpriteFont("fonts/setback.rbmf") - fonts[4] = raylib.LoadSpriteFont("fonts/romulus.rbmf") - fonts[5] = raylib.LoadSpriteFont("fonts/pixantiqua.rbmf") - fonts[6] = raylib.LoadSpriteFont("fonts/alpha_beta.rbmf") - fonts[7] = raylib.LoadSpriteFont("fonts/jupiter_crash.rbmf") + fonts := make([]raylib.SpriteFont, maxFonts) + fonts[0] = raylib.LoadSpriteFont("fonts/alagard.png") + fonts[1] = raylib.LoadSpriteFont("fonts/pixelplay.png") + fonts[2] = raylib.LoadSpriteFont("fonts/mecha.png") + fonts[3] = raylib.LoadSpriteFont("fonts/setback.png") + fonts[4] = raylib.LoadSpriteFont("fonts/romulus.png") + fonts[5] = raylib.LoadSpriteFont("fonts/pixantiqua.png") + fonts[6] = raylib.LoadSpriteFont("fonts/alpha_beta.png") + fonts[7] = raylib.LoadSpriteFont("fonts/jupiter_crash.png") messages := []string{ "ALAGARD FONT designed by Hewett Tsoi", @@ -32,15 +34,20 @@ func main() { } spacings := []int32{2, 4, 8, 4, 3, 4, 4, 1} - positions := make([]raylib.Vector2, 8) + positions := make([]raylib.Vector2, maxFonts) var i int32 - for i = 0; i < 8; i++ { + for i = 0; i < maxFonts; i++ { x := screenWidth/2 - int32(raylib.MeasureTextEx(fonts[i], messages[i], float32(fonts[i].BaseSize*2), spacings[i]).X/2) y := 60 + fonts[i].BaseSize + 45*i positions[i] = raylib.NewVector2(float32(x), float32(y)) } + // Small Y position corrections + positions[3].Y += 8 + positions[4].Y += 2 + positions[7].Y -= 8 + colors := []raylib.Color{raylib.Maroon, raylib.Orange, raylib.DarkGreen, raylib.DarkBlue, raylib.DarkPurple, raylib.Lime, raylib.Gold, raylib.DarkBrown} raylib.SetTargetFPS(60) @@ -52,14 +59,14 @@ func main() { raylib.DrawText("free fonts included with raylib", 250, 20, 20, raylib.DarkGray) raylib.DrawLine(220, 50, 590, 50, raylib.DarkGray) - for i = 0; i < 8; i++ { + for i = 0; i < maxFonts; i++ { raylib.DrawTextEx(fonts[i], messages[i], positions[i], float32(fonts[i].BaseSize*2), spacings[i], colors[i]) } raylib.EndDrawing() } - for i = 0; i < 8; i++ { + for i = 0; i < maxFonts; i++ { raylib.UnloadSpriteFont(fonts[i]) } diff --git a/examples/text/rbmf_fonts/fonts/alagard.rbmf b/examples/text/rbmf_fonts/fonts/alagard.rbmf deleted file mode 100644 index 8c9b68d..0000000 Binary files a/examples/text/rbmf_fonts/fonts/alagard.rbmf and /dev/null differ diff --git a/examples/text/rbmf_fonts/fonts/alpha_beta.rbmf b/examples/text/rbmf_fonts/fonts/alpha_beta.rbmf deleted file mode 100644 index bdb2e75..0000000 Binary files a/examples/text/rbmf_fonts/fonts/alpha_beta.rbmf and /dev/null differ diff --git a/examples/text/rbmf_fonts/fonts/jupiter_crash.rbmf b/examples/text/rbmf_fonts/fonts/jupiter_crash.rbmf deleted file mode 100644 index d797e0d..0000000 Binary files a/examples/text/rbmf_fonts/fonts/jupiter_crash.rbmf and /dev/null differ diff --git a/examples/text/rbmf_fonts/fonts/mecha.rbmf b/examples/text/rbmf_fonts/fonts/mecha.rbmf deleted file mode 100644 index 0266a06..0000000 Binary files a/examples/text/rbmf_fonts/fonts/mecha.rbmf and /dev/null differ diff --git a/examples/text/rbmf_fonts/fonts/pixantiqua.rbmf b/examples/text/rbmf_fonts/fonts/pixantiqua.rbmf deleted file mode 100644 index 04ef0e2..0000000 Binary files a/examples/text/rbmf_fonts/fonts/pixantiqua.rbmf and /dev/null differ diff --git a/examples/text/rbmf_fonts/fonts/pixelplay.rbmf b/examples/text/rbmf_fonts/fonts/pixelplay.rbmf deleted file mode 100644 index 31d1403..0000000 Binary files a/examples/text/rbmf_fonts/fonts/pixelplay.rbmf and /dev/null differ diff --git a/examples/text/rbmf_fonts/fonts/romulus.rbmf b/examples/text/rbmf_fonts/fonts/romulus.rbmf deleted file mode 100644 index be9da01..0000000 Binary files a/examples/text/rbmf_fonts/fonts/romulus.rbmf and /dev/null differ diff --git a/examples/text/rbmf_fonts/fonts/setback.rbmf b/examples/text/rbmf_fonts/fonts/setback.rbmf deleted file mode 100644 index 0957221..0000000 Binary files a/examples/text/rbmf_fonts/fonts/setback.rbmf and /dev/null differ diff --git a/examples/text/ttf_loading/main.go b/examples/text/ttf_loading/main.go index 709f0b5..f9d3eaa 100644 --- a/examples/text/ttf_loading/main.go +++ b/examples/text/ttf_loading/main.go @@ -19,7 +19,7 @@ func main() { fontChars := int32(0) // TTF SpriteFont loading with custom generation parameters - font := raylib.LoadSpriteFontTTF("fonts/KAISG.ttf", 96, 0, &fontChars) + font := raylib.LoadSpriteFontEx("fonts/KAISG.ttf", 96, 0, &fontChars) // Generate mipmap levels to use trilinear filtering // NOTE: On 2D drawing it won't be noticeable, it looks like FILTER_BILINEAR @@ -69,7 +69,7 @@ func main() { if count == 1 { // Only support one ttf file dropped raylib.UnloadSpriteFont(font) - font = raylib.LoadSpriteFontTTF(droppedFiles[0], fontSize, 0, &fontChars) + font = raylib.LoadSpriteFontEx(droppedFiles[0], fontSize, 0, &fontChars) raylib.ClearDroppedFiles() } } diff --git a/examples/textures/formats_loading/main.go b/examples/textures/formats_loading/main.go deleted file mode 100644 index ee44721..0000000 --- a/examples/textures/formats_loading/main.go +++ /dev/null @@ -1,220 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/gen2brain/raylib-go/raylib" -) - -const numTextures = 24 - -// Formats -const ( - PngR8g8b8a8 = iota - PvrGrayscale - PvrGrayAlpha - PvrR5g6b5 - PvrR5g5b5a1 - PvrR4g4b4a4 - DdsR5g6b5 - DdsR5g5b5a1 - DdsR4g4b4a4 - DdsR8g8b8a8 - DdsDxt1Rgb - DdsDxt1Rgba - DdsDxt3Rgba - DdsDxt5Rgba - PkmEtc1Rgb - PkmEtc2Rgb - PkmEtc2EacRgba - KtxEtc1Rgb - KtxEtc2Rgb - KtxEtc2EacRgba - Astc4x4Ldr - Astc8x8Ldr - PvrPvrtRgb - PvrPvrtRgba -) - -var formatText = []string{ - "PNG_R8G8B8A8", - "PVR_GRAYSCALE", - "PVR_GRAY_ALPHA", - "PVR_R5G6B5", - "PVR_R5G5B5A1", - "PVR_R4G4B4A4", - "DDS_R5G6B5", - "DDS_R5G5B5A1", - "DDS_R4G4B4A4", - "DDS_R8G8B8A8", - "DDS_DXT1_RGB", - "DDS_DXT1_RGBA", - "DDS_DXT3_RGBA", - "DDS_DXT5_RGBA", - "PKM_ETC1_RGB", - "PKM_ETC2_RGB", - "PKM_ETC2_EAC_RGBA", - "KTX_ETC1_RGB", - "KTX_ETC2_RGB", - "KTX_ETC2_EAC_RGBA", - "ASTC_4x4_LDR", - "ASTC_8x8_LDR", - "PVR_PVRT_RGB", - "PVR_PVRT_RGBA", -} - -func main() { - screenWidth := int32(800) - screenHeight := int32(450) - - raylib.InitWindow(screenWidth, screenHeight, "raylib [textures] example - texture formats loading") - - // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) - - sonic := make([]raylib.Texture2D, numTextures) - - sonic[PngR8g8b8a8] = raylib.LoadTexture("texture_formats/sonic.png") - - // Load UNCOMPRESSED PVR texture data - sonic[PvrGrayscale] = raylib.LoadTexture("texture_formats/sonic_GRAYSCALE.pvr") - sonic[PvrGrayAlpha] = raylib.LoadTexture("texture_formats/sonic_L8A8.pvr") - sonic[PvrR5g6b5] = raylib.LoadTexture("texture_formats/sonic_R5G6B5.pvr") - sonic[PvrR5g5b5a1] = raylib.LoadTexture("texture_formats/sonic_R5G5B5A1.pvr") - sonic[PvrR4g4b4a4] = raylib.LoadTexture("texture_formats/sonic_R4G4B4A4.pvr") - - // Load UNCOMPRESSED DDS texture data - sonic[DdsR5g6b5] = raylib.LoadTexture("texture_formats/sonic_R5G6B5.dds") - sonic[DdsR5g5b5a1] = raylib.LoadTexture("texture_formats/sonic_A1R5G5B5.dds") - sonic[DdsR4g4b4a4] = raylib.LoadTexture("texture_formats/sonic_A4R4G4B4.dds") - sonic[DdsR8g8b8a8] = raylib.LoadTexture("texture_formats/sonic_A8R8G8B8.dds") - - // Load COMPRESSED DXT DDS texture data (if supported) - sonic[DdsDxt1Rgb] = raylib.LoadTexture("texture_formats/sonic_DXT1_RGB.dds") - sonic[DdsDxt1Rgba] = raylib.LoadTexture("texture_formats/sonic_DXT1_RGBA.dds") - sonic[DdsDxt3Rgba] = raylib.LoadTexture("texture_formats/sonic_DXT3_RGBA.dds") - sonic[DdsDxt5Rgba] = raylib.LoadTexture("texture_formats/sonic_DXT5_RGBA.dds") - - // Load COMPRESSED ETC texture data (if supported) - sonic[PkmEtc1Rgb] = raylib.LoadTexture("texture_formats/sonic_ETC1_RGB.pkm") - sonic[PkmEtc2Rgb] = raylib.LoadTexture("texture_formats/sonic_ETC2_RGB.pkm") - sonic[PkmEtc2EacRgba] = raylib.LoadTexture("texture_formats/sonic_ETC2_EAC_RGBA.pkm") - - sonic[KtxEtc1Rgb] = raylib.LoadTexture("texture_formats/sonic_ETC1_RGB.ktx") - sonic[KtxEtc2Rgb] = raylib.LoadTexture("texture_formats/sonic_ETC2_RGB.ktx") - sonic[KtxEtc2EacRgba] = raylib.LoadTexture("texture_formats/sonic_ETC2_EAC_RGBA.ktx") - - // Load COMPRESSED ASTC texture data (if supported) - sonic[Astc4x4Ldr] = raylib.LoadTexture("texture_formats/sonic_ASTC_4x4_ldr.astc") - sonic[Astc8x8Ldr] = raylib.LoadTexture("texture_formats/sonic_ASTC_8x8_ldr.astc") - - // Load COMPRESSED PVR texture data (if supported) - sonic[PvrPvrtRgb] = raylib.LoadTexture("texture_formats/sonic_PVRT_RGB.pvr") - sonic[PvrPvrtRgba] = raylib.LoadTexture("texture_formats/sonic_PVRT_RGBA.pvr") - - selectedFormat := PngR8g8b8a8 - - selectRecs := make([]raylib.Rectangle, numTextures) - - for i := 0; i < numTextures; i++ { - if i < numTextures/2 { - selectRecs[i] = raylib.NewRectangle(40, int32(30+32*i), 150, 30) - } else { - selectRecs[i] = raylib.NewRectangle(40+152, int32(30+32*(i-numTextures/2)), 150, 30) - } - } - - // Texture sizes in KB - var textureSizes = [numTextures]int{ - 512 * 512 * 32 / 8 / 1024, //PNG_R8G8B8A8 (32 bpp) - 512 * 512 * 8 / 8 / 1024, //PVR_GRAYSCALE (8 bpp) - 512 * 512 * 16 / 8 / 1024, //PVR_GRAY_ALPHA (16 bpp) - 512 * 512 * 16 / 8 / 1024, //PVR_R5G6B5 (16 bpp) - 512 * 512 * 16 / 8 / 1024, //PVR_R5G5B5A1 (16 bpp) - 512 * 512 * 16 / 8 / 1024, //PVR_R4G4B4A4 (16 bpp) - 512 * 512 * 16 / 8 / 1024, //DDS_R5G6B5 (16 bpp) - 512 * 512 * 16 / 8 / 1024, //DDS_R5G5B5A1 (16 bpp) - 512 * 512 * 16 / 8 / 1024, //DDS_R4G4B4A4 (16 bpp) - 512 * 512 * 32 / 8 / 1024, //DDS_R8G8B8A8 (32 bpp) - 512 * 512 * 4 / 8 / 1024, //DDS_DXT1_RGB (4 bpp) -Compressed- - 512 * 512 * 4 / 8 / 1024, //DDS_DXT1_RGBA (4 bpp) -Compressed- - 512 * 512 * 8 / 8 / 1024, //DDS_DXT3_RGBA (8 bpp) -Compressed- - 512 * 512 * 8 / 8 / 1024, //DDS_DXT5_RGBA (8 bpp) -Compressed- - 512 * 512 * 4 / 8 / 1024, //PKM_ETC1_RGB (4 bpp) -Compressed- - 512 * 512 * 4 / 8 / 1024, //PKM_ETC2_RGB (4 bpp) -Compressed- - 512 * 512 * 8 / 8 / 1024, //PKM_ETC2_EAC_RGBA (8 bpp) -Compressed- - 512 * 512 * 4 / 8 / 1024, //KTX_ETC1_RGB (4 bpp) -Compressed- - 512 * 512 * 4 / 8 / 1024, //KTX_ETC2_RGB (4 bpp) -Compressed- - 512 * 512 * 8 / 8 / 1024, //KTX_ETC2_EAC_RGBA (8 bpp) -Compressed- - 512 * 512 * 8 / 8 / 1024, //ASTC_4x4_LDR (8 bpp) -Compressed- - 512 * 512 * 2 / 8 / 1024, //ASTC_8x8_LDR (2 bpp) -Compressed- - 512 * 512 * 4 / 8 / 1024, //PVR_PVRT_RGB (4 bpp) -Compressed- - 512 * 512 * 4 / 8 / 1024, //PVR_PVRT_RGBA (4 bpp) -Compressed- - } - - raylib.SetTargetFPS(60) - - for !raylib.WindowShouldClose() { - // Update - - if raylib.IsKeyPressed(raylib.KeyDown) { - selectedFormat++ - if selectedFormat >= numTextures { - selectedFormat = 0 - } - } else if raylib.IsKeyPressed(raylib.KeyUp) { - selectedFormat-- - if selectedFormat < 0 { - selectedFormat = numTextures - 1 - } - } else if raylib.IsKeyPressed(raylib.KeyRight) { - if selectedFormat < numTextures/2 { - selectedFormat += numTextures / 2 - } - } else if raylib.IsKeyPressed(raylib.KeyLeft) { - if selectedFormat >= numTextures/2 { - selectedFormat -= numTextures / 2 - } - } - - // Draw - - raylib.BeginDrawing() - - raylib.ClearBackground(raylib.RayWhite) - - // Draw rectangles - for i := 0; i < numTextures; i++ { - if i == selectedFormat { - raylib.DrawRectangleRec(selectRecs[i], raylib.SkyBlue) - raylib.DrawRectangleLines(selectRecs[i].X, selectRecs[i].Y, selectRecs[i].Width, selectRecs[i].Height, raylib.Blue) - raylib.DrawText(formatText[i], selectRecs[i].X+selectRecs[i].Width/2-raylib.MeasureText(formatText[i], 10)/2, selectRecs[i].Y+11, 10, raylib.DarkBlue) - } else { - raylib.DrawRectangleRec(selectRecs[i], raylib.LightGray) - raylib.DrawRectangleLines(selectRecs[i].X, selectRecs[i].Y, selectRecs[i].Width, selectRecs[i].Height, raylib.Gray) - raylib.DrawText(formatText[i], selectRecs[i].X+selectRecs[i].Width/2-raylib.MeasureText(formatText[i], 10)/2, selectRecs[i].Y+11, 10, raylib.DarkGray) - } - } - - // Draw selected texture - if sonic[selectedFormat].ID != 0 { - raylib.DrawTexture(sonic[selectedFormat], 350, -10, raylib.White) - } else { - raylib.DrawRectangleLines(488, 165, 200, 110, raylib.DarkGray) - raylib.DrawText("FORMAT", 550, 180, 20, raylib.Maroon) - raylib.DrawText("NOT SUPPORTED", 500, 210, 20, raylib.Maroon) - raylib.DrawText("ON YOUR GPU", 520, 240, 20, raylib.Maroon) - } - - raylib.DrawText("Select texture format (use cursor keys):", 40, 10, 10, raylib.DarkGray) - raylib.DrawText("Required GPU memory size (VRAM):", 40, 427, 10, raylib.DarkGray) - raylib.DrawText(fmt.Sprintf("%4.0d KB", textureSizes[selectedFormat]), 240, 420, 20, raylib.DarkBlue) - - raylib.EndDrawing() - } - - for i := 0; i < numTextures; i++ { - raylib.UnloadTexture(sonic[i]) - } - - raylib.CloseWindow() -} diff --git a/examples/textures/formats_loading/texture_formats/sonic.png b/examples/textures/formats_loading/texture_formats/sonic.png deleted file mode 100644 index 7a09684..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic.png and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_A1R5G5B5.dds b/examples/textures/formats_loading/texture_formats/sonic_A1R5G5B5.dds deleted file mode 100644 index 5e2347d..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_A1R5G5B5.dds and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_A4R4G4B4.dds b/examples/textures/formats_loading/texture_formats/sonic_A4R4G4B4.dds deleted file mode 100644 index c5ccaf0..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_A4R4G4B4.dds and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_A8R8G8B8.dds b/examples/textures/formats_loading/texture_formats/sonic_A8R8G8B8.dds deleted file mode 100644 index fb71b7b..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_A8R8G8B8.dds and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_ASTC_4x4_ldr.astc b/examples/textures/formats_loading/texture_formats/sonic_ASTC_4x4_ldr.astc deleted file mode 100644 index 9a98d9a..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_ASTC_4x4_ldr.astc and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_ASTC_8x8_ldr.astc b/examples/textures/formats_loading/texture_formats/sonic_ASTC_8x8_ldr.astc deleted file mode 100644 index 360a264..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_ASTC_8x8_ldr.astc and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_DXT1_RGB.dds b/examples/textures/formats_loading/texture_formats/sonic_DXT1_RGB.dds deleted file mode 100644 index 9d0b459..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_DXT1_RGB.dds and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_DXT1_RGBA.dds b/examples/textures/formats_loading/texture_formats/sonic_DXT1_RGBA.dds deleted file mode 100644 index 102bae7..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_DXT1_RGBA.dds and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_DXT3_RGBA.dds b/examples/textures/formats_loading/texture_formats/sonic_DXT3_RGBA.dds deleted file mode 100644 index 46d965c..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_DXT3_RGBA.dds and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_DXT5_RGBA.dds b/examples/textures/formats_loading/texture_formats/sonic_DXT5_RGBA.dds deleted file mode 100644 index b3a59a7..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_DXT5_RGBA.dds and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_ETC1_RGB.ktx b/examples/textures/formats_loading/texture_formats/sonic_ETC1_RGB.ktx deleted file mode 100644 index 66241b9..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_ETC1_RGB.ktx and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_ETC1_RGB.pkm b/examples/textures/formats_loading/texture_formats/sonic_ETC1_RGB.pkm deleted file mode 100644 index c6fc6df..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_ETC1_RGB.pkm and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_ETC2_EAC_RGBA.ktx b/examples/textures/formats_loading/texture_formats/sonic_ETC2_EAC_RGBA.ktx deleted file mode 100644 index b01812c..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_ETC2_EAC_RGBA.ktx and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_ETC2_EAC_RGBA.old.pkm b/examples/textures/formats_loading/texture_formats/sonic_ETC2_EAC_RGBA.old.pkm deleted file mode 100644 index 61ac48c..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_ETC2_EAC_RGBA.old.pkm and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_ETC2_EAC_RGBA.pkm b/examples/textures/formats_loading/texture_formats/sonic_ETC2_EAC_RGBA.pkm deleted file mode 100644 index 61ac48c..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_ETC2_EAC_RGBA.pkm and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_ETC2_RGB.ktx b/examples/textures/formats_loading/texture_formats/sonic_ETC2_RGB.ktx deleted file mode 100644 index 7f1207f..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_ETC2_RGB.ktx and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_ETC2_RGB.pkm b/examples/textures/formats_loading/texture_formats/sonic_ETC2_RGB.pkm deleted file mode 100644 index f290f01..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_ETC2_RGB.pkm and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_GRAYSCALE.pvr b/examples/textures/formats_loading/texture_formats/sonic_GRAYSCALE.pvr deleted file mode 100644 index d31e265..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_GRAYSCALE.pvr and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_L8A8.pvr b/examples/textures/formats_loading/texture_formats/sonic_L8A8.pvr deleted file mode 100644 index ccf5932..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_L8A8.pvr and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_PVRT_RGB.pvr b/examples/textures/formats_loading/texture_formats/sonic_PVRT_RGB.pvr deleted file mode 100644 index 22f3f66..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_PVRT_RGB.pvr and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_PVRT_RGBA.pvr b/examples/textures/formats_loading/texture_formats/sonic_PVRT_RGBA.pvr deleted file mode 100644 index feb9aea..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_PVRT_RGBA.pvr and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_PVRT_RGBA_2bpp.pvr b/examples/textures/formats_loading/texture_formats/sonic_PVRT_RGBA_2bpp.pvr deleted file mode 100644 index 9147e1b..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_PVRT_RGBA_2bpp.pvr and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_PVRT_RGB_2bpp.pvr b/examples/textures/formats_loading/texture_formats/sonic_PVRT_RGB_2bpp.pvr deleted file mode 100644 index 2a8aea8..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_PVRT_RGB_2bpp.pvr and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_R4G4B4A4.pvr b/examples/textures/formats_loading/texture_formats/sonic_R4G4B4A4.pvr deleted file mode 100644 index 3f7368a..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_R4G4B4A4.pvr and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_R5G5B5A1.pvr b/examples/textures/formats_loading/texture_formats/sonic_R5G5B5A1.pvr deleted file mode 100644 index c7fa098..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_R5G5B5A1.pvr and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_R5G6B5.dds b/examples/textures/formats_loading/texture_formats/sonic_R5G6B5.dds deleted file mode 100644 index 217da95..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_R5G6B5.dds and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_R5G6B5.pvr b/examples/textures/formats_loading/texture_formats/sonic_R5G6B5.pvr deleted file mode 100644 index 9bb8320..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_R5G6B5.pvr and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_R8G8B8.pvr b/examples/textures/formats_loading/texture_formats/sonic_R8G8B8.pvr deleted file mode 100644 index 072cf3e..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_R8G8B8.pvr and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_R8G8B8A8.pvr b/examples/textures/formats_loading/texture_formats/sonic_R8G8B8A8.pvr deleted file mode 100644 index f82534f..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_R8G8B8A8.pvr and /dev/null differ diff --git a/examples/textures/formats_loading/texture_formats/sonic_R8G8B8A8.raw b/examples/textures/formats_loading/texture_formats/sonic_R8G8B8A8.raw deleted file mode 100644 index fc5858e..0000000 Binary files a/examples/textures/formats_loading/texture_formats/sonic_R8G8B8A8.raw and /dev/null differ diff --git a/examples/textures/particles_trail_blending/main.go b/examples/textures/particles_blending/main.go similarity index 98% rename from examples/textures/particles_trail_blending/main.go rename to examples/textures/particles_blending/main.go index 301a5fa..2a87165 100644 --- a/examples/textures/particles_trail_blending/main.go +++ b/examples/textures/particles_blending/main.go @@ -22,7 +22,7 @@ func main() { screenHeight := int32(450) //raylib.SetConfigFlags(raylib.FlagVsyncHint) - raylib.InitWindow(screenWidth, screenHeight, "raylib [textures] example - particles trail blending") + raylib.InitWindow(screenWidth, screenHeight, "raylib [textures] example - particles blending") // Particles pool, reuse them! mouseTail := make([]particle, maxParticles) diff --git a/examples/textures/particles_trail_blending/smoke.png b/examples/textures/particles_blending/smoke.png similarity index 100% rename from examples/textures/particles_trail_blending/smoke.png rename to examples/textures/particles_blending/smoke.png diff --git a/examples/textures/raw_data/main.go b/examples/textures/raw_data/main.go index 513dab0..c0f5203 100644 --- a/examples/textures/raw_data/main.go +++ b/examples/textures/raw_data/main.go @@ -12,10 +12,10 @@ func main() { // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) - // Load RAW image data (512x512, 32bit RGBA, no file header) - sonicRaw := raylib.LoadImageRaw("texture_formats/sonic_R8G8B8A8.raw", 512, 512, raylib.UncompressedR8g8b8a8, 0) - sonic := raylib.LoadTextureFromImage(sonicRaw) // Upload CPU (RAM) image to GPU (VRAM) - raylib.UnloadImage(sonicRaw) // Unload CPU (RAM) image data + // Load RAW image data (384x512, 32bit RGBA, no file header) + fudesumiRaw := raylib.LoadImageRaw("texture_formats/fudesumi.raw", 384, 512, raylib.UncompressedR8g8b8a8, 0) + fudesumi := raylib.LoadTextureFromImage(fudesumiRaw) // Upload CPU (RAM) image to GPU (VRAM) + raylib.UnloadImage(fudesumiRaw) // Unload CPU (RAM) image data // Generate a checked texture by code (1024x1024 pixels) width := 1024 @@ -27,9 +27,9 @@ func main() { for y := 0; y < height; y++ { for x := 0; x < width; x++ { if ((x/32+y/32)/1)%2 == 0 { - pixels[y*height+x] = raylib.DarkBlue + pixels[y*height+x] = raylib.Orange } else { - pixels[y*height+x] = raylib.SkyBlue + pixels[y*height+x] = raylib.Gold } } } @@ -46,18 +46,18 @@ func main() { raylib.ClearBackground(raylib.RayWhite) - raylib.DrawTexture(checked, screenWidth/2-checked.Width/2, screenHeight/2-checked.Height/2, raylib.Fade(raylib.White, 0.3)) - raylib.DrawTexture(sonic, 330, -20, raylib.White) + raylib.DrawTexture(checked, screenWidth/2-checked.Width/2, screenHeight/2-checked.Height/2, raylib.Fade(raylib.White, 0.5)) + raylib.DrawTexture(fudesumi, 430, -30, raylib.White) - raylib.DrawText("CHECKED TEXTURE ", 84, 100, 30, raylib.DarkBlue) - raylib.DrawText("GENERATED by CODE", 72, 164, 30, raylib.DarkBlue) - raylib.DrawText("and RAW IMAGE LOADING", 46, 226, 30, raylib.DarkBlue) + raylib.DrawText("CHECKED TEXTURE ", 84, 100, 30, raylib.Brown) + raylib.DrawText("GENERATED by CODE", 72, 164, 30, raylib.Brown) + raylib.DrawText("and RAW IMAGE LOADING", 46, 226, 30, raylib.Brown) raylib.EndDrawing() } - raylib.UnloadTexture(sonic) // Texture unloading - raylib.UnloadTexture(checked) // Texture unloading + raylib.UnloadTexture(fudesumi) // Texture unloading + raylib.UnloadTexture(checked) // Texture unloading raylib.CloseWindow() } diff --git a/examples/textures/raw_data/texture_formats/fudesumi.raw b/examples/textures/raw_data/texture_formats/fudesumi.raw new file mode 100644 index 0000000..dad6ff0 Binary files /dev/null and b/examples/textures/raw_data/texture_formats/fudesumi.raw differ diff --git a/examples/textures/raw_data/texture_formats/sonic_R8G8B8A8.raw b/examples/textures/raw_data/texture_formats/sonic_R8G8B8A8.raw deleted file mode 100644 index fc5858e..0000000 Binary files a/examples/textures/raw_data/texture_formats/sonic_R8G8B8A8.raw and /dev/null differ diff --git a/examples/textures/rectangle/guybrush.png b/examples/textures/rectangle/guybrush.png deleted file mode 100644 index 32c9dce..0000000 Binary files a/examples/textures/rectangle/guybrush.png and /dev/null differ diff --git a/examples/textures/rectangle/main.go b/examples/textures/rectangle/main.go index 2365795..02892a9 100644 --- a/examples/textures/rectangle/main.go +++ b/examples/textures/rectangle/main.go @@ -1,9 +1,16 @@ package main import ( + "fmt" + "github.com/gen2brain/raylib-go/raylib" ) +const ( + maxFrameSpeed = 15 + minFrameSpeed = 1 +) + func main() { screenWidth := int32(800) screenHeight := int32(450) @@ -11,47 +18,70 @@ func main() { raylib.InitWindow(screenWidth, screenHeight, "raylib [textures] example - texture loading and drawing") // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) - guybrush := raylib.LoadTexture("guybrush.png") // Texture loading + scarfy := raylib.LoadTexture("scarfy.png") // Texture loading - position := raylib.NewVector2(350.0, 240.0) - frameRec := raylib.NewRectangle(0, 0, guybrush.Width/7, guybrush.Height) + position := raylib.NewVector2(350.0, 280.0) + frameRec := raylib.NewRectangle(0, 0, scarfy.Width/6, scarfy.Height) currentFrame := int32(0) + framesCounter := 0 + framesSpeed := 8 // Number of spritesheet frames shown by second + raylib.SetTargetFPS(60) for !raylib.WindowShouldClose() { - if raylib.IsKeyPressed(raylib.KeyRight) { + framesCounter++ + + if framesCounter >= (60 / framesSpeed) { + framesCounter = 0 currentFrame++ - if currentFrame > 6 { + if currentFrame > 5 { currentFrame = 0 } - frameRec.X = currentFrame * guybrush.Width / 7 + frameRec.X = currentFrame * scarfy.Width / 6 + } + + if raylib.IsKeyPressed(raylib.KeyRight) { + framesSpeed++ + } else if raylib.IsKeyPressed(raylib.KeyLeft) { + framesSpeed-- + } + + if framesSpeed > maxFrameSpeed { + framesSpeed = maxFrameSpeed + } else if framesSpeed < minFrameSpeed { + framesSpeed = minFrameSpeed } raylib.BeginDrawing() raylib.ClearBackground(raylib.RayWhite) - raylib.DrawTexture(guybrush, 35, 40, raylib.White) - raylib.DrawRectangleLines(35, 40, guybrush.Width, guybrush.Height, raylib.Lime) + raylib.DrawTexture(scarfy, 15, 40, raylib.White) + raylib.DrawRectangleLines(15, 40, scarfy.Width, scarfy.Height, raylib.Lime) + raylib.DrawRectangleLines(15+frameRec.X, 40+frameRec.Y, frameRec.Width, frameRec.Height, raylib.Red) - raylib.DrawTextureRec(guybrush, frameRec, position, raylib.White) // Draw part of the texture + raylib.DrawText("FRAME SPEED: ", 165, 210, 10, raylib.DarkGray) + raylib.DrawText(fmt.Sprintf("%02d FPS", framesSpeed), 575, 210, 10, raylib.DarkGray) + raylib.DrawText("PRESS RIGHT/LEFT KEYS to CHANGE SPEED!", 290, 240, 10, raylib.DarkGray) - raylib.DrawRectangleLines(35+frameRec.X, 40+frameRec.Y, frameRec.Width, frameRec.Height, raylib.Red) + for i := 0; i < maxFrameSpeed; i++ { + if i < framesSpeed { + raylib.DrawRectangle(int32(250+21*i), 205, 20, 20, raylib.Red) + } + raylib.DrawRectangleLines(int32(250+21*i), 205, 20, 20, raylib.Maroon) + } - raylib.DrawText("PRESS RIGHT KEY TO", 540, 310, 10, raylib.Gray) - raylib.DrawText("CHANGE DRAWING RECTANGLE", 520, 330, 10, raylib.Gray) + raylib.DrawTextureRec(scarfy, frameRec, position, raylib.White) // Draw part of the texture - raylib.DrawText("Guybrush Ulysses Threepwood,", 100, 300, 10, raylib.Gray) - raylib.DrawText("main character of the Monkey Island series", 80, 320, 10, raylib.Gray) - raylib.DrawText("of computer adventure games by LucasArts.", 80, 340, 10, raylib.Gray) + raylib.DrawText("(c) Scarfy sprite by Eiden Marsal", screenWidth-200, screenHeight-20, 10, raylib.Gray) raylib.EndDrawing() } - raylib.UnloadTexture(guybrush) + raylib.UnloadTexture(scarfy) raylib.CloseWindow() } diff --git a/examples/textures/rectangle/scarfy.png b/examples/textures/rectangle/scarfy.png new file mode 100644 index 0000000..beb5ffa Binary files /dev/null and b/examples/textures/rectangle/scarfy.png differ diff --git a/examples/textures/srcrec_dstrec/guybrush.png b/examples/textures/srcrec_dstrec/guybrush.png deleted file mode 100644 index 32c9dce..0000000 Binary files a/examples/textures/srcrec_dstrec/guybrush.png and /dev/null differ diff --git a/examples/textures/srcrec_dstrec/main.go b/examples/textures/srcrec_dstrec/main.go index 50d3e7b..53696b3 100644 --- a/examples/textures/srcrec_dstrec/main.go +++ b/examples/textures/srcrec_dstrec/main.go @@ -11,10 +11,10 @@ func main() { raylib.InitWindow(screenWidth, screenHeight, "raylib [textures] examples - texture source and destination rectangles") // NOTE: Textures MUST be loaded after Window initialization (OpenGL context is required) - guybrush := raylib.LoadTexture("guybrush.png") // Texture loading + scarfy := raylib.LoadTexture("scarfy.png") // Texture loading - frameWidth := guybrush.Width / 7 - frameHeight := guybrush.Height + frameWidth := scarfy.Width / 7 + frameHeight := scarfy.Height // NOTE: Source rectangle (part of the texture to use for drawing) sourceRec := raylib.NewRectangle(0, 0, int32(frameWidth), int32(frameHeight)) @@ -43,15 +43,17 @@ func main() { // destRec defines the rectangle where our texture part will fit (scaling it to fit) // origin defines the point of the texture used as reference for rotation and scaling // rotation defines the texture rotation (using origin as rotation point) - raylib.DrawTexturePro(guybrush, sourceRec, destRec, origin, rotation, raylib.White) + raylib.DrawTexturePro(scarfy, sourceRec, destRec, origin, rotation, raylib.White) raylib.DrawLine(destRec.X, 0, destRec.X, screenHeight, raylib.Gray) raylib.DrawLine(0, destRec.Y, screenWidth, destRec.Y, raylib.Gray) + raylib.DrawText("(c) Scarfy sprite by Eiden Marsal", screenWidth-200, screenHeight-20, 10, raylib.Gray) + raylib.EndDrawing() } - raylib.UnloadTexture(guybrush) + raylib.UnloadTexture(scarfy) raylib.CloseWindow() } diff --git a/examples/textures/srcrec_dstrec/scarfy.png b/examples/textures/srcrec_dstrec/scarfy.png new file mode 100644 index 0000000..beb5ffa Binary files /dev/null and b/examples/textures/srcrec_dstrec/scarfy.png differ diff --git a/raylib/audio.c b/raylib/audio.c index 659ead0..d63047a 100644 --- a/raylib/audio.c +++ b/raylib/audio.c @@ -1,26 +1,22 @@ /********************************************************************************************** * -* raylib.audio +* raylib.audio - Basic funtionality to work with audio * -* This module provides basic functionality to work with audio: -* Manage audio device (init/close) -* Load and Unload audio files (WAV, OGG, FLAC, XM, MOD) -* Play/Stop/Pause/Resume loaded audio -* Manage mixing channels -* Manage raw audio context -* -* NOTES: -* -* Only up to two channels supported: MONO and STEREO (for additional channels, use AL_EXT_MCFORMATS) -* Only the following sample sizes supported: 8bit PCM, 16bit PCM, 32-bit float PCM (using AL_EXT_FLOAT32) +* FEATURES: +* - Manage audio device (init/close) +* - Load and unload audio files +* - Format wave data (sample rate, size, channels) +* - Play/Stop/Pause/Resume loaded audio +* - Manage mixing channels +* - Manage raw audio context * * CONFIGURATION: * * #define AUDIO_STANDALONE -* If defined, the module can be used as standalone library (independently of raylib). +* Define to use the module as standalone library (independently of raylib). * Required types and functions are defined in the same module. * -* #define SUPPORT_FILEFORMAT_WAV / SUPPORT_LOAD_WAV / ENABLE_LOAD_WAV +* #define SUPPORT_FILEFORMAT_WAV * #define SUPPORT_FILEFORMAT_OGG * #define SUPPORT_FILEFORMAT_XM * #define SUPPORT_FILEFORMAT_MOD @@ -28,7 +24,9 @@ * Selected desired fileformats to be supported for loading. Some of those formats are * supported by default, to remove support, just comment unrequired #define in this module * -* #define SUPPORT_RAW_AUDIO_BUFFERS +* LIMITATIONS: +* Only up to two channels supported: MONO and STEREO (for additional channels, use AL_EXT_MCFORMATS) +* Only the following sample sizes supported: 8bit PCM, 16bit PCM, 32-bit float PCM (using AL_EXT_FLOAT32) * * DEPENDENCIES: * OpenAL Soft - Audio device management (http://kcat.strangesoft.net/openal.html) @@ -38,17 +36,16 @@ * dr_flac - FLAC audio file loading * * CONTRIBUTORS: -* -* Many thanks to Joshua Reisenauer (github: @kd7tck) for the following additions: -* XM audio module support (jar_xm) -* MOD audio module support (jar_mod) -* Mixing channels support -* Raw audio context support +* Joshua Reisenauer (github: @kd7tck): +* - XM audio module support (jar_xm) +* - MOD audio module support (jar_mod) +* - Mixing channels support +* - Raw audio context support * * * LICENSE: zlib/libpng * -* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -67,14 +64,19 @@ * **********************************************************************************************/ -//#define AUDIO_STANDALONE // NOTE: To use the audio module as standalone lib, just uncomment this line +// Default configuration flags (supported features) +//------------------------------------------------- +#define SUPPORT_FILEFORMAT_WAV +#define SUPPORT_FILEFORMAT_OGG +#define SUPPORT_FILEFORMAT_XM +//------------------------------------------------- #if defined(AUDIO_STANDALONE) #include "audio.h" #include // Required for: va_list, va_start(), vfprintf(), va_end() #else #include "raylib.h" - #include "utils.h" // Required for: fopen() Android mapping, TraceLog() + #include "utils.h" // Required for: fopen() Android mapping #endif #ifdef __APPLE__ @@ -93,18 +95,26 @@ #include // Required for: strcmp(), strncmp() #include // Required for: FILE, fopen(), fclose(), fread() -//#define STB_VORBIS_HEADER_ONLY -#include "external/stb_vorbis.h" // OGG loading functions +#if defined(SUPPORT_FILEFORMAT_OGG) + //#define STB_VORBIS_HEADER_ONLY + #include "external/stb_vorbis.h" // OGG loading functions +#endif -#define JAR_XM_IMPLEMENTATION -#include "external/jar_xm.h" // XM loading functions +#if defined(SUPPORT_FILEFORMAT_XM) + #define JAR_XM_IMPLEMENTATION + #include "external/jar_xm.h" // XM loading functions +#endif -#define JAR_MOD_IMPLEMENTATION -#include "external/jar_mod.h" // MOD loading functions +#if defined(SUPPORT_FILEFORMAT_MOD) + #define JAR_MOD_IMPLEMENTATION + #include "external/jar_mod.h" // MOD loading functions +#endif -#define DR_FLAC_IMPLEMENTATION -#define DR_FLAC_NO_WIN32_IO -#include "external/dr_flac.h" // FLAC loading functions +#if defined(SUPPORT_FILEFORMAT_FLAC) + #define DR_FLAC_IMPLEMENTATION + #define DR_FLAC_NO_WIN32_IO + #include "external/dr_flac.h" // FLAC loading functions +#endif #ifdef _MSC_VER #undef bool @@ -139,10 +149,18 @@ typedef enum { MUSIC_AUDIO_OGG = 0, MUSIC_AUDIO_FLAC, MUSIC_MODULE_XM, MUSIC_MOD // Music type (file streaming from memory) typedef struct MusicData { MusicContextType ctxType; // Type of music context (OGG, XM, MOD) +#if defined(SUPPORT_FILEFORMAT_OGG) stb_vorbis *ctxOgg; // OGG audio context +#endif +#if defined(SUPPORT_FILEFORMAT_FLAC) drflac *ctxFlac; // FLAC audio context +#endif +#if defined(SUPPORT_FILEFORMAT_XM) jar_xm_context_t *ctxXm; // XM chiptune context +#endif +#if defined(SUPPORT_FILEFORMAT_MOD) jar_mod_context_t ctxMod; // MOD chiptune context +#endif AudioStream stream; // Audio stream (double buffering) @@ -163,13 +181,19 @@ typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- +#if defined(SUPPORT_FILEFORMAT_WAV) static Wave LoadWAV(const char *fileName); // Load WAV file +#endif +#if defined(SUPPORT_FILEFORMAT_OGG) static Wave LoadOGG(const char *fileName); // Load OGG file +#endif +#if defined(SUPPORT_FILEFORMAT_FLAC) static Wave LoadFLAC(const char *fileName); // Load FLAC file +#endif #if defined(AUDIO_STANDALONE) -const char *GetExtension(const char *fileName); // Get the extension for a filename -void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message (INFO, ERROR, WARNING) +bool IsFileExtension(const char *fileName, const char *ext); // Check file extension +void TraceLog(int msgType, const char *text, ...); // Outputs trace log message (INFO, ERROR, WARNING) #endif //---------------------------------------------------------------------------------- @@ -259,10 +283,15 @@ Wave LoadWave(const char *fileName) { Wave wave = { 0 }; - if (strcmp(GetExtension(fileName), "wav") == 0) wave = LoadWAV(fileName); - else if (strcmp(GetExtension(fileName), "ogg") == 0) wave = LoadOGG(fileName); - else if (strcmp(GetExtension(fileName), "flac") == 0) wave = LoadFLAC(fileName); - else if (strcmp(GetExtension(fileName),"rres") == 0) + if (IsFileExtension(fileName, ".wav")) wave = LoadWAV(fileName); +#if defined(SUPPORT_FILEFORMAT_OGG) + else if (IsFileExtension(fileName, ".ogg")) wave = LoadOGG(fileName); +#endif +#if defined(SUPPORT_FILEFORMAT_FLAC) + else if (IsFileExtension(fileName, ".flac")) wave = LoadFLAC(fileName); +#endif +#if !defined(AUDIO_STANDALONE) + else if (IsFileExtension(fileName, ".rres")) { RRES rres = LoadResource(fileName, 0); @@ -273,7 +302,8 @@ Wave LoadWave(const char *fileName) UnloadResource(rres); } - else TraceLog(WARNING, "[%s] File extension not recognized, it can't be loaded", fileName); +#endif + else TraceLog(WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName); return wave; } @@ -640,7 +670,7 @@ Music LoadMusicStream(const char *fileName) { Music music = (MusicData *)malloc(sizeof(MusicData)); - if (strcmp(GetExtension(fileName), "ogg") == 0) + if (IsFileExtension(fileName, ".ogg")) { // Open ogg audio stream music->ctxOgg = stb_vorbis_open_filename(fileName, NULL, NULL); @@ -663,7 +693,8 @@ Music LoadMusicStream(const char *fileName) TraceLog(DEBUG, "[%s] OGG memory required: %i", fileName, info.temp_memory_required); } } - else if (strcmp(GetExtension(fileName), "flac") == 0) +#if defined(SUPPORT_FILEFORMAT_FLAC) + else if (IsFileExtension(fileName, ".flac")) { music->ctxFlac = drflac_open_file(fileName); @@ -682,7 +713,9 @@ Music LoadMusicStream(const char *fileName) TraceLog(DEBUG, "[%s] FLAC channels: %i", fileName, music->ctxFlac->channels); } } - else if (strcmp(GetExtension(fileName), "xm") == 0) +#endif +#if defined(SUPPORT_FILEFORMAT_XM) + else if (IsFileExtension(fileName, ".xm")) { int result = jar_xm_create_context_from_file(&music->ctxXm, 48000, fileName); @@ -702,7 +735,9 @@ Music LoadMusicStream(const char *fileName) } else TraceLog(WARNING, "[%s] XM file could not be opened", fileName); } - else if (strcmp(GetExtension(fileName), "mod") == 0) +#endif +#if defined(SUPPORT_FILEFORMAT_MOD) + else if (IsFileExtension(fileName, ".mod")) { jar_mod_init(&music->ctxMod); @@ -719,7 +754,8 @@ Music LoadMusicStream(const char *fileName) } else TraceLog(WARNING, "[%s] MOD file could not be opened", fileName); } - else TraceLog(WARNING, "[%s] Music extension not recognized, it can't be loaded", fileName); +#endif + else TraceLog(WARNING, "[%s] Audio fileformat not supported, it can't be loaded", fileName); return music; } @@ -730,9 +766,15 @@ void UnloadMusicStream(Music music) CloseAudioStream(music->stream); if (music->ctxType == MUSIC_AUDIO_OGG) stb_vorbis_close(music->ctxOgg); +#if defined(SUPPORT_FILEFORMAT_FLAC) else if (music->ctxType == MUSIC_AUDIO_FLAC) drflac_free(music->ctxFlac); +#endif +#if defined(SUPPORT_FILEFORMAT_XM) else if (music->ctxType == MUSIC_MODULE_XM) jar_xm_free_context(music->ctxXm); +#endif +#if defined(SUPPORT_FILEFORMAT_MOD) else if (music->ctxType == MUSIC_MODULE_MOD) jar_mod_unload(&music->ctxMod); +#endif free(music); } @@ -777,8 +819,15 @@ void StopMusicStream(Music music) switch (music->ctxType) { case MUSIC_AUDIO_OGG: stb_vorbis_seek_start(music->ctxOgg); break; +#if defined(SUPPORT_FILEFORMAT_FLAC) + case MUSIC_MODULE_FLAC: /* TODO: Restart FLAC context */ break; +#endif +#if defined(SUPPORT_FILEFORMAT_XM) case MUSIC_MODULE_XM: /* TODO: Restart XM context */ break; +#endif +#if defined(SUPPORT_FILEFORMAT_MOD) case MUSIC_MODULE_MOD: jar_mod_seek_start(&music->ctxMod); break; +#endif default: break; } @@ -820,14 +869,20 @@ void UpdateMusicStream(Music music) int numSamplesOgg = stb_vorbis_get_samples_short_interleaved(music->ctxOgg, music->stream.channels, (short *)pcm, samplesCount*music->stream.channels); } break; + #if defined(SUPPORT_FILEFORMAT_FLAC) case MUSIC_AUDIO_FLAC: { // NOTE: Returns the number of samples to process unsigned int numSamplesFlac = (unsigned int)drflac_read_s16(music->ctxFlac, samplesCount*music->stream.channels, (short *)pcm); } break; + #endif + #if defined(SUPPORT_FILEFORMAT_XM) case MUSIC_MODULE_XM: jar_xm_generate_samples_16bit(music->ctxXm, pcm, samplesCount); break; + #endif + #if defined(SUPPORT_FILEFORMAT_MOD) case MUSIC_MODULE_MOD: jar_mod_fillbuffer(&music->ctxMod, pcm, samplesCount, 0); break; + #endif default: break; } @@ -1066,6 +1121,7 @@ void StopAudioStream(AudioStream stream) // Module specific Functions Definition //---------------------------------------------------------------------------------- +#if defined(SUPPORT_FILEFORMAT_WAV) // Load WAV file into Wave structure static Wave LoadWAV(const char *fileName) { @@ -1182,7 +1238,9 @@ static Wave LoadWAV(const char *fileName) return wave; } +#endif +#if defined(SUPPORT_FILEFORMAT_OGG) // Load OGG file into Wave structure // NOTE: Using stb_vorbis library static Wave LoadOGG(const char *fileName) @@ -1206,7 +1264,7 @@ static Wave LoadOGG(const char *fileName) wave.sampleCount = (int)stb_vorbis_stream_length_in_samples(oggFile); float totalSeconds = stb_vorbis_stream_length_in_seconds(oggFile); - if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio lenght is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); + if (totalSeconds > 10) TraceLog(WARNING, "[%s] Ogg audio length is larger than 10 seconds (%f), that's a big file in memory, consider music streaming", fileName, totalSeconds); wave.data = (short *)malloc(wave.sampleCount*wave.channels*sizeof(short)); @@ -1222,7 +1280,9 @@ static Wave LoadOGG(const char *fileName) return wave; } +#endif +#if defined(SUPPORT_FILEFORMAT_FLAC) // Load FLAC file into Wave structure // NOTE: Using dr_flac library static Wave LoadFLAC(const char *fileName) @@ -1244,15 +1304,22 @@ static Wave LoadFLAC(const char *fileName) return wave; } +#endif // Some required functions for audio standalone module version #if defined(AUDIO_STANDALONE) -// Get the extension for a filename -const char *GetExtension(const char *fileName) +// Check file extension +bool IsFileExtension(const char *fileName, const char *ext) { - const char *dot = strrchr(fileName, '.'); - if (!dot || dot == fileName) return ""; - return (dot + 1); + bool result = false; + const char *fileExt; + + if ((fileExt = strrchr(fileName, '.')) != NULL) + { + if (strcmp(fileExt, ext) == 0) result = true; + } + + return result; } // Outputs a trace log message (INFO, ERROR, WARNING) diff --git a/raylib/audio.h b/raylib/audio.h index 01ed9f7..48ef740 100644 --- a/raylib/audio.h +++ b/raylib/audio.h @@ -1,31 +1,37 @@ /********************************************************************************************** * -* raylib.audio +* raylib.audio - Basic funtionality to work with audio * -* This module provides basic functionality to work with audio: -* Manage audio device (init/close) -* Load and Unload audio files (WAV, OGG, FLAC, XM, MOD) -* Play/Stop/Pause/Resume loaded audio -* Manage mixing channels -* Manage raw audio context +* FEATURES: +* - Manage audio device (init/close) +* - Load and unload audio files +* - Format wave data (sample rate, size, channels) +* - Play/Stop/Pause/Resume loaded audio +* - Manage mixing channels +* - Manage raw audio context +* +* LIMITATIONS: +* Only up to two channels supported: MONO and STEREO (for additional channels, use AL_EXT_MCFORMATS) +* Only the following sample sizes supported: 8bit PCM, 16bit PCM, 32-bit float PCM (using AL_EXT_FLOAT32) * * DEPENDENCIES: * OpenAL Soft - Audio device management (http://kcat.strangesoft.net/openal.html) * stb_vorbis - OGG audio files loading (http://www.nothings.org/stb_vorbis/) -* jar_xm - XM module file loading -* jar_mod - MOD audio file loading -* dr_flac - FLAC audio file loading +* jar_xm - XM module file loading (#define SUPPORT_FILEFORMAT_XM) +* jar_mod - MOD audio file loading (#define SUPPORT_FILEFORMAT_MOD) +* dr_flac - FLAC audio file loading (#define SUPPORT_FILEFORMAT_FLAC) * -* Many thanks to Joshua Reisenauer (github: @kd7tck) for the following additions: -* XM audio module support (jar_xm) -* MOD audio module support (jar_mod) -* Mixing channels support -* Raw audio context support +* CONTRIBUTORS: +* Joshua Reisenauer (github: @kd7tck): +* - XM audio module support (jar_xm) +* - MOD audio module support (jar_mod) +* - Mixing channels support +* - Raw audio context support * * * LICENSE: zlib/libpng * -* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -117,7 +123,7 @@ Wave LoadWave(const char *fileName); // Load wave dat Wave LoadWaveEx(void *data, int sampleCount, int sampleRate, int sampleSize, int channels); // Load wave data from raw array data Sound LoadSound(const char *fileName); // Load sound from file Sound LoadSoundFromWave(Wave wave); // Load sound from wave data -void UpdateSound(Sound sound, const void *data, int samplesCount); // Update sound buffer with new data +void UpdateSound(Sound sound, const void *data, int samplesCount);// Update sound buffer with new data void UnloadWave(Wave wave); // Unload wave data void UnloadSound(Sound sound); // Unload sound void PlaySound(Sound sound); // Play a sound @@ -145,10 +151,11 @@ void SetMusicLoopCount(Music music, float count); // Set music loo float GetMusicTimeLength(Music music); // Get music time length (in seconds) float GetMusicTimePlayed(Music music); // Get current music time played (in seconds) +// Raw audio stream functions AudioStream InitAudioStream(unsigned int sampleRate, - unsigned int sampleSize, - unsigned int channels); // Init audio stream (to stream raw audio pcm data) -void UpdateAudioStream(AudioStream stream, void *data, int samplesCount); // Update audio stream buffers with data + unsigned int sampleSize, + unsigned int channels); // Init audio stream (to stream raw audio pcm data) +void UpdateAudioStream(AudioStream stream, const void *data, int samplesCount); // Update audio stream buffers with data void CloseAudioStream(AudioStream stream); // Close audio stream and free memory bool IsAudioBufferProcessed(AudioStream stream); // Check if any audio stream buffers requires refill void PlayAudioStream(AudioStream stream); // Play audio stream diff --git a/raylib/camera.h b/raylib/camera.h index 87ba194..e1b00ac 100644 --- a/raylib/camera.h +++ b/raylib/camera.h @@ -1,6 +1,6 @@ /******************************************************************************************* * -* raylib Camera System - Camera Modes Setup and Control Functions +* raylib.camera - Camera system with multiple modes support * * NOTE: Memory footprint of this library is aproximately 52 bytes (global variables) * @@ -22,7 +22,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2015-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. diff --git a/raylib/core.c b/raylib/core.c index 931989e..408b764 100644 --- a/raylib/core.c +++ b/raylib/core.c @@ -2,7 +2,14 @@ * * raylib.core - Basic functions to manage windows, OpenGL context and input on multiple platforms * -* The following platforms are supported: Windows, Linux, Mac (OSX), Android, Raspberry Pi, HTML5, Oculus Rift CV1 +* PLATFORMS SUPPORTED: +* - Windows (win32/Win64) +* - Linux (tested on Ubuntu) +* - Mac (OSX) +* - Android (API Level 9 or greater) +* - Raspberry Pi (Raspbian) +* - HTML5 (Chrome, Firefox) +* - Oculus Rift CV1 * * CONFIGURATION: * @@ -22,13 +29,15 @@ * Windowing and input system configured for HTML5 (run on browser), code converted from C to asm.js * using emscripten compiler. OpenGL ES 2.0 required for direct translation to WebGL equivalent code. * -* #define LOAD_DEFAULT_FONT (defined by default) +* #define SUPPORT_DEFAULT_FONT (default) * Default font is loaded on window initialization to be available for the user to render simple text. * NOTE: If enabled, uses external module functions to load default raylib font (module: text) * -* #define INCLUDE_CAMERA_SYSTEM / SUPPORT_CAMERA_SYSTEM +* #define SUPPORT_CAMERA_SYSTEM +* Camera module is included (camera.h) and multiple predefined cameras are available: free, 1st/3rd person, orbital * -* #define INCLUDE_GESTURES_SYSTEM / SUPPORT_GESTURES_SYSTEM +* #define SUPPORT_GESTURES_SYSTEM +* Gestures module is included (gestures.h) to support gestures detection: tap, hold, swipe, drag * * #define SUPPORT_MOUSE_GESTURES * Mouse gestures are directly mapped like touches and processed by gestures system. @@ -42,7 +51,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -61,19 +70,29 @@ * **********************************************************************************************/ +// Default configuration flags (supported features) +//------------------------------------------------- +#define SUPPORT_DEFAULT_FONT +#define SUPPORT_MOUSE_GESTURES +#define SUPPORT_CAMERA_SYSTEM +#define SUPPORT_GESTURES_SYSTEM +//------------------------------------------------- + #include "raylib.h" #include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 3.3+ or ES2 -#include "utils.h" // Required for: fopen() Android mapping, TraceLog() +#include "utils.h" // Required for: fopen() Android mapping #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 -#define GESTURES_IMPLEMENTATION -#include "gestures.h" // Gestures detection functionality +#if defined(SUPPORT_GESTURES_SYSTEM) + #define GESTURES_IMPLEMENTATION + #include "gestures.h" // Gestures detection functionality +#endif -#if !defined(PLATFORM_ANDROID) +#if defined(SUPPORT_CAMERA_SYSTEM) && !defined(PLATFORM_ANDROID) #define CAMERA_IMPLEMENTATION #include "camera.h" // Camera system functionality #endif @@ -83,10 +102,10 @@ #include // Required for: typedef unsigned long long int uint64_t, used by hi-res timer #include // Required for: time() - Android/RPI hi-res timer (NOTE: Linux only!) #include // Required for: tan() [Used in Begin3dMode() to set perspective] -#include // Required for: strcmp() +#include // Required for: strrchr(), strcmp() //#include // Macros for reporting and retrieving error conditions through error codes -#if defined __linux || defined(PLATFORM_WEB) +#if defined __linux__ || defined(PLATFORM_WEB) #include // Required for: timespec, nanosleep(), select() - POSIX #elif defined __APPLE__ #include // Required for: usleep() @@ -96,7 +115,7 @@ //#define GLFW_INCLUDE_NONE // Disable the standard OpenGL header inclusion on GLFW3 #include // GLFW3 library: Windows, OpenGL context and Input management - #ifdef __linux + #ifdef __linux__ #define GLFW_EXPOSE_NATIVE_X11 // Linux specific definitions for getting #define GLFW_EXPOSE_NATIVE_GLX // native functions like glfwGetX11Window #include // which are required for hiding mouse @@ -140,8 +159,6 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define STORAGE_FILENAME "storage.data" - #if defined(PLATFORM_RPI) // Old device inputs system #define DEFAULT_KEYBOARD_DEV STDIN_FILENO // Standard input @@ -161,7 +178,7 @@ #define MAX_GAMEPAD_BUTTONS 32 // Max bumber of buttons supported (per gamepad) #define MAX_GAMEPAD_AXIS 8 // Max number of axis supported (per gamepad) -#define LOAD_DEFAULT_FONT // Load default font on window initialization (module: text) +#define STORAGE_FILENAME "storage.data" //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -259,7 +276,10 @@ static int lastGamepadButtonPressed = -1; // Register last gamepad button pres static int gamepadAxisCount = 0; // Register number of available gamepad axis static Vector2 mousePosition; // Mouse position on screen + +#if defined(SUPPORT_GESTURES_SYSTEM) static Vector2 touchPosition[MAX_TOUCH_POINTS]; // Touch position on screen +#endif #if defined(PLATFORM_DESKTOP) static char **dropFilesPath; // Store dropped files paths as strings @@ -277,7 +297,7 @@ static bool showLogo = false; // Track if showing logo at init is //---------------------------------------------------------------------------------- // Other Modules Functions Declaration (required by core) //---------------------------------------------------------------------------------- -#if defined(LOAD_DEFAULT_FONT) +#if defined(SUPPORT_DEFAULT_FONT) extern void LoadDefaultFont(void); // [Module: text] Loads default font on InitWindow() extern void UnloadDefaultFont(void); // [Module: text] Unloads default font from GPU memory #endif @@ -296,9 +316,6 @@ static void PollInputEvents(void); // Register user events static void SwapBuffers(void); // Copy back buffer to front buffers static void LogoAnimation(void); // Plays raylib logo appearing animation static void SetupViewport(void); // Set viewport parameters -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) -static void TakeScreenshot(void); // Takes a screenshot and saves it in the same folder as executable -#endif #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) static void ErrorCallback(int error, const char *description); // GLFW3 Error Callback, runs on GLFW3 error @@ -323,7 +340,9 @@ static int32_t AndroidInputCallback(struct android_app *app, AInputEvent *event) #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); +static EM_BOOL EmscriptenKeyboardCallback(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData); +static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData); +static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData); static EM_BOOL EmscriptenGamepadCallback(int eventType, const EmscriptenGamepadEvent *gamepadEvent, void *userData); #endif @@ -359,7 +378,7 @@ void InitWindow(int width, int height, const char *title) // Init graphics device (display device and OpenGL context) InitGraphicsDevice(width, height); -#if defined(LOAD_DEFAULT_FONT) +#if defined(SUPPORT_DEFAULT_FONT) // Load default font // NOTE: External function (defined in module: text) LoadDefaultFont(); @@ -378,16 +397,22 @@ void InitWindow(int width, int height, const char *title) #if defined(PLATFORM_WEB) emscripten_set_fullscreenchange_callback(0, 0, 1, EmscriptenFullscreenChangeCallback); + + // Support keyboard events + emscripten_set_keypress_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback); + + // Support mouse events + emscripten_set_click_callback("#canvas", NULL, 1, EmscriptenMouseCallback); - // NOTE: Some code examples + // Support touch events + emscripten_set_touchstart_callback("#canvas", NULL, 1, EmscriptenTouchCallback); + emscripten_set_touchend_callback("#canvas", NULL, 1, EmscriptenTouchCallback); + emscripten_set_touchmove_callback("#canvas", NULL, 1, EmscriptenTouchCallback); + emscripten_set_touchcancel_callback("#canvas", NULL, 1, EmscriptenTouchCallback); //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); - // Support gamepad (not provided by GLFW3 on emscripten) + // Support gamepad events (not provided by GLFW3 on emscripten) emscripten_set_gamepadconnected_callback(NULL, 1, EmscriptenGamepadCallback); emscripten_set_gamepaddisconnected_callback(NULL, 1, EmscriptenGamepadCallback); #endif @@ -471,7 +496,7 @@ void InitWindow(int width, int height, void *state) // Close Window and Terminate Context void CloseWindow(void) { -#if defined(LOAD_DEFAULT_FONT) +#if defined(SUPPORT_DEFAULT_FONT) UnloadDefaultFont(); #endif @@ -621,7 +646,7 @@ int GetScreenHeight(void) void ShowCursor() { #if defined(PLATFORM_DESKTOP) - #ifdef __linux + #ifdef __linux__ XUndefineCursor(glfwGetX11Display(), glfwGetX11Window(window)); #else glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); @@ -634,7 +659,7 @@ void ShowCursor() void HideCursor() { #if defined(PLATFORM_DESKTOP) - #ifdef __linux + #ifdef __linux__ XColor col; const char nil[] = {0}; @@ -958,6 +983,12 @@ Color Fade(Color color, float alpha) return (Color){color.r, color.g, color.b, (unsigned char)colorAlpha}; } +// Activates raylib logo at startup +void ShowLogo(void) +{ + showLogo = true; +} + // Enable some window/system configurations void SetConfigFlags(char flags) { @@ -967,10 +998,40 @@ void SetConfigFlags(char flags) if (configFlags & FLAG_FULLSCREEN_MODE) fullscreen = true; } -// Activates raylib logo at startup -void ShowLogo(void) +// Takes a screenshot and saves it in the same folder as executable +void TakeScreenshot(void) { - showLogo = true; +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) + static int shotNum = 0; // Screenshot number, increments every screenshot take during program execution + char buffer[20]; // Buffer to store file name + + unsigned char *imgData = rlglReadScreenPixels(renderWidth, renderHeight); + + sprintf(buffer, "screenshot%03i.png", shotNum); + + // Save image as PNG + SavePNG(buffer, imgData, renderWidth, renderHeight, 4); + + free(imgData); + + shotNum++; + + TraceLog(INFO, "[%s] Screenshot taken #03i", buffer, shotNum); +#endif +} + +// Check file extension +bool IsFileExtension(const char *fileName, const char *ext) +{ + bool result = false; + const char *fileExt; + + if ((fileExt = strrchr(fileName, '.')) != NULL) + { + if (strcmp(fileExt, ext) == 0) result = true; + } + + return result; } #if defined(PLATFORM_DESKTOP) @@ -2004,6 +2065,9 @@ static double GetTime(void) } // Wait for some milliseconds (stop program execution) +// NOTE: Sleep() granularity could be around 10 ms, it means, Sleep() could +// take longer than expected... for that reason we use the busy wait loop +// http://stackoverflow.com/questions/43057578/c-programming-win32-games-sleep-taking-longer-than-expected static void Wait(float ms) { //#define SUPPORT_BUSY_WAIT_LOOP @@ -2015,8 +2079,8 @@ static void Wait(float ms) while ((nextTime - prevTime) < ms/1000.0f) nextTime = GetTime(); #else #if defined _WIN32 - Sleep(ms); - #elif defined __linux || defined(PLATFORM_WEB) + Sleep((unsigned int)ms); + #elif defined __linux__ || defined(PLATFORM_WEB) struct timespec req = { 0 }; time_t sec = (int)(ms/1000.0f); ms -= (sec*1000); @@ -2064,9 +2128,11 @@ static bool GetMouseButtonStatus(int button) // Poll (store) all input events static void PollInputEvents(void) { +#if defined(SUPPORT_GESTURES_SYSTEM) // 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 // Reset last key pressed registered lastKeyPressed = -1; @@ -2237,28 +2303,6 @@ static void SwapBuffers(void) #endif } -#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) -// Takes a screenshot and saves it in the same folder as executable -static void TakeScreenshot(void) -{ - static int shotNum = 0; // Screenshot number, increments every screenshot take during program execution - char buffer[20]; // Buffer to store file name - - unsigned char *imgData = rlglReadScreenPixels(renderWidth, renderHeight); - - sprintf(buffer, "screenshot%03i.png", shotNum); - - // Save image as PNG - SavePNG(buffer, imgData, renderWidth, renderHeight, 4); - - free(imgData); - - shotNum++; - - TraceLog(INFO, "[%s] Screenshot taken!", buffer); -} -#endif - #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_WEB) // GLFW3 Error Callback, runs on GLFW3 error static void ErrorCallback(int error, const char *description) @@ -2296,8 +2340,7 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int { currentMouseState[button] = action; -#define ENABLE_MOUSE_GESTURES -#if defined(ENABLE_MOUSE_GESTURES) +#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES) // Process mouse events as touches to be able to use mouse-gestures GestureEvent gestureEvent; @@ -2328,8 +2371,7 @@ static void MouseButtonCallback(GLFWwindow *window, int button, int action, int // 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) +#if defined(SUPPORT_GESTURES_SYSTEM) && defined(SUPPORT_MOUSE_GESTURES) // Process mouse events as touches to be able to use mouse-gestures GestureEvent gestureEvent; @@ -2459,7 +2501,7 @@ static void AndroidCommandCallback(struct android_app *app, int32_t cmd) // Init graphics device (display device and OpenGL context) InitGraphicsDevice(screenWidth, screenHeight); - #if defined(LOAD_DEFAULT_FONT) + #if defined(SUPPORT_DEFAULT_FONT) // Load default font // NOTE: External function (defined in module: text) LoadDefaultFont(); @@ -2663,8 +2705,39 @@ static EM_BOOL EmscriptenFullscreenChangeCallback(int eventType, const Emscripte return 0; } +// Register keyboard input events +static EM_BOOL EmscriptenKeyboardCallback(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) +{ + if ((eventType == EMSCRIPTEN_EVENT_KEYPRESS) && (strcmp(keyEvent->code, "Escape") == 0)) + { + emscripten_exit_pointerlock(); + } + + return 0; +} + +// Register mouse input events +static EM_BOOL EmscriptenMouseCallback(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData) +{ + if (eventType == EMSCRIPTEN_EVENT_CLICK) + { + EmscriptenPointerlockChangeEvent plce; + emscripten_get_pointerlock_status(&plce); + + if (!plce.isActive) emscripten_request_pointerlock(0, 1); + else + { + emscripten_exit_pointerlock(); + emscripten_get_pointerlock_status(&plce); + //if (plce.isActive) TraceLog(WARNING, "Pointer lock exit did not work!"); + } + } + + return 0; +} + // Register touch input events -static EM_BOOL EmscriptenInputCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData) +static EM_BOOL EmscriptenTouchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData) { /* for (int i = 0; i < touchEvent->numTouches; i++) diff --git a/raylib/core.go b/raylib/core.go index dd301ec..44f0420 100644 --- a/raylib/core.go +++ b/raylib/core.go @@ -665,15 +665,20 @@ func Fade(color Color, alpha float32) Color { return v } +// ShowLogo - Activates raylib logo at startup (can be done with flags) +func ShowLogo() { + C.ShowLogo() +} + // SetConfigFlags - Setup some window configuration flags func SetConfigFlags(flags byte) { cflags := (C.char)(flags) C.SetConfigFlags(cflags) } -// ShowLogo - Activates raylib logo at startup (can be done with flags) -func ShowLogo() { - C.ShowLogo() +// TakeScreenshot - Takes a screenshot and saves it in the same folder as executable +func TakeScreenshot() { + C.TakeScreenshot() } // StorageSaveValue - Storage save integer value (to defined position) diff --git a/raylib/external/stb_image.h b/raylib/external/stb_image.h index 4d8d013..ae2ada6 100644 --- a/raylib/external/stb_image.h +++ b/raylib/external/stb_image.h @@ -1,4 +1,4 @@ -/* stb_image - v2.14 - public domain image loader - http://nothings.org/stb_image.h +/* stb_image - v2.15 - public domain image loader - http://nothings.org/stb_image.h no warranty implied; use at your own risk Do this: @@ -21,7 +21,7 @@ avoid problematic images and only need the trivial interface JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) - PNG 1/2/4/8-bit-per-channel (16 bpc not supported) + PNG 1/2/4/8/16-bit-per-channel TGA (not sure what subset, if a subset) BMP non-1bpp, non-RLE @@ -42,115 +42,19 @@ Full documentation under "DOCUMENTATION" below. - Revision 2.00 release notes: +LICENSE - - Progressive JPEG is now supported. + See end of file for license information. - - PPM and PGM binary formats are now supported, thanks to Ken Miller. +RECENT REVISION HISTORY: - - x86 platforms now make use of SSE2 SIMD instructions for - JPEG decoding, and ARM platforms can use NEON SIMD if requested. - This work was done by Fabian "ryg" Giesen. SSE2 is used by - default, but NEON must be enabled explicitly; see docs. - - With other JPEG optimizations included in this version, we see - 2x speedup on a JPEG on an x86 machine, and a 1.5x speedup - on a JPEG on an ARM machine, relative to previous versions of this - library. The same results will not obtain for all JPGs and for all - x86/ARM machines. (Note that progressive JPEGs are significantly - slower to decode than regular JPEGs.) This doesn't mean that this - is the fastest JPEG decoder in the land; rather, it brings it - closer to parity with standard libraries. If you want the fastest - decode, look elsewhere. (See "Philosophy" section of docs below.) - - See final bullet items below for more info on SIMD. - - - Added STBI_MALLOC, STBI_REALLOC, and STBI_FREE macros for replacing - the memory allocator. Unlike other STBI libraries, these macros don't - support a context parameter, so if you need to pass a context in to - the allocator, you'll have to store it in a global or a thread-local - variable. - - - Split existing STBI_NO_HDR flag into two flags, STBI_NO_HDR and - STBI_NO_LINEAR. - STBI_NO_HDR: suppress implementation of .hdr reader format - STBI_NO_LINEAR: suppress high-dynamic-range light-linear float API - - - You can suppress implementation of any of the decoders to reduce - your code footprint by #defining one or more of the following - symbols before creating the implementation. - - STBI_NO_JPEG - STBI_NO_PNG - STBI_NO_BMP - STBI_NO_PSD - STBI_NO_TGA - STBI_NO_GIF - STBI_NO_HDR - STBI_NO_PIC - STBI_NO_PNM (.ppm and .pgm) - - - You can request *only* certain decoders and suppress all other ones - (this will be more forward-compatible, as addition of new decoders - doesn't require you to disable them explicitly): - - STBI_ONLY_JPEG - STBI_ONLY_PNG - STBI_ONLY_BMP - STBI_ONLY_PSD - STBI_ONLY_TGA - STBI_ONLY_GIF - STBI_ONLY_HDR - STBI_ONLY_PIC - STBI_ONLY_PNM (.ppm and .pgm) - - Note that you can define multiples of these, and you will get all - of them ("only x" and "only y" is interpreted to mean "only x&y"). - - - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still - want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB - - - Compilation of all SIMD code can be suppressed with - #define STBI_NO_SIMD - It should not be necessary to disable SIMD unless you have issues - compiling (e.g. using an x86 compiler which doesn't support SSE - intrinsics or that doesn't support the method used to detect - SSE2 support at run-time), and even those can be reported as - bugs so I can refine the built-in compile-time checking to be - smarter. - - - The old STBI_SIMD system which allowed installing a user-defined - IDCT etc. has been removed. If you need this, don't upgrade. My - assumption is that almost nobody was doing this, and those who - were will find the built-in SIMD more satisfactory anyway. - - - RGB values computed for JPEG images are slightly different from - previous versions of stb_image. (This is due to using less - integer precision in SIMD.) The C code has been adjusted so - that the same RGB values will be computed regardless of whether - SIMD support is available, so your app should always produce - consistent results. But these results are slightly different from - previous versions. (Specifically, about 3% of available YCbCr values - will compute different RGB results from pre-1.49 versions by +-1; - most of the deviating values are one smaller in the G channel.) - - - If you must produce consistent results with previous versions of - stb_image, #define STBI_JPEG_OLD and you will get the same results - you used to; however, you will not get the SIMD speedups for - the YCbCr-to-RGB conversion step (although you should still see - significant JPEG speedup from the other changes). - - Please note that STBI_JPEG_OLD is a temporary feature; it will be - removed in future versions of the library. It is only intended for - near-term back-compatibility use. - - - Latest revision history: + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 RGB-format JPEG; remove white matting in PSD; - allocate large structures on the stack; + allocate large structures on the stack; correct channel count for PNG & BMP 2.10 (2016-01-22) avoid warning introduced in 2.09 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED @@ -174,32 +78,26 @@ Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) github:urraka (animated gif) Junggon Kim (PNM comments) Daniel Gibson (16-bit TGA) - socks-the-fox (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) Optimizations & bugfixes Fabian "ryg" Giesen Arseny Kapoulkine Bug & warning fixes Marc LeBlanc David Woo Guillaume George Martins Mozeiko - Christpher Lloyd Martin Golini Jerry Jansson Joseph Thomson - Dave Moore Roy Eltham Hayaki Saito Phil Jordan - Won Chun Luke Graham Johan Duparc Nathan Reed - the Horde3D community Thomas Ruf Ronny Chevalier Nick Verigakis - Janez Zemva John Bartholomew Michal Cichon github:svdijk - Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson - Laurent Gomila Cort Stratton Sergio Gonzalez github:romigrou - Aruelien Pocheville Thibault Reuille Cass Everitt Matthew Gregan - Ryamond Barbiero Paul Du Bois Engin Manap github:snagar - Michaelangel007@github Oriol Ferrer Mesia Dale Weiler github:Zelex - Philipp Wiesemann Josh Tobin github:rlyeh github:grim210@github - Blazej Dariusz Roszkowski github:sammyhw - - -LICENSE - -This software is dual-licensed to the public domain and under the following -license: you are granted a perpetual, irrevocable license to copy, modify, -publish, and distribute this file as you see fit. + Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan + Dave Moore Roy Eltham Hayaki Saito Nathan Reed + Won Chun Luke Graham Johan Duparc Nick Verigakis + the Horde3D community Thomas Ruf Ronny Chevalier Baldur Karlsson + Janez Zemva John Bartholomew Michal Cichon github:rlyeh + Jonathan Blow Ken Hamada Tero Hanninen github:romigrou + Laurent Gomila Cort Stratton Sergio Gonzalez github:svdijk + Aruelien Pocheville Thibault Reuille Cass Everitt github:snagar + Ryamond Barbiero Paul Du Bois Engin Manap github:Zelex + Michaelangel007@github Philipp Wiesemann Dale Weiler github:grim210 + Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:sammyhw + Blazej Dariusz Roszkowski Gregory Mullen github:phprus */ @@ -274,13 +172,13 @@ publish, and distribute this file as you see fit. // and for best performance I may provide less-easy-to-use APIs that give higher // performance, in addition to the easy to use ones. Nevertheless, it's important // to keep in mind that from the standpoint of you, a client of this library, -// all you care about is #1 and #3, and stb libraries do not emphasize #3 above all. +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. // // Some secondary priorities arise directly from the first two, some of which // make more explicit reasons why performance can't be emphasized. // // - Portable ("ease of use") -// - Small footprint ("easy to maintain") +// - Small source code footprint ("easy to maintain") // - No dependencies ("ease of use") // // =========================================================================== @@ -312,13 +210,6 @@ publish, and distribute this file as you see fit. // (at least this is true for iOS and Android). Therefore, the NEON support is // toggled by a build flag: define STBI_NEON to get NEON loops. // -// The output of the JPEG decoder is slightly different from versions where -// SIMD support was introduced (that is, for versions before 1.49). The -// difference is only +-1 in the 8-bit RGB channels, and only on a small -// fraction of pixels. You can force the pre-1.49 behavior by defining -// STBI_JPEG_OLD, but this will disable some of the SIMD decoding path -// and hence cost some performance. -// // If for some reason you do not want to use any of SIMD code, or if // you have issues compiling it, you can disable it entirely by // defining STBI_NO_SIMD. @@ -374,20 +265,47 @@ publish, and distribute this file as you see fit. // says there's premultiplied data (currently only happens in iPhone images, // and only if iPhone convert-to-rgb processing is on). // +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// #ifndef STBI_NO_STDIO #include #endif // STBI_NO_STDIO -#define STBI_NO_HDR // RaySan: not required by raylib -//#define STBI_NO_SIMD // RaySan: issues when compiling with GCC 4.7.2 - -// NOTE: Added to work with raylib on Android -#if defined(PLATFORM_ANDROID) - #include "utils.h" // RaySan: Android fopen function map -#endif - #define STBI_VERSION 1 enum @@ -666,12 +584,14 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; #define STBI__X86_TARGET #endif -#if defined(__GNUC__) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) -// NOTE: not clear do we actually need this for the 64-bit path? +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) // gcc doesn't support sse2 intrinsics unless you compile with -msse2, -// (but compiling with -msse2 allows the compiler to use SSE2 everywhere; -// this is just broken and gcc are jerks for not fixing it properly -// http://www.virtualdub.org/blog/pivot/entry.php?id=363 ) +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. #define STBI_NO_SIMD #endif @@ -729,14 +649,10 @@ static int stbi__sse2_available() static int stbi__sse2_available() { -#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 // GCC 4.8 or later - // GCC 4.8+ has a nice way to do this - return __builtin_cpu_supports("sse2"); -#else - // portable way to do this, preferably without using GCC inline ASM? - // just bail for now. - return 0; -#endif + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; } #endif #endif @@ -1738,7 +1654,7 @@ typedef struct stbi__context *s; stbi__huffman huff_dc[4]; stbi__huffman huff_ac[4]; - stbi_uc dequant[4][64]; + stbi__uint16 dequant[4][64]; stbi__int16 fast_ac[4][1 << FAST_BITS]; // sizes for components, interleaved MCUs @@ -1774,6 +1690,8 @@ typedef struct int succ_high; int succ_low; int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag int rgb; int scan_n, order[4]; @@ -1844,7 +1762,7 @@ static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) // magnitude code followed by receive_extend code int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); int m = 1 << (magbits - 1); - if (k < m) k += (-1 << magbits) + 1; + if (k < m) k += (~0U << magbits) + 1; // if the result is small enough, we can fit it in fast_ac table if (k >= -128 && k <= 127) fast_ac[i] = (stbi__int16) ((k << 8) + (run << 4) + (len + magbits)); @@ -1859,6 +1777,7 @@ static void stbi__grow_buffer_unsafe(stbi__jpeg *j) int b = j->nomore ? 0 : stbi__get8(j->s); if (b == 0xff) { int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes if (c != 0) { j->marker = (unsigned char) c; j->nomore = 1; @@ -1983,7 +1902,7 @@ static stbi_uc stbi__jpeg_dezigzag[64+15] = }; // decode one 64-entry block-- -static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi_uc *dequant) +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) { int diff,dc,k; int t; @@ -2692,7 +2611,7 @@ static stbi_uc stbi__get_marker(stbi__jpeg *j) x = stbi__get8(j->s); if (x != 0xff) return STBI__MARKER_none; while (x == 0xff) - x = stbi__get8(j->s); + x = stbi__get8(j->s); // consume repeated 0xff fill bytes return x; } @@ -2707,7 +2626,7 @@ static void stbi__jpeg_reset(stbi__jpeg *j) j->code_bits = 0; j->code_buffer = 0; j->nomore = 0; - j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; j->marker = STBI__MARKER_none; j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; j->eob_run = 0; @@ -2839,7 +2758,7 @@ static int stbi__parse_entropy_coded_data(stbi__jpeg *z) } } -static void stbi__jpeg_dequantize(short *data, stbi_uc *dequant) +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) { int i; for (i=0; i < 64; ++i) @@ -2881,13 +2800,14 @@ static int stbi__process_marker(stbi__jpeg *z, int m) L = stbi__get16be(z->s)-2; while (L > 0) { int q = stbi__get8(z->s); - int p = q >> 4; + int p = q >> 4, sixteen = (p != 0); int t = q & 15,i; - if (p != 0) return stbi__err("bad DQT type","Corrupt JPEG"); + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + for (i=0; i < 64; ++i) - z->dequant[t][stbi__jpeg_dezigzag[i]] = stbi__get8(z->s); - L -= 65; + z->dequant[t][stbi__jpeg_dezigzag[i]] = sixteen ? stbi__get16be(z->s) : stbi__get8(z->s); + L -= (sixteen ? 129 : 65); } return L==0; @@ -2920,12 +2840,50 @@ static int stbi__process_marker(stbi__jpeg *z, int m) } return L==0; } + // check for comment block or APP blocks if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { - stbi__skip(z->s, stbi__get16be(z->s)-2); + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); return 1; } - return 0; + + return stbi__err("unknown marker","Corrupt JPEG"); } // after we see SOS @@ -2999,7 +2957,7 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires c = stbi__get8(s); - if (c != 3 && c != 1) return stbi__err("bad component count","Corrupt JPEG"); // JFIF requires + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); s->img_n = c; for (i=0; i < c; ++i) { z->img_comp[i].data = NULL; @@ -3012,13 +2970,8 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) for (i=0; i < s->img_n; ++i) { static unsigned char rgb[3] = { 'R', 'G', 'B' }; z->img_comp[i].id = stbi__get8(s); - if (z->img_comp[i].id != i+1) // JFIF requires - if (z->img_comp[i].id != i) { // some version of jpegtran outputs non-JFIF-compliant files! - // somethings output this (see http://fileformats.archiveteam.org/wiki/JPEG#Color_format) - if (z->img_comp[i].id != rgb[i]) - return stbi__err("bad component ID","Corrupt JPEG"); - ++z->rgb; - } + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; q = stbi__get8(s); z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); @@ -3090,6 +3043,8 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan) static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) { int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 z->marker = STBI__MARKER_none; // initialize cached marker to empty m = stbi__get_marker(z); if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); @@ -3131,12 +3086,15 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j) if (x == 255) { j->marker = stbi__get8(j->s); break; - } else if (x != 0) { - return stbi__err("junk before marker", "Corrupt JPEG"); } } // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 } + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) stbi__err("bad DNL height", "Corrupt JPEG"); } else { if (!stbi__process_marker(j, m)) return 0; } @@ -3355,38 +3313,9 @@ static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_ return out; } -#ifdef STBI_JPEG_OLD -// this is the same YCbCr-to-RGB calculation that stb_image has used -// historically before the algorithm changes in 1.49 -#define float2fixed(x) ((int) ((x) * 65536 + 0.5)) -static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) -{ - int i; - for (i=0; i < count; ++i) { - int y_fixed = (y[i] << 16) + 32768; // rounding - int r,g,b; - int cr = pcr[i] - 128; - int cb = pcb[i] - 128; - r = y_fixed + cr*float2fixed(1.40200f); - g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f); - b = y_fixed + cb*float2fixed(1.77200f); - r >>= 16; - g >>= 16; - b >>= 16; - if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } - if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } - if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } - out[0] = (stbi_uc)r; - out[1] = (stbi_uc)g; - out[2] = (stbi_uc)b; - out[3] = 255; - out += step; - } -} -#else // this is a reduced-precision calculation of YCbCr-to-RGB introduced // to make sure the code produces the same results in both SIMD and scalar -#define float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) { int i; @@ -3395,9 +3324,9 @@ static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc int r,g,b; int cr = pcr[i] - 128; int cb = pcb[i] - 128; - r = y_fixed + cr* float2fixed(1.40200f); - g = y_fixed + (cr*-float2fixed(0.71414f)) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); - b = y_fixed + cb* float2fixed(1.77200f); + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); r >>= 20; g >>= 20; b >>= 20; @@ -3411,7 +3340,6 @@ static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc out += step; } } -#endif #if defined(STBI_SSE2) || defined(STBI_NEON) static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) @@ -3530,9 +3458,9 @@ static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc cons int r,g,b; int cr = pcr[i] - 128; int cb = pcb[i] - 128; - r = y_fixed + cr* float2fixed(1.40200f); - g = y_fixed + cr*-float2fixed(0.71414f) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); - b = y_fixed + cb* float2fixed(1.77200f); + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); r >>= 20; g >>= 20; b >>= 20; @@ -3558,18 +3486,14 @@ static void stbi__setup_jpeg(stbi__jpeg *j) #ifdef STBI_SSE2 if (stbi__sse2_available()) { j->idct_block_kernel = stbi__idct_simd; - #ifndef STBI_JPEG_OLD j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; - #endif j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; } #endif #ifdef STBI_NEON j->idct_block_kernel = stbi__idct_simd; - #ifndef STBI_JPEG_OLD j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; - #endif j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; #endif } @@ -3590,9 +3514,16 @@ typedef struct int ypos; // which pre-expansion row we're on } stbi__resample; +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) { - int n, decode_n; + int n, decode_n, is_rgb; z->s->img_n = 0; // make stbi__cleanup_jpeg safe // validate req_comp @@ -3602,9 +3533,11 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } // determine actual number of components to generate - n = req_comp ? req_comp : z->s->img_n; + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; - if (z->s->img_n == 3 && n < 3) + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) decode_n = 1; else decode_n = z->s->img_n; @@ -3664,7 +3597,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp if (n >= 3) { stbi_uc *y = coutput[0]; if (z->s->img_n == 3) { - if (z->rgb == 3) { + if (is_rgb) { for (i=0; i < z->s->img_x; ++i) { out[0] = y[i]; out[1] = coutput[1][i]; @@ -3675,6 +3608,28 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp } else { z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc k = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], k); + out[1] = stbi__blinn_8x8(coutput[1][i], k); + out[2] = stbi__blinn_8x8(coutput[2][i], k); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc k = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], k); + out[1] = stbi__blinn_8x8(255 - out[1], k); + out[2] = stbi__blinn_8x8(255 - out[2], k); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } } else for (i=0; i < z->s->img_x; ++i) { out[0] = out[1] = out[2] = y[i]; @@ -3682,17 +3637,45 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp out += n; } } else { - stbi_uc *y = coutput[0]; - if (n == 1) - for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; - else - for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc k = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], k); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], k); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], k); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + } } } stbi__cleanup_jpeg(z); *out_x = z->s->img_x; *out_y = z->s->img_y; - if (comp) *comp = z->s->img_n; // report original components, not output + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output return output; } } @@ -3701,6 +3684,7 @@ static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int re { unsigned char* result; stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); j->s = s; stbi__setup_jpeg(j); result = load_jpeg_image(j, x,y,comp,req_comp); @@ -3711,11 +3695,12 @@ static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int re static int stbi__jpeg_test(stbi__context *s) { int r; - stbi__jpeg j; - j.s = s; - stbi__setup_jpeg(&j); - r = stbi__decode_jpeg_header(&j, STBI__SCAN_type); + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); stbi__rewind(s); + STBI_FREE(j); return r; } @@ -3727,7 +3712,7 @@ static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) } if (x) *x = j->s->img_x; if (y) *y = j->s->img_y; - if (comp) *comp = j->s->img_n; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; return 1; } @@ -3784,7 +3769,7 @@ stbi_inline static int stbi__bit_reverse(int v, int bits) return stbi__bitreverse16(v) >> (16-bits); } -static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) { int i,k=0; int code, next_code[16], sizes[17]; @@ -4074,9 +4059,24 @@ static int stbi__parse_zlib_header(stbi__zbuf *a) return 1; } -// @TODO: should statically initialize these for optimal thread safety -static stbi_uc stbi__zdefault_length[288], stbi__zdefault_distance[32]; -static void stbi__init_zdefaults(void) +static const stbi_uc stbi__zdefault_length[288] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: { int i; // use <= to match clearly with spec for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; @@ -4086,6 +4086,7 @@ static void stbi__init_zdefaults(void) for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; } +*/ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) { @@ -4104,7 +4105,6 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) } else { if (type == 1) { // use fixed code lengths - if (!stbi__zdefault_distance[31]) stbi__init_zdefaults(); if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; } else { @@ -4305,7 +4305,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r for (j=0; j < y; ++j) { stbi_uc *cur = a->out + stride*j; - stbi_uc *prior = cur - stride; + stbi_uc *prior; int filter = *raw++; if (filter > 4) @@ -4317,6 +4317,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r filter_bytes = 1; width = img_width_bytes; } + prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above // if first row, use special filter that doesn't sample previous row if (j == 0) filter = first_row_filter[filter]; @@ -4709,7 +4710,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); - if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); @@ -4992,7 +4993,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) info->offset = stbi__get32le(s); info->hsz = hsz = stbi__get32le(s); info->mr = info->mg = info->mb = info->ma = 0; - + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); if (hsz == 12) { s->img_x = stbi__get16le(s); @@ -5077,7 +5078,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req stbi__bmp_data info; STBI_NOTUSED(ri); - info.all_a = 255; + info.all_a = 255; if (stbi__bmp_parse_header(s, &info) == NULL) return NULL; // error code already set @@ -5196,7 +5197,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req stbi__skip(s, pad); } } - + // if alpha channel is all 0s, replace with all 255s if (target == 4 && all_a == 0) for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) @@ -5979,9 +5980,11 @@ static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *c static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) { stbi_uc *result; - int i, x,y; + int i, x,y, internal_comp; STBI_NOTUSED(ri); + if (!comp) comp = &internal_comp; + for (i=0; i<92; ++i) stbi__get8(s); @@ -6600,6 +6603,11 @@ static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) char buffer[STBI__HDR_BUFLEN]; char *token; int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; if (stbi__hdr_test(s) == 0) { stbi__rewind( s ); @@ -6641,14 +6649,14 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) void *p; stbi__bmp_data info; - info.all_a = 255; + info.all_a = 255; p = stbi__bmp_parse_header(s, &info); stbi__rewind( s ); if (p == NULL) return 0; - *x = s->img_x; - *y = s->img_y; - *comp = info.ma ? 4 : 3; + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) *comp = info.ma ? 4 : 3; return 1; } #endif @@ -6656,7 +6664,10 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) #ifndef STBI_NO_PSD static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) { - int channelCount; + int channelCount, dummy; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; if (stbi__get32be(s) != 0x38425053) { stbi__rewind( s ); return 0; @@ -6689,9 +6700,13 @@ static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) #ifndef STBI_NO_PIC static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) { - int act_comp=0,num_packets=0,chained; + int act_comp=0,num_packets=0,chained,dummy; stbi__pic_packet packets[10]; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { stbi__rewind(s); return 0; @@ -6777,7 +6792,7 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req *x = s->img_x; *y = s->img_y; - *comp = s->img_n; + if (comp) *comp = s->img_n; if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0)) return stbi__errpuc("too large", "PNM too large"); @@ -6831,16 +6846,20 @@ static int stbi__pnm_getinteger(stbi__context *s, char *c) static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) { - int maxv; + int maxv, dummy; char c, p, t; - stbi__rewind( s ); + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); // Get identifier p = (char) stbi__get8(s); t = (char) stbi__get8(s); if (p != 'P' || (t != '5' && t != '6')) { - stbi__rewind( s ); + stbi__rewind(s); return 0; } @@ -6947,6 +6966,11 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int /* revision history: + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes 2.11 (2016-04-02) allocate large structures on the stack @@ -7108,3 +7132,46 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int 0.50 (2006-11-19) first released version */ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/raylib/external/stb_image_resize.h b/raylib/external/stb_image_resize.h index 5214ad6..b507e04 100644 --- a/raylib/external/stb_image_resize.h +++ b/raylib/external/stb_image_resize.h @@ -1,4 +1,4 @@ -/* stb_image_resize - v0.92 - public domain image resizing +/* stb_image_resize - v0.94 - public domain image resizing by Jorge L Rodriguez (@VinoBS) - 2014 http://github.com/nothings/stb @@ -107,8 +107,8 @@ industry, it is still uncommon in the videogame/real-time world. If you linearly filter non-premultiplied alpha, strange effects - occur. (For example, the average of 1% opaque bright green - and 99% opaque black produces 50% transparent dark green when + occur. (For example, the 50/50 average of 99% transparent bright green + and 1% transparent black produces 50% transparent dark green when non-premultiplied, whereas premultiplied it produces 50% transparent near-black. The former introduces green energy that doesn't exist in the source image.) @@ -152,20 +152,20 @@ (For example, graphics hardware does not apply sRGB conversion to the alpha channel.) - ADDITIONAL CONTRIBUTORS + CONTRIBUTORS + Jorge L Rodriguez: Implementation Sean Barrett: API design, optimizations Aras Pranckevicius: bugfix REVISIONS + 0.94 (2017-03-18) fixed warnings + 0.93 (2017-03-03) fixed bug with certain combinations of heights 0.92 (2017-01-02) fix integer overflow on large (>2GB) images 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions 0.90 (2014-09-17) first released version LICENSE - - This software is dual-licensed to the public domain and under the following - license: you are granted a perpetual, irrevocable license to copy, modify, - publish, and distribute this file as you see fit. + See end of file for license information. TODO Don't decode all of the image data when only processing a partial tile @@ -533,10 +533,11 @@ typedef struct int horizontal_num_contributors; int vertical_num_contributors; - int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_num_entries; // Total number of entries in the ring buffer. int ring_buffer_first_scanline; int ring_buffer_last_scanline; - int ring_buffer_begin_index; + int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer float* ring_buffer; float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds. @@ -551,16 +552,17 @@ typedef struct int encode_buffer_size; } stbir__info; + +static const float stbir__max_uint8_as_float = 255.0f; +static const float stbir__max_uint16_as_float = 65535.0f; +static const double stbir__max_uint32_as_float = 4294967295.0; + + static stbir__inline int stbir__min(int a, int b) { return a < b ? a : b; } -static stbir__inline int stbir__max(int a, int b) -{ - return a > b ? a : b; -} - static stbir__inline float stbir__saturate(float x) { if (x < 0) @@ -1027,7 +1029,7 @@ static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radi *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5)); } -static void stbir__calculate_coefficients_upsample(stbir__info* stbir_info, stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group) +static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group) { int i; float total_filter = 0; @@ -1077,7 +1079,7 @@ static void stbir__calculate_coefficients_upsample(stbir__info* stbir_info, stbi } } -static void stbir__calculate_coefficients_downsample(stbir__info* stbir_info, stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group) +static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group) { int i; @@ -1107,7 +1109,7 @@ static void stbir__calculate_coefficients_downsample(stbir__info* stbir_info, st } } -static void stbir__normalize_downsample_coefficients(stbir__info* stbir_info, stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) +static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size) { int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio); @@ -1184,7 +1186,7 @@ static void stbir__normalize_downsample_coefficients(stbir__info* stbir_info, st // Each scan line uses the same kernel values so we should calculate the kernel // values once and then we can use them for every scan line. -static void stbir__calculate_filters(stbir__info* stbir_info, stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) +static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) { int n; int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); @@ -1201,7 +1203,7 @@ static void stbir__calculate_filters(stbir__info* stbir_info, stbir__contributor stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out); - stbir__calculate_coefficients_upsample(stbir_info, filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); } } else @@ -1217,10 +1219,10 @@ static void stbir__calculate_filters(stbir__info* stbir_info, stbir__contributor stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in); - stbir__calculate_coefficients_downsample(stbir_info, filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); } - stbir__normalize_downsample_coefficients(stbir_info, contributors, coefficients, filter, scale_ratio, shift, input_size, output_size); + stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size); } } @@ -1270,7 +1272,7 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) int decode_pixel_index = x * channels; int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; for (c = 0; c < channels; c++) - decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / 255; + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float; } break; @@ -1283,7 +1285,7 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]]; if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) - decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / 255; + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float; } break; @@ -1293,7 +1295,7 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) int decode_pixel_index = x * channels; int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; for (c = 0; c < channels; c++) - decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / 65535; + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float; } break; @@ -1303,10 +1305,10 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) int decode_pixel_index = x * channels; int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; for (c = 0; c < channels; c++) - decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / 65535); + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float); if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) - decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / 65535; + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float; } break; @@ -1316,7 +1318,7 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) int decode_pixel_index = x * channels; int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; for (c = 0; c < channels; c++) - decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / 4294967295); + decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float); } break; @@ -1326,10 +1328,10 @@ static void stbir__decode_scanline(stbir__info* stbir_info, int n) int decode_pixel_index = x * channels; int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; for (c = 0; c < channels; c++) - decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / 4294967295)); + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float)); if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) - decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / 4294967295); + decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float); } break; @@ -1411,6 +1413,8 @@ static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) int ring_buffer_index; float* ring_buffer; + stbir_info->ring_buffer_last_scanline = n; + if (stbir_info->ring_buffer_begin_index < 0) { ring_buffer_index = stbir_info->ring_buffer_begin_index = 0; @@ -1418,24 +1422,21 @@ static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) } else { - ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline) + 1) % stbir_info->vertical_filter_pixel_width; + ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); } ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes); - stbir_info->ring_buffer_last_scanline = n; - return ring_buffer; } -static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, float* output_buffer) +static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, float* output_buffer) { int x, k; int output_w = stbir_info->output_w; - int kernel_pixel_width = stbir_info->horizontal_filter_pixel_width; int channels = stbir_info->channels; float* decode_buffer = stbir__get_decode_buffer(stbir_info); stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; @@ -1515,12 +1516,10 @@ static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, int n, } } -static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, int n, float* output_buffer) +static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float* output_buffer) { int x, k; int input_w = stbir_info->input_w; - int output_w = stbir_info->output_w; - int kernel_pixel_width = stbir_info->horizontal_filter_pixel_width; int channels = stbir_info->channels; float* decode_buffer = stbir__get_decode_buffer(stbir_info); stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; @@ -1654,9 +1653,9 @@ static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n) // Now resample it into the ring buffer. if (stbir__use_width_upsampling(stbir_info)) - stbir__resample_horizontal_upsample(stbir_info, n, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); else - stbir__resample_horizontal_downsample(stbir_info, n, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. } @@ -1670,17 +1669,17 @@ static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n // Now resample it into the horizontal buffer. if (stbir__use_width_upsampling(stbir_info)) - stbir__resample_horizontal_upsample(stbir_info, n, stbir_info->horizontal_buffer); + stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer); else - stbir__resample_horizontal_downsample(stbir_info, n, stbir_info->horizontal_buffer); + stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer); // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers. } // Get the specified scan line from the ring buffer. -static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_size, int ring_buffer_length) +static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length) { - int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_size; + int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries; return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length); } @@ -1715,19 +1714,23 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void // build a table of all channels that need colorspace correction, so // we don't perform colorspace correction on channels that don't need it. - for (x=0, num_nonalpha=0; x < channels; ++x) + for (x = 0, num_nonalpha = 0; x < channels; ++x) + { if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) - nonalpha[num_nonalpha++] = x; + { + nonalpha[num_nonalpha++] = (stbir_uint16)x; + } + } #define STBIR__ROUND_INT(f) ((int) ((f)+0.5)) #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5)) #ifdef STBIR__SATURATE_INT - #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * 255 )) - #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * 65535)) + #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float )) + #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float)) #else - #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * 255 ) - #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * 65535) + #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float ) + #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float) #endif switch (decode) @@ -1782,7 +1785,7 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void for (n = 0; n < num_nonalpha; n++) { int index = pixel_index + nonalpha[n]; - ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * 65535); + ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float); } if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) @@ -1799,7 +1802,7 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void for (n = 0; n < channels; n++) { int index = pixel_index + n; - ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * 4294967295); + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float); } } break; @@ -1812,11 +1815,11 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void for (n = 0; n < num_nonalpha; n++) { int index = pixel_index + nonalpha[n]; - ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * 4294967295); + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float); } if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) - ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * 4294967295); + ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float); } break; @@ -1855,7 +1858,7 @@ static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void } } -static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, int in_first_scanline, int in_last_scanline, float in_center_of_out) +static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n) { int x, k; int output_w = stbir_info->output_w; @@ -1865,7 +1868,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in int alpha_channel = stbir_info->alpha_channel; int type = stbir_info->type; int colorspace = stbir_info->colorspace; - int kernel_pixel_width = stbir_info->vertical_filter_pixel_width; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; void* output_data = stbir_info->output_data; float* encode_buffer = stbir_info->encode_buffer; int decode = STBIR__DECODE(type, colorspace); @@ -1876,7 +1879,6 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in float* ring_buffer = stbir_info->ring_buffer; int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; - int ring_buffer_last_scanline = stbir_info->ring_buffer_last_scanline; int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); int n0,n1, output_row_start; @@ -1900,7 +1902,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in for (k = n0; k <= n1; k++) { int coefficient_index = coefficient_counter++; - float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length); + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; for (x = 0; x < output_w; ++x) { @@ -1913,7 +1915,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in for (k = n0; k <= n1; k++) { int coefficient_index = coefficient_counter++; - float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length); + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; for (x = 0; x < output_w; ++x) { @@ -1927,7 +1929,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in for (k = n0; k <= n1; k++) { int coefficient_index = coefficient_counter++; - float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length); + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; for (x = 0; x < output_w; ++x) { @@ -1942,7 +1944,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in for (k = n0; k <= n1; k++) { int coefficient_index = coefficient_counter++; - float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length); + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; for (x = 0; x < output_w; ++x) { @@ -1958,7 +1960,7 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in for (k = n0; k <= n1; k++) { int coefficient_index = coefficient_counter++; - float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length); + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; for (x = 0; x < output_w; ++x) { @@ -1973,16 +1975,14 @@ static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n, in stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode); } -static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n, int in_first_scanline, int in_last_scanline, float in_center_of_out) +static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n) { int x, k; int output_w = stbir_info->output_w; - int output_h = stbir_info->output_h; stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; float* vertical_coefficients = stbir_info->vertical_coefficients; int channels = stbir_info->channels; - int kernel_pixel_width = stbir_info->vertical_filter_pixel_width; - void* output_data = stbir_info->output_data; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; float* horizontal_buffer = stbir_info->horizontal_buffer; int coefficient_width = stbir_info->vertical_coefficient_width; int contributor = n + stbir_info->vertical_filter_pixel_margin; @@ -1990,7 +1990,6 @@ static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n, float* ring_buffer = stbir_info->ring_buffer; int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; - int ring_buffer_last_scanline = stbir_info->ring_buffer_last_scanline; int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); int n0,n1; @@ -2005,7 +2004,7 @@ static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n, int coefficient_group = coefficient_width * contributor; float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; - float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, kernel_pixel_width, ring_buffer_length); + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); switch (channels) { case 1: @@ -2071,7 +2070,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info) stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); - STBIR_ASSERT(in_last_scanline - in_first_scanline <= stbir_info->vertical_filter_pixel_width); + STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); if (stbir_info->ring_buffer_begin_index >= 0) { @@ -2090,7 +2089,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info) else { stbir_info->ring_buffer_first_scanline++; - stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->vertical_filter_pixel_width; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; } } } @@ -2103,7 +2102,7 @@ static void stbir__buffer_loop_upsample(stbir__info* stbir_info) stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1); // Now all buffers should be ready to write a row of vertical sampling. - stbir__resample_vertical_upsample(stbir_info, y, in_first_scanline, in_last_scanline, in_center_of_out); + stbir__resample_vertical_upsample(stbir_info, y); STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h); } @@ -2148,7 +2147,7 @@ static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessar else { stbir_info->ring_buffer_first_scanline++; - stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->vertical_filter_pixel_width; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; } } } @@ -2172,7 +2171,7 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info) stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); - STBIR_ASSERT(out_last_scanline - out_first_scanline <= stbir_info->vertical_filter_pixel_width); + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); if (out_last_scanline < 0 || out_first_scanline >= output_h) continue; @@ -2189,7 +2188,7 @@ static void stbir__buffer_loop_downsample(stbir__info* stbir_info) stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1); // Now the horizontal buffer is ready to write to all ring buffer rows. - stbir__resample_vertical_downsample(stbir_info, y, out_first_scanline, out_last_scanline, out_center_of_in); + stbir__resample_vertical_downsample(stbir_info, y); } stbir__empty_ring_buffer(stbir_info, stbir_info->output_h); @@ -2246,13 +2245,16 @@ static stbir_uint32 stbir__calculate_memory(stbir__info *info) info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w); info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h); + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + info->ring_buffer_num_entries = filter_height + 1; + info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors); info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float); info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors); info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float); info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float); info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float); - info->ring_buffer_size = info->output_w * info->channels * filter_height * sizeof(float); + info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float); info->encode_buffer_size = info->output_w * info->channels * sizeof(float); STBIR_ASSERT(info->horizontal_filter != 0); @@ -2390,8 +2392,8 @@ static int stbir__resize_allocated(stbir__info *info, // This signals that the ring buffer is empty info->ring_buffer_begin_index = -1; - stbir__calculate_filters(info, info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w); - stbir__calculate_filters(info, info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h); + stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w); + stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h); STBIR_PROGRESS_REPORT(0); @@ -2578,3 +2580,45 @@ STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int } #endif // STB_IMAGE_RESIZE_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/raylib/external/stb_image_write.h b/raylib/external/stb_image_write.h index ae9180b..df62339 100644 --- a/raylib/external/stb_image_write.h +++ b/raylib/external/stb_image_write.h @@ -1,4 +1,4 @@ -/* stb_image_write - v1.03 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v1.05 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk @@ -104,12 +104,11 @@ CREDITS: Filip Wasil Thatcher Ulrich github:poppolopoppo + Patrick Boettcher LICENSE -This software is dual-licensed to the public domain and under the following -license: you are granted a perpetual, irrevocable license to copy, modify, -publish, and distribute this file as you see fit. + See end of file for license information. */ @@ -294,10 +293,8 @@ static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, in s->func(s->context, &d[comp - 1], 1); switch (comp) { + case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case case 1: - s->func(s->context,d,1); - break; - case 2: if (expand_mono) stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp else @@ -897,6 +894,7 @@ static unsigned char stbiw__paeth(int a, int b, int c) return STBIW_UCHAR(c); } +// @OPTIMIZE: provide an option that always forces left-predict or paeth predict unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) { int ctype[5] = { -1, 0, 4, 2, 6 }; @@ -913,10 +911,10 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in for (j=0; j < y; ++j) { static int mapping[] = { 0,1,2,3,4 }; static int firstmap[] = { 0,1,0,5,6 }; - int *mymap = j ? mapping : firstmap; + int *mymap = (j != 0) ? mapping : firstmap; int best = 0, bestval = 0x7fffffff; for (p=0; p < 2; ++p) { - for (k= p?best:0; k < 5; ++k) { + for (k= p?best:0; k < 5; ++k) { // @TODO: clarity: rewrite this to go 0..5, and 'continue' the unwanted ones during 2nd pass int type = mymap[k],est=0; unsigned char *z = pixels + stride_bytes*j; for (i=0; i < n; ++i) @@ -1018,6 +1016,9 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history + 1.04 (2017-03-03) + monochrome BMP expansion + 1.03 ??? 1.02 (2016-04-02) avoid allocating large structures on the stack 1.01 (2016-01-16) @@ -1047,3 +1048,45 @@ STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, first public release 0.90 first internal release */ + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/raylib/external/stb_rect_pack.h b/raylib/external/stb_rect_pack.h index c75527d..f5eb8d3 100644 --- a/raylib/external/stb_rect_pack.h +++ b/raylib/external/stb_rect_pack.h @@ -1,4 +1,4 @@ -// stb_rect_pack.h - v0.10 - public domain - rectangle packing +// stb_rect_pack.h - v0.11 - public domain - rectangle packing // Sean Barrett 2014 // // Useful for e.g. packing rectangular textures into an atlas. @@ -27,11 +27,14 @@ // Sean Barrett // Minor features // Martins Mozeiko +// github:IntellectualKitty +// // Bugfixes / warning fixes // Jeremy Jaussaud // // Version history: // +// 0.11 (2017-03-03) return packing success/fail result // 0.10 (2016-10-25) remove cast-away-const to avoid warnings // 0.09 (2016-08-27) fix compiler warnings // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) @@ -43,9 +46,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. ////////////////////////////////////////////////////////////////////////////// // @@ -77,7 +78,7 @@ typedef int stbrp_coord; typedef unsigned short stbrp_coord; #endif -STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); +STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); // Assign packed locations to rectangles. The rectangles are of type // 'stbrp_rect' defined below, stored in the array 'rects', and there // are 'num_rects' many of them. @@ -98,6 +99,9 @@ STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int // arrays will probably produce worse packing results than calling it // a single time with the full rectangle array, but the option is // available. +// +// The function returns 1 if all of the rectangles were successfully +// packed and 0 otherwise. struct stbrp_rect { @@ -544,9 +548,9 @@ static int rect_original_order(const void *a, const void *b) #define STBRP__MAXVAL 0xffff #endif -STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) +STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) { - int i; + int i, all_rects_packed = 1; // we use the 'was_packed' field internally to allow sorting/unsorting for (i=0; i < num_rects; ++i) { @@ -576,8 +580,56 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n // unsort STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); - // set was_packed flags - for (i=0; i < num_rects; ++i) + // set was_packed flags and all_rects_packed status + for (i=0; i < num_rects; ++i) { rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); + if (!rects[i].was_packed) + all_rects_packed = 0; + } + + // return the all_rects_packed status + return all_rects_packed; } #endif + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/raylib/external/stb_truetype.h b/raylib/external/stb_truetype.h index 92b9a87..fc5b978 100644 --- a/raylib/external/stb_truetype.h +++ b/raylib/external/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.14 - public domain +// stb_truetype.h - v1.15 - public domain // authored from 2009-2016 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -50,10 +50,13 @@ // Higor Euripedes // Thomas Fields // Derek Vinyard +// Cort Stratton // // VERSION HISTORY // -// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts, num-fonts-in-TTC function +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef @@ -69,9 +72,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. // // USAGE // @@ -494,7 +495,7 @@ typedef struct float x1,y1,s1,t1; // bottom-right } stbtt_aligned_quad; -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw @@ -594,7 +595,7 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h // To use with PackFontRangesGather etc., you must set it before calls // call to PackFontRangesGatherRects. -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw @@ -3287,11 +3288,11 @@ static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // fo return bottom_y; } -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) { float d3d_bias = opengl_fillrule ? 0 : -0.5f; float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_bakedchar *b = chardata + char_index; + const stbtt_bakedchar *b = chardata + char_index; int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); @@ -3735,10 +3736,10 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontda return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); } -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) { float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_packedchar *b = chardata + char_index; + const stbtt_packedchar *b = chardata + char_index; if (align_to_integer) { float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); @@ -4016,3 +4017,45 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const // 0.2 (2009-03-11) Fix unsigned/signed char warnings // 0.1 (2009-03-09) First public release // + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/raylib/external/stb_vorbis.c b/raylib/external/stb_vorbis.c index 07d7931..21638bc 100644 --- a/raylib/external/stb_vorbis.c +++ b/raylib/external/stb_vorbis.c @@ -162,21 +162,23 @@ #endif #ifndef STB_VORBIS_NO_CRT -#include -#include -#include -#include -#if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)) -#include -#if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) -#include -#endif -#endif + #include + #include + #include + #include + + // find definition of alloca if it's not in stdlib.h: + #if defined(_MSC_VER) || defined(__MINGW32__) + #include + #endif + #if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__) + #include + #endif #else // STB_VORBIS_NO_CRT -#define NULL 0 -#define malloc(s) 0 -#define free(s) ((void) 0) -#define realloc(s) 0 + #define NULL 0 + #define malloc(s) 0 + #define free(s) ((void) 0) + #define realloc(s) 0 #endif // STB_VORBIS_NO_CRT #include @@ -597,17 +599,18 @@ static int ilog(int32 n) { static signed char log2_4[16] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4 }; + if (n < 0) return 0; // signed n returns 0 + // 2 compares if n < 16, 3 compares otherwise (4 if signed or n > 1<<29) if (n < (1 << 14)) - if (n < (1 << 4)) return 0 + log2_4[n ]; - else if (n < (1 << 9)) return 5 + log2_4[n >> 5]; + if (n < (1 << 4)) return 0 + log2_4[n ]; + else if (n < (1 << 9)) return 5 + log2_4[n >> 5]; else return 10 + log2_4[n >> 10]; else if (n < (1 << 24)) - if (n < (1 << 19)) return 15 + log2_4[n >> 15]; + if (n < (1 << 19)) return 15 + log2_4[n >> 15]; else return 20 + log2_4[n >> 20]; - else if (n < (1 << 29)) return 25 + log2_4[n >> 25]; - else if (n < (1 << 31)) return 30 + log2_4[n >> 30]; - else return 0; // signed n returns 0 + else if (n < (1 << 29)) return 25 + log2_4[n >> 25]; + else return 30 + log2_4[n >> 30]; } #ifndef M_PI @@ -880,13 +883,13 @@ static void neighbors(uint16 *x, int n, int *plow, int *phigh) // this has been repurposed so y is now the original index instead of y typedef struct { - uint16 x,y; -} Point; + uint16 x,id; +} stbv__floor_ordering; static int STBV_CDECL point_compare(const void *p, const void *q) { - Point *a = (Point *) p; - Point *b = (Point *) q; + stbv__floor_ordering *a = (stbv__floor_ordering *) p; + stbv__floor_ordering *b = (stbv__floor_ordering *) q; return a->x < b->x ? -1 : a->x > b->x; } @@ -3095,11 +3098,13 @@ static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right) return right - left; } -static void vorbis_pump_first_frame(stb_vorbis *f) +static int vorbis_pump_first_frame(stb_vorbis *f) { - int len, right, left; - if (vorbis_decode_packet(f, &len, &left, &right)) + int len, right, left, res; + res = vorbis_decode_packet(f, &len, &left, &right); + if (res) vorbis_finish_frame(f, len, left, right); + return res; } #ifndef STB_VORBIS_NO_PUSHDATA_API @@ -3482,7 +3487,7 @@ static int start_decoder(vorb *f) g->book_list[j] = get_bits(f,8); return error(f, VORBIS_feature_not_supported); } else { - Point p[31*8+2]; + stbv__floor_ordering p[31*8+2]; Floor1 *g = &f->floor_config[i].floor1; int max_class = -1; g->partitions = get_bits(f, 5); @@ -3518,11 +3523,11 @@ static int start_decoder(vorb *f) // precompute the sorting for (j=0; j < g->values; ++j) { p[j].x = g->Xlist[j]; - p[j].y = j; + p[j].id = j; } qsort(p, g->values, sizeof(p[0]), point_compare); for (j=0; j < g->values; ++j) - g->sorted_order[j] = (uint8) p[j].y; + g->sorted_order[j] = (uint8) p[j].id; // precompute the neighbors for (j=2; j < g->values; ++j) { int low,hi; @@ -4226,8 +4231,9 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number) // starting from the start is handled differently if (sample_number <= left.last_decoded_sample) { - stb_vorbis_seek_start(f); - return 1; + if (stb_vorbis_seek_start(f)) + return 1; + return 0; } while (left.page_end != right.page_start) { @@ -4328,7 +4334,10 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number) skip(f, f->segments[i]); // start decoding (optimizable - this frame is generally discarded) - vorbis_pump_first_frame(f); + if (!vorbis_pump_first_frame(f)) + return 0; + if (f->current_loc > sample_number) + return error(f, VORBIS_seek_failed); return 1; error: @@ -4419,14 +4428,14 @@ int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number) return 1; } -void stb_vorbis_seek_start(stb_vorbis *f) +int stb_vorbis_seek_start(stb_vorbis *f) { - if (IS_PUSH_MODE(f)) { error(f, VORBIS_invalid_api_mixing); return; } + if (IS_PUSH_MODE(f)) { return error(f, VORBIS_invalid_api_mixing); } set_file_offset(f, f->first_audio_page_offset); f->previous_length = 0; f->first_decode = TRUE; f->next_seg = -1; - vorbis_pump_first_frame(f); + return vorbis_pump_first_frame(f); } unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f) @@ -4591,6 +4600,7 @@ stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *err if (f) { *f = p; vorbis_pump_first_frame(f); + if (error) *error = VORBIS__no_error; return f; } } @@ -4956,6 +4966,7 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in #endif // STB_VORBIS_NO_PULLDATA_API /* Version history + 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory 1.09 - 2016/04/04 - back out 'avoid discarding last frame' fix from previous version 1.08 - 2016/04/02 - fixed multiple warnings; fix setup memory leaks; avoid discarding last frame of audio data @@ -5008,3 +5019,46 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in */ #endif // STB_VORBIS_HEADER_ONLY + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/raylib/external/stb_vorbis.h b/raylib/external/stb_vorbis.h index 624ce4b..9394e81 100644 --- a/raylib/external/stb_vorbis.h +++ b/raylib/external/stb_vorbis.h @@ -1,4 +1,4 @@ -// Ogg Vorbis audio decoder - v1.09 - public domain +// Ogg Vorbis audio decoder - v1.10 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. @@ -9,12 +9,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. -// -// No warranty for any purpose is expressed or implied by the author (nor -// by RAD Game Tools). Report bugs and send enhancements to the author. +// See end of file for license information. // // Limitations: // @@ -37,6 +32,7 @@ // manxorist@github saga musix // // Partial history: +// 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory // 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version // 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame // 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const @@ -280,7 +276,7 @@ extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number); // do not need to seek to EXACTLY the target sample when using get_samples_*, // you can also use seek_frame(). -extern void stb_vorbis_seek_start(stb_vorbis *f); +extern int stb_vorbis_seek_start(stb_vorbis *f); // this function is equivalent to stb_vorbis_seek(f,0) extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f); diff --git a/raylib/gestures.h b/raylib/gestures.h index 99f49d2..f04bf09 100644 --- a/raylib/gestures.h +++ b/raylib/gestures.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raylib Gestures System - Gestures Processing based on input gesture events (touch/mouse) +* raylib.gestures - Gestures system, gestures processing based on input events (touch/mouse) * * NOTE: Memory footprint of this library is aproximately 128 bytes (global variables) * @@ -24,7 +24,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -147,7 +147,7 @@ float GetGesturePinchAngle(void); // Get gesture pinch ang // Functions required to query time on Windows int __stdcall QueryPerformanceCounter(unsigned long long int *lpPerformanceCount); int __stdcall QueryPerformanceFrequency(unsigned long long int *lpFrequency); -#elif defined(__linux) +#elif defined(__linux__) #include // Required for: timespec #include // Required for: clock_gettime() #endif @@ -213,8 +213,11 @@ static unsigned int enabledGestures = 0b0000001111111111; //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- +#if defined(GESTURES_STANDALONE) +// Some required math functions provided by raymath.h static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition); static float Vector2Distance(Vector2 v1, Vector2 v2); +#endif static double GetCurrentTime(void); //---------------------------------------------------------------------------------- @@ -477,13 +480,11 @@ float GetGesturePinchAngle(void) //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- - +#if defined(GESTURES_STANDALONE) // Returns angle from two-points vector with X-axis -static float Vector2Angle(Vector2 initialPosition, Vector2 finalPosition) +static float Vector2Angle(Vector2 v1, Vector2 v2) { - float angle; - - angle = atan2f(finalPosition.y - initialPosition.y, finalPosition.x - initialPosition.x)*(180.0f/PI); + float angle = angle = atan2f(v2.y - v1.y, v2.x - v1.x)*(180.0f/PI); if (angle < 0) angle += 360.0f; @@ -502,6 +503,7 @@ static float Vector2Distance(Vector2 v1, Vector2 v2) return result; } +#endif // Time measure returned are milliseconds static double GetCurrentTime(void) @@ -517,7 +519,7 @@ static double GetCurrentTime(void) time = (double)currentTime/clockFrequency*1000.0f; // Time in miliseconds #endif -#if defined(__linux) +#if defined(__linux__) // NOTE: Only for Linux-based systems struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); diff --git a/raylib/models.c b/raylib/models.c index bef19e1..fa6faf1 100644 --- a/raylib/models.c +++ b/raylib/models.c @@ -1,17 +1,19 @@ /********************************************************************************************** * -* raylib.models - Basic functions to draw 3d shapes and 3d models +* raylib.models - Basic functions to deal with 3d shapes and 3d models * * CONFIGURATION: * -* #define SUPPORT_FILEFORMAT_OBJ / SUPPORT_LOAD_OBJ +* #define SUPPORT_FILEFORMAT_OBJ +* Selected desired fileformats to be supported for loading. * * #define SUPPORT_FILEFORMAT_MTL +* Selected desired fileformats to be supported for loading. * * * LICENSE: zlib/libpng * -* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -30,6 +32,12 @@ * **********************************************************************************************/ +// Default configuration flags (supported features) +//------------------------------------------------- +#define SUPPORT_FILEFORMAT_OBJ +#define SUPPORT_FILEFORMAT_MTL +//------------------------------------------------- + #include "raylib.h" #if defined(PLATFORM_ANDROID) @@ -61,8 +69,12 @@ //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- +#if defined(SUPPORT_FILEFORMAT_OBJ) static Mesh LoadOBJ(const char *fileName); // Load OBJ mesh data +#endif +#if defined(SUPPORT_FILEFORMAT_MTL) static Material LoadMTL(const char *fileName); // Load MTL material data +#endif static Mesh GenMeshHeightmap(Image image, Vector3 size); static Mesh GenMeshCubicmap(Image cubicmap, Vector3 cubeSize); @@ -580,8 +592,11 @@ Mesh LoadMesh(const char *fileName) { Mesh mesh = { 0 }; - if (strcmp(GetExtension(fileName), "obj") == 0) mesh = LoadOBJ(fileName); - else TraceLog(WARNING, "[%s] Mesh extension not recognized, it can't be loaded", fileName); +#if defined(SUPPORT_FILEFORMAT_OBJ) + if (IsFileExtension(fileName, ".obj")) mesh = LoadOBJ(fileName); +#else + TraceLog(WARNING, "[%s] Mesh fileformat not supported, it can't be loaded", fileName); +#endif if (mesh.vertexCount == 0) TraceLog(WARNING, "Mesh could not be loaded"); else rlglLoadMesh(&mesh, false); // Upload vertex data to GPU (static mesh) @@ -592,13 +607,13 @@ Mesh LoadMesh(const char *fileName) } // Load mesh from vertex data -// NOTE: All vertex data arrays must be same size: numVertex -Mesh LoadMeshEx(int numVertex, float *vData, float *vtData, float *vnData, Color *cData) +// NOTE: All vertex data arrays must be same size: vertexCount +Mesh LoadMeshEx(int vertexCount, float *vData, float *vtData, float *vnData, Color *cData) { Mesh mesh = { 0 }; - mesh.vertexCount = numVertex; - mesh.triangleCount = numVertex/3; + mesh.vertexCount = vertexCount; + mesh.triangleCount = vertexCount/3; mesh.vertices = vData; mesh.texcoords = vtData; mesh.texcoords2 = NULL; @@ -690,8 +705,11 @@ Material LoadMaterial(const char *fileName) { Material material = { 0 }; - if (strcmp(GetExtension(fileName), "mtl") == 0) material = LoadMTL(fileName); - else TraceLog(WARNING, "[%s] Material extension not recognized, it can't be loaded", fileName); +#if defined(SUPPORT_FILEFORMAT_MTL) + if (IsFileExtension(fileName, ".mtl")) material = LoadMTL(fileName); +#else + TraceLog(WARNING, "[%s] Material fileformat not supported, it can't be loaded", fileName); +#endif return material; } @@ -736,9 +754,9 @@ static Mesh GenMeshHeightmap(Image heightmap, Vector3 size) Color *pixels = GetImageData(heightmap); // NOTE: One vertex per pixel - int numTriangles = (mapX-1)*(mapZ-1)*2; // One quad every four pixels + int triangleCount = (mapX-1)*(mapZ-1)*2; // One quad every four pixels - mesh.vertexCount = numTriangles*3; + mesh.vertexCount = triangleCount*3; mesh.vertices = (float *)malloc(mesh.vertexCount*3*sizeof(float)); mesh.normals = (float *)malloc(mesh.vertexCount*3*sizeof(float)); @@ -1588,6 +1606,7 @@ BoundingBox CalculateBoundingBox(Mesh mesh) // Module specific Functions Definition //---------------------------------------------------------------------------------- +#if defined(SUPPORT_FILEFORMAT_OBJ) // Load OBJ mesh data static Mesh LoadOBJ(const char *fileName) { @@ -1596,10 +1615,10 @@ static Mesh LoadOBJ(const char *fileName) char dataType; char comments[200]; - int numVertex = 0; - int numNormals = 0; - int numTexCoords = 0; - int numTriangles = 0; + int vertexCount = 0; + int normalCount = 0; + int texcoordCount = 0; + int triangleCount = 0; FILE *objFile; @@ -1611,7 +1630,7 @@ static Mesh LoadOBJ(const char *fileName) return mesh; } - // First reading pass: Get numVertex, numNormals, numTexCoords, numTriangles + // First reading pass: Get vertexCount, normalCount, texcoordCount, triangleCount // NOTE: vertex, texcoords and normals could be optimized (to be used indexed on faces definition) // NOTE: faces MUST be defined as TRIANGLES (3 vertex per face) while (!feof(objFile)) @@ -1635,40 +1654,40 @@ static Mesh LoadOBJ(const char *fileName) if (dataType == 't') // Read texCoord { - numTexCoords++; + texcoordCount++; fgets(comments, 200, objFile); } else if (dataType == 'n') // Read normals { - numNormals++; + normalCount++; fgets(comments, 200, objFile); } else // Read vertex { - numVertex++; + vertexCount++; fgets(comments, 200, objFile); } } break; case 'f': { - numTriangles++; + triangleCount++; fgets(comments, 200, objFile); } break; default: break; } } - TraceLog(DEBUG, "[%s] Model num vertices: %i", fileName, numVertex); - TraceLog(DEBUG, "[%s] Model num texcoords: %i", fileName, numTexCoords); - TraceLog(DEBUG, "[%s] Model num normals: %i", fileName, numNormals); - TraceLog(DEBUG, "[%s] Model num triangles: %i", fileName, numTriangles); + TraceLog(DEBUG, "[%s] Model vertices: %i", fileName, vertexCount); + TraceLog(DEBUG, "[%s] Model texcoords: %i", fileName, texcoordCount); + TraceLog(DEBUG, "[%s] Model normals: %i", fileName, normalCount); + TraceLog(DEBUG, "[%s] Model triangles: %i", fileName, triangleCount); // Once we know the number of vertices to store, we create required arrays - Vector3 *midVertices = (Vector3 *)malloc(numVertex*sizeof(Vector3)); + Vector3 *midVertices = (Vector3 *)malloc(vertexCount*sizeof(Vector3)); Vector3 *midNormals = NULL; - if (numNormals > 0) midNormals = (Vector3 *)malloc(numNormals*sizeof(Vector3)); + if (normalCount > 0) midNormals = (Vector3 *)malloc(normalCount*sizeof(Vector3)); Vector2 *midTexCoords = NULL; - if (numTexCoords > 0) midTexCoords = (Vector2 *)malloc(numTexCoords*sizeof(Vector2)); + if (texcoordCount > 0) midTexCoords = (Vector2 *)malloc(texcoordCount*sizeof(Vector2)); int countVertex = 0; int countNormals = 0; @@ -1719,7 +1738,7 @@ static Mesh 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 Mesh struct - mesh.vertexCount = numTriangles*3; + mesh.vertexCount = triangleCount*3; // Additional arrays to store vertex data as floats mesh.vertices = (float *)malloc(mesh.vertexCount*3*sizeof(float)); @@ -1731,11 +1750,11 @@ static Mesh LoadOBJ(const char *fileName) int tcCounter = 0; // Used to count texcoords float by float int nCounter = 0; // Used to count normals float by float - int vNum[3], vtNum[3], vnNum[3]; // Used to store triangle indices for v, vt, vn + int vCount[3], vtCount[3], vnCount[3]; // Used to store triangle indices for v, vt, vn rewind(objFile); // Return to the beginning of the file, to read again - if (numNormals == 0) TraceLog(INFO, "[%s] No normals data on OBJ, normals will be generated from faces data", fileName); + if (normalCount == 0) TraceLog(INFO, "[%s] No normals data on OBJ, normals will be generated from faces data", fileName); // Third reading pass: Get faces (triangles) data and fill VertexArray while (!feof(objFile)) @@ -1749,43 +1768,43 @@ static Mesh LoadOBJ(const char *fileName) { // NOTE: It could be that OBJ does not have normals or texcoords defined! - if ((numNormals == 0) && (numTexCoords == 0)) fscanf(objFile, "%i %i %i", &vNum[0], &vNum[1], &vNum[2]); - 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 if (numTexCoords == 0) fscanf(objFile, "%i//%i %i//%i %i//%i", &vNum[0], &vnNum[0], &vNum[1], &vnNum[1], &vNum[2], &vnNum[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]); + if ((normalCount == 0) && (texcoordCount == 0)) fscanf(objFile, "%i %i %i", &vCount[0], &vCount[1], &vCount[2]); + else if (normalCount == 0) fscanf(objFile, "%i/%i %i/%i %i/%i", &vCount[0], &vtCount[0], &vCount[1], &vtCount[1], &vCount[2], &vtCount[2]); + else if (texcoordCount == 0) fscanf(objFile, "%i//%i %i//%i %i//%i", &vCount[0], &vnCount[0], &vCount[1], &vnCount[1], &vCount[2], &vnCount[2]); + else fscanf(objFile, "%i/%i/%i %i/%i/%i %i/%i/%i", &vCount[0], &vtCount[0], &vnCount[0], &vCount[1], &vtCount[1], &vnCount[1], &vCount[2], &vtCount[2], &vnCount[2]); - 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; + mesh.vertices[vCounter] = midVertices[vCount[0]-1].x; + mesh.vertices[vCounter + 1] = midVertices[vCount[0]-1].y; + mesh.vertices[vCounter + 2] = midVertices[vCount[0]-1].z; vCounter += 3; - 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; + mesh.vertices[vCounter] = midVertices[vCount[1]-1].x; + mesh.vertices[vCounter + 1] = midVertices[vCount[1]-1].y; + mesh.vertices[vCounter + 2] = midVertices[vCount[1]-1].z; vCounter += 3; - 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; + mesh.vertices[vCounter] = midVertices[vCount[2]-1].x; + mesh.vertices[vCounter + 1] = midVertices[vCount[2]-1].y; + mesh.vertices[vCounter + 2] = midVertices[vCount[2]-1].z; vCounter += 3; - if (numNormals > 0) + if (normalCount > 0) { - 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; + mesh.normals[nCounter] = midNormals[vnCount[0]-1].x; + mesh.normals[nCounter + 1] = midNormals[vnCount[0]-1].y; + mesh.normals[nCounter + 2] = midNormals[vnCount[0]-1].z; nCounter += 3; - 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; + mesh.normals[nCounter] = midNormals[vnCount[1]-1].x; + mesh.normals[nCounter + 1] = midNormals[vnCount[1]-1].y; + mesh.normals[nCounter + 2] = midNormals[vnCount[1]-1].z; nCounter += 3; - 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; + mesh.normals[nCounter] = midNormals[vnCount[2]-1].x; + mesh.normals[nCounter + 1] = midNormals[vnCount[2]-1].y; + mesh.normals[nCounter + 2] = midNormals[vnCount[2]-1].z; nCounter += 3; } else { // If normals not defined, they are calculated from the 3 vertices [N = (V2 - V1) x (V3 - V1)] - Vector3 norm = VectorCrossProduct(VectorSubtract(midVertices[vNum[1]-1], midVertices[vNum[0]-1]), VectorSubtract(midVertices[vNum[2]-1], midVertices[vNum[0]-1])); + Vector3 norm = VectorCrossProduct(VectorSubtract(midVertices[vCount[1]-1], midVertices[vCount[0]-1]), VectorSubtract(midVertices[vCount[2]-1], midVertices[vCount[0]-1])); VectorNormalize(&norm); mesh.normals[nCounter] = norm.x; @@ -1802,18 +1821,18 @@ static Mesh LoadOBJ(const char *fileName) nCounter += 3; } - if (numTexCoords > 0) + if (texcoordCount > 0) { // 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 - mesh.texcoords[tcCounter] = midTexCoords[vtNum[0]-1].x; - mesh.texcoords[tcCounter + 1] = 1.0f - midTexCoords[vtNum[0]-1].y; + mesh.texcoords[tcCounter] = midTexCoords[vtCount[0]-1].x; + mesh.texcoords[tcCounter + 1] = 1.0f - midTexCoords[vtCount[0]-1].y; tcCounter += 2; - mesh.texcoords[tcCounter] = midTexCoords[vtNum[1]-1].x; - mesh.texcoords[tcCounter + 1] = 1.0f - midTexCoords[vtNum[1]-1].y; + mesh.texcoords[tcCounter] = midTexCoords[vtCount[1]-1].x; + mesh.texcoords[tcCounter + 1] = 1.0f - midTexCoords[vtCount[1]-1].y; tcCounter += 2; - mesh.texcoords[tcCounter] = midTexCoords[vtNum[2]-1].x; - mesh.texcoords[tcCounter + 1] = 1.0f - midTexCoords[vtNum[2]-1].y; + mesh.texcoords[tcCounter] = midTexCoords[vtCount[2]-1].x; + mesh.texcoords[tcCounter + 1] = 1.0f - midTexCoords[vtCount[2]-1].y; tcCounter += 2; } } break; @@ -1824,7 +1843,77 @@ static Mesh 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*mesh.vertexCount); i++) mesh.texcoords[i] = 0.0f; + if (texcoordCount == 0) for (int i = 0; i < (2*mesh.vertexCount); i++) mesh.texcoords[i] = 0.0f; + else + { + // Attempt to calculate mesh tangents and binormals using positions and texture coordinates + mesh.tangents = (float *)malloc(mesh.vertexCount*3*sizeof(float)); + // mesh.binormals = (float *)malloc(mesh.vertexCount*3*sizeof(float)); + + int vCount = 0; + int uvCount = 0; + while (vCount < mesh.vertexCount*3) + { + // Calculate mesh vertex positions as Vector3 + Vector3 v0 = { mesh.vertices[vCount], mesh.vertices[vCount + 1], mesh.vertices[vCount + 2] }; + Vector3 v1 = { mesh.vertices[vCount + 3], mesh.vertices[vCount + 4], mesh.vertices[vCount + 5] }; + Vector3 v2 = { mesh.vertices[vCount + 6], mesh.vertices[vCount + 7], mesh.vertices[vCount + 8] }; + + // Calculate mesh texture coordinates as Vector2 + Vector2 uv0 = { mesh.texcoords[uvCount + 0], mesh.texcoords[uvCount + 1] }; + Vector2 uv1 = { mesh.texcoords[uvCount + 2], mesh.texcoords[uvCount + 3] }; + Vector2 uv2 = { mesh.texcoords[uvCount + 4], mesh.texcoords[uvCount + 5] }; + + // Calculate edges of the triangle (position delta) + Vector3 deltaPos1 = VectorSubtract(v1, v0); + Vector3 deltaPos2 = VectorSubtract(v2, v0); + + // UV delta + Vector2 deltaUV1 = { uv1.x - uv0.x, uv1.y - uv0.y }; + Vector2 deltaUV2 = { uv2.x - uv0.x, uv2.y - uv0.y }; + + float r = 1.0f/(deltaUV1.x*deltaUV2.y - deltaUV1.y*deltaUV2.x); + Vector3 t1 = { deltaPos1.x*deltaUV2.y, deltaPos1.y*deltaUV2.y, deltaPos1.z*deltaUV2.y }; + Vector3 t2 = { deltaPos2.x*deltaUV1.y, deltaPos2.y*deltaUV1.y, deltaPos2.z*deltaUV1.y }; + // Vector3 b1 = { deltaPos2.x*deltaUV1.x, deltaPos2.y*deltaUV1.x, deltaPos2.z*deltaUV1.x }; + // Vector3 b2 = { deltaPos1.x*deltaUV2.x, deltaPos1.y*deltaUV2.x, deltaPos1.z*deltaUV2.x }; + + // Calculate vertex tangent + Vector3 tangent = VectorSubtract(t1, t2); + VectorScale(&tangent, r); + + // Apply calculated tangents data to mesh struct + mesh.tangents[vCount + 0] = tangent.x; + mesh.tangents[vCount + 1] = tangent.y; + mesh.tangents[vCount + 2] = tangent.z; + mesh.tangents[vCount + 3] = tangent.x; + mesh.tangents[vCount + 4] = tangent.y; + mesh.tangents[vCount + 5] = tangent.z; + mesh.tangents[vCount + 6] = tangent.x; + mesh.tangents[vCount + 7] = tangent.y; + mesh.tangents[vCount + 8] = tangent.z; + + // TODO: add binormals to mesh struct and assign buffers id and locations properly + /* // Calculate vertex binormal + Vector3 binormal = VectorSubtract(b1, b2); + VectorScale(&binormal, r); + + // Apply calculated binormals data to mesh struct + mesh.binormals[vCount + 0] = binormal.x; + mesh.binormals[vCount + 1] = binormal.y; + mesh.binormals[vCount + 2] = binormal.z; + mesh.binormals[vCount + 3] = binormal.x; + mesh.binormals[vCount + 4] = binormal.y; + mesh.binormals[vCount + 5] = binormal.z; + mesh.binormals[vCount + 6] = binormal.x; + mesh.binormals[vCount + 7] = binormal.y; + mesh.binormals[vCount + 8] = binormal.z; */ + + // Update vertex position and texture coordinates counters + vCount += 9; + uvCount += 6; + } + } // Now we can free temp mid* arrays free(midVertices); @@ -1836,7 +1925,9 @@ static Mesh LoadOBJ(const char *fileName) return mesh; } +#endif +#if defined(SUPPORT_FILEFORMAT_MTL) // Load MTL material data (specs: http://paulbourke.net/dataformats/mtl/) // NOTE: Texture map parameters are not supported static Material LoadMTL(const char *fileName) @@ -2000,3 +2091,4 @@ static Material LoadMTL(const char *fileName) return material; } +#endif diff --git a/raylib/raylib.h b/raylib/raylib.h index e679e01..18d442d 100644 --- a/raylib/raylib.h +++ b/raylib/raylib.h @@ -1,43 +1,45 @@ /********************************************************************************************** * -* raylib v1.7.0 (www.raylib.com) +* raylib v1.7.0 * -* A simple and easy-to-use library to learn videogames programming +* A simple and easy-to-use library to learn videogames programming (www.raylib.com) * * FEATURES: -* Library written in plain C code (C99) -* Uses PascalCase/camelCase notation -* Hardware accelerated with OpenGL (1.1, 2.1, 3.3 or ES 2.0) -* Unique OpenGL abstraction layer (usable as standalone module): [rlgl] -* Powerful fonts module with SpriteFonts support (XNA bitmap fonts, AngelCode fonts, TTF) -* Multiple textures support, including compressed formats and mipmaps generation -* Basic 3d support for Shapes, Models, Billboards, Heightmaps and Cubicmaps -* Powerful math module for Vector, Matrix and Quaternion operations: [raymath] -* Audio loading and playing with streaming support and mixing channels [audio] -* VR stereo rendering support with configurable HMD device parameters -* Multiple platforms support: Windows, Linux, Mac, Android, Raspberry Pi, HTML5 and Oculus Rift CV1 -* Custom color palette for fancy visuals on raywhite background -* Minimal external dependencies (GLFW3, OpenGL, OpenAL) -* Complete binding for Lua [rlua] +* - Library written in plain C code (C99) +* - Uses PascalCase/camelCase notation +* - Hardware accelerated with OpenGL (1.1, 2.1, 3.3 or ES 2.0) +* - Unique OpenGL abstraction layer (usable as standalone module): [rlgl] +* - Powerful fonts module with SpriteFonts support (XNA bitmap fonts, AngelCode fonts, TTF) +* - Multiple textures support, including compressed formats and mipmaps generation +* - Basic 3d support for Shapes, Models, Billboards, Heightmaps and Cubicmaps +* - Powerful math module for Vector, Matrix and Quaternion operations: [raymath] +* - Audio loading and playing with streaming support and mixing channels: [audio] +* - VR stereo rendering support with configurable HMD device parameters +* - Multiple platforms support: Windows, Linux, Mac, Android, Raspberry Pi, HTML5 and Oculus Rift CV1 +* - Custom color palette for fancy visuals on raywhite background +* - Minimal external dependencies (GLFW3, OpenGL, OpenAL) +* - Complete bindings for Lua, Go and Pascal * * NOTES: -* 32bit Colors - All defined color are always RGBA (struct Color is 4 byte) -* One custom default font could be loaded automatically when InitWindow() [core] -* 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 could be loaded automatically (internally defined) +* 32bit Colors - All defined color are always RGBA (struct Color is 4 byte) +* One custom default font could be loaded automatically when InitWindow() [core] +* 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 could be loaded automatically (internally defined) * * DEPENDENCIES: -* GLFW3 (www.glfw.org) for window/context management and input [core] -* GLAD for OpenGL extensions loading (3.3 Core profile, only PLATFORM_DESKTOP) [rlgl] -* stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA) [textures] -* stb_image_write (Sean Barret) for image writting (PNG) [utils] -* stb_truetype (Sean Barret) for ttf fonts loading [text] -* stb_vorbis (Sean Barret) for ogg audio loading [audio] -* jar_xm (Joshua Reisenauer) for XM audio module loading [audio] -* jar_mod (Joshua Reisenauer) for MOD audio module loading [audio] -* dr_flac (David Reid) for FLAC audio file loading [audio] -* OpenAL Soft for audio device/context management [audio] -* tinfl for data decompression (DEFLATE algorithm) [utils] +* GLFW3 (www.glfw.org) for window/context management and input [core] +* GLAD for OpenGL extensions loading (3.3 Core profile, only PLATFORM_DESKTOP) [rlgl] +* OpenAL Soft for audio device/context management [audio] +* +* OPTIONAL DEPENDENCIES: +* stb_image (Sean Barret) for images loading (JPEG, PNG, BMP, TGA) [textures] +* stb_image_write (Sean Barret) for image writting (PNG) [utils] +* stb_truetype (Sean Barret) for ttf fonts loading [text] +* stb_vorbis (Sean Barret) for ogg audio loading [audio] +* jar_xm (Joshua Reisenauer) for XM audio module loading [audio] +* jar_mod (Joshua Reisenauer) for MOD audio module loading [audio] +* dr_flac (David Reid) for FLAC audio file loading [audio] +* tinfl for data decompression (DEFLATE algorithm) [rres] * * * LICENSE: zlib/libpng @@ -45,7 +47,7 @@ * 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: * -* Copyright (c) 2013-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2013-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -72,7 +74,6 @@ //#define PLATFORM_ANDROID // Android device //#define PLATFORM_RPI // Raspberry Pi //#define PLATFORM_WEB // HTML5 (emscripten, asm.js) -//#define RLGL_OCULUS_SUPPORT // Oculus Rift CV1 (complementary to PLATFORM_DESKTOP) // Security check in case no PLATFORM_* defined #if !defined(PLATFORM_DESKTOP) && !defined(PLATFORM_ANDROID) && !defined(PLATFORM_RPI) && !defined(PLATFORM_WEB) @@ -293,7 +294,7 @@ #define RAYWHITE CLITERAL{ 245, 245, 245, 255 } // My own White (raylib logo) //---------------------------------------------------------------------------------- -// Types and Structures Definition +// Structures Definition //---------------------------------------------------------------------------------- #ifndef __cplusplus // Boolean type @@ -514,6 +515,34 @@ typedef struct AudioStream { unsigned int buffers[2]; // OpenAL audio buffers (double buffering) } AudioStream; +// rRES data returned when reading a resource, +// it contains all required data for user (24 byte) +typedef struct RRESData { + unsigned int type; // Resource type (4 byte) + + unsigned int param1; // Resouce parameter 1 (4 byte) + unsigned int param2; // Resouce parameter 2 (4 byte) + unsigned int param3; // Resouce parameter 3 (4 byte) + unsigned int param4; // Resouce parameter 4 (4 byte) + + void *data; // Resource data pointer (4 byte) +} RRESData; + +// RRES type (pointer to RRESData array) +typedef struct RRESData *RRES; + +//---------------------------------------------------------------------------------- +// Enumerators Definition +//---------------------------------------------------------------------------------- +// Trace log type +typedef enum { + INFO = 0, + WARNING, + ERROR, + DEBUG, + OTHER +} LogType; + // Texture formats // NOTE: Support depends on OpenGL version and platform typedef enum { @@ -550,10 +579,18 @@ typedef enum { } TextureFilterMode; // Texture parameters: wrap mode -typedef enum { WRAP_REPEAT = 0, WRAP_CLAMP, WRAP_MIRROR } TextureWrapMode; +typedef enum { + WRAP_REPEAT = 0, + WRAP_CLAMP, + WRAP_MIRROR +} TextureWrapMode; // Color blending modes (pre-defined) -typedef enum { BLEND_ALPHA = 0, BLEND_ADDITIVE, BLEND_MULTIPLIED } BlendMode; +typedef enum { + BLEND_ALPHA = 0, + BLEND_ADDITIVE, + BLEND_MULTIPLIED +} BlendMode; // Gestures type // NOTE: It could be used as flags to enable only some gestures @@ -593,19 +630,6 @@ typedef enum { HMD_FOVE_VR, } VrDevice; -// rRES data returned when reading a resource, -// it contains all required data for user (24 byte) -typedef struct RRESData { - unsigned int type; // Resource type (4 byte) - - unsigned int param1; // Resouce parameter 1 (4 byte) - unsigned int param2; // Resouce parameter 2 (4 byte) - unsigned int param3; // Resouce parameter 3 (4 byte) - unsigned int param4; // Resouce parameter 4 (4 byte) - - void *data; // Resource data pointer (4 byte) -} RRESData; - // RRESData type typedef enum { RRES_TYPE_RAW = 0, @@ -618,9 +642,6 @@ typedef enum { RRES_TYPE_DIRECTORY } RRESDataType; -// RRES type (pointer to RRESData array) -typedef struct RRESData *RRES; - #ifdef __cplusplus extern "C" { // Prevents name mangling of functions #endif @@ -685,9 +706,11 @@ RLAPI float *MatrixToFloat(Matrix mat); // Converts Ma RLAPI int GetRandomValue(int min, int max); // Returns a random value between min and max (both included) RLAPI Color Fade(Color color, float alpha); // Color fade-in or fade-out, alpha goes from 0.0f to 1.0f -RLAPI void SetConfigFlags(char flags); // Setup some window configuration flags RLAPI void ShowLogo(void); // Activates raylib logo at startup (can be done with flags) -//RLAPI void TraceLog(int logType, const char *text, ...); // Trace log messages showing (INFO, WARNING, ERROR, DEBUG) +RLAPI void SetConfigFlags(char flags); // Setup some window configuration flags +RLAPI void TraceLog(int logType, const char *text, ...); // Show trace log messages (INFO, WARNING, ERROR, DEBUG) +RLAPI void TakeScreenshot(void); // Takes a screenshot and saves it in the same folder as executable +RLAPI bool IsFileExtension(const char *fileName, const char *ext);// Check file extension RLAPI bool IsFileDropped(void); // Check if a file have been dropped into window RLAPI char **GetDroppedFiles(int *count); // Retrieve dropped files into window @@ -843,7 +866,7 @@ RLAPI void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle dest //------------------------------------------------------------------------------------ RLAPI SpriteFont GetDefaultFont(void); // Get the default SpriteFont RLAPI SpriteFont LoadSpriteFont(const char *fileName); // Load SpriteFont from file into GPU memory (VRAM) -RLAPI SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load SpriteFont from TTF font file with generation parameters +RLAPI SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load SpriteFont from file with extended parameters RLAPI void UnloadSpriteFont(SpriteFont spriteFont); // Unload SpriteFont from GPU memory (VRAM) RLAPI void DrawText(const char *text, int posX, int posY, int fontSize, Color color); // Draw text (using default font) @@ -889,7 +912,6 @@ RLAPI void UnloadMesh(Mesh *mesh); RLAPI void UnloadModel(Model model); // Unload model from memory (RAM and/or VRAM) RLAPI Material LoadMaterial(const char *fileName); // Load material from file -RLAPI Material LoadMaterialEx(Shader shader, Texture2D diffuse, Color color); // Load material from basic shading data RLAPI Material LoadDefaultMaterial(void); // Load default material (uses default models shader) RLAPI void UnloadMaterial(Material material); // Unload material from GPU memory (VRAM) diff --git a/raylib/raymath.h b/raylib/raymath.h index a2263f1..3bde10f 100644 --- a/raylib/raymath.h +++ b/raylib/raymath.h @@ -1,6 +1,6 @@ /********************************************************************************************** * -* raymath v1.0 - Some useful functions to work with Vector3, Matrix and Quaternions +* raymath v1.0 - Math functions to work with Vector3, Matrix and Quaternions * * CONFIGURATION: * @@ -112,45 +112,67 @@ typedef struct Quaternion { #ifndef RAYMATH_EXTERN_INLINE +//------------------------------------------------------------------------------------ +// Functions Declaration - math utils +//------------------------------------------------------------------------------------ +RMDEF float Clamp(float value, float min, float max); // Clamp float value + +//------------------------------------------------------------------------------------ +// Functions Declaration to work with Vector2 +//------------------------------------------------------------------------------------ +RMDEF Vector2 Vector2Zero(void); // Vector with components value 0.0f +RMDEF Vector2 Vector2One(void); // Vector with components value 1.0f +RMDEF Vector2 Vector2Add(Vector2 v1, Vector2 v2); // Add two vectors (v1 + v2) +RMDEF Vector2 Vector2Subtract(Vector2 v1, Vector2 v2); // Subtract two vectors (v1 - v2) +RMDEF float Vector2Lenght(Vector2 v); // Calculate vector lenght +RMDEF float Vector2DotProduct(Vector2 v1, Vector2 v2); // Calculate two vectors dot product +RMDEF float Vector2Distance(Vector2 v1, Vector2 v2); // Calculate distance between two vectors +RMDEF float Vector2Angle(Vector2 v1, Vector2 v2); // Calculate angle between two vectors in X-axis +RMDEF void Vector2Scale(Vector2 *v, float scale); // Scale vector (multiply by value) +RMDEF void Vector2Negate(Vector2 *v); // Negate vector +RMDEF void Vector2Divide(Vector2 *v, float div); // Divide vector by a float value +RMDEF void Vector2Normalize(Vector2 *v); // Normalize provided vector + //------------------------------------------------------------------------------------ // 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 VectorZero(void); // Vector with components value 0.0f +RMDEF Vector3 VectorOne(void); // Vector with components value 1.0f +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 VectorLength(const Vector3 v); // Calculate vector lenght +RMDEF float VectorDotProduct(Vector3 v1, Vector3 v2); // Calculate two vectors dot product +RMDEF float VectorDistance(Vector3 v1, Vector3 v2); // Calculate distance between two points +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 void VectorTransform(Vector3 *v, Matrix mat); // Transforms a Vector3 by a given Matrix 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 -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 -RMDEF Vector3 Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycenter coords for p in triangle abc +RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal); // Calculate reflected vector to normal +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 +RMDEF Vector3 VectorBarycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycenter coords for p in triangle abc //------------------------------------------------------------------------------------ // 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(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) -RMDEF Matrix MatrixScale(float x, float y, float z); // Returns scaling matrix -RMDEF Matrix MatrixMultiply(Matrix left, Matrix right); // Returns two matrix multiplication +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(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) +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 @@ -159,9 +181,9 @@ RMDEF Matrix MatrixLookAt(Vector3 position, Vector3 target, Vector3 up); // Ret //------------------------------------------------------------------------------------ // 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 void QuaternionInvert(Quaternion *quat); // Invert provided quaternion +RMDEF float QuaternionLength(Quaternion quat); // Compute the length of a quaternion +RMDEF void QuaternionNormalize(Quaternion *q); // Normalize provided quaternion +RMDEF void QuaternionInvert(Quaternion *quat); // Invert 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 @@ -179,32 +201,113 @@ RMDEF void QuaternionTransform(Quaternion *q, Matrix mat); // Transfo #include // Required for: sinf(), cosf(), tan(), fabs() +//---------------------------------------------------------------------------------- +// Module Functions Definition - Utils math +//---------------------------------------------------------------------------------- + +// Clamp float value +RMDEF float Clamp(float value, float min, float max) +{ + const float res = value < min ? min : value; + return res > max ? max : res; +} + +//---------------------------------------------------------------------------------- +// Module Functions Definition - Vector2 math +//---------------------------------------------------------------------------------- + +// Vector with components value 0.0f +RMDEF Vector2 Vector2Zero(void) { return (Vector2){ 0.0f, 0.0f }; } + +// Vector with components value 1.0f +RMDEF Vector2 Vector2One(void) { return (Vector2){ 1.0f, 1.0f }; } + +// Add two vectors (v1 + v2) +RMDEF Vector2 Vector2Add(Vector2 v1, Vector2 v2) +{ + return (Vector2){ v1.x + v2.x, v1.y + v2.y }; +} + +// Subtract two vectors (v1 - v2) +RMDEF Vector2 Vector2Subtract(Vector2 v1, Vector2 v2) +{ + return (Vector2){ v1.x - v2.x, v1.y - v2.y }; +} + +// Calculate vector lenght +RMDEF float Vector2Lenght(Vector2 v) +{ + return sqrtf((v.x*v.x) + (v.y*v.y)); +} + +// Calculate two vectors dot product +RMDEF float Vector2DotProduct(Vector2 v1, Vector2 v2) +{ + return (v1.x*v2.x + v1.y*v2.y); +} + +// Calculate distance between two vectors +RMDEF float Vector2Distance(Vector2 v1, Vector2 v2) +{ + return sqrtf((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y)); +} + +// Calculate angle from two vectors in X-axis +RMDEF float Vector2Angle(Vector2 v1, Vector2 v2) +{ + float angle = atan2f(v2.y - v1.y, v2.x - v1.x)*(180.0f/PI); + + if (angle < 0) angle += 360.0f; + + return angle; +} + +// Scale vector (multiply by value) +RMDEF void Vector2Scale(Vector2 *v, float scale) +{ + v->x *= scale; + v->y *= scale; +} + +// Negate vector +RMDEF void Vector2Negate(Vector2 *v) +{ + v->x = -v->x; + v->y = -v->y; +} + +// Divide vector by a float value +RMDEF void Vector2Divide(Vector2 *v, float div) +{ + *v = (Vector2){v->x/div, v->y/div}; +} + +// Normalize provided vector +RMDEF void Vector2Normalize(Vector2 *v) +{ + Vector2Divide(v, Vector2Lenght(*v)); +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Vector3 math //---------------------------------------------------------------------------------- +// Vector with components value 0.0f +RMDEF Vector3 VectorZero(void) { return (Vector3){ 0.0f, 0.0f, 0.0f }; } + +// Vector with components value 1.0f +RMDEF Vector3 VectorOne(void) { return (Vector3){ 1.0f, 1.0f, 1.0f }; } + // Add two vectors RMDEF Vector3 VectorAdd(Vector3 v1, Vector3 v2) { - Vector3 result; - - result.x = v1.x + v2.x; - result.y = v1.y + v2.y; - result.z = v1.z + v2.z; - - return result; + return (Vector3){ v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; } // Substract two vectors RMDEF Vector3 VectorSubtract(Vector3 v1, Vector3 v2) { - Vector3 result; - - result.x = v1.x - v2.x; - result.y = v1.y - v2.y; - result.z = v1.z - v2.z; - - return result; + return (Vector3){ v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; } // Calculate two vectors cross product @@ -233,7 +336,7 @@ RMDEF Vector3 VectorPerpendicular(Vector3 v) cardinalAxis = (Vector3){0.0f, 1.0f, 0.0f}; } - if(fabsf(v.z) < min) + if (fabsf(v.z) < min) { cardinalAxis = (Vector3){0.0f, 0.0f, 1.0f}; } @@ -243,24 +346,26 @@ RMDEF Vector3 VectorPerpendicular(Vector3 v) return result; } -// Calculate two vectors dot product -RMDEF float VectorDotProduct(Vector3 v1, Vector3 v2) -{ - float result; - - result = v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; - - return result; -} - // Calculate vector lenght RMDEF float VectorLength(const Vector3 v) { - float length; + return sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); +} - length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); +// Calculate two vectors dot product +RMDEF float VectorDotProduct(Vector3 v1, Vector3 v2) +{ + return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); +} - return length; +// Calculate distance between two vectors +RMDEF float VectorDistance(Vector3 v1, Vector3 v2) +{ + float dx = v2.x - v1.x; + float dy = v2.y - v1.y; + float dz = v2.z - v1.z; + + return sqrtf(dx*dx + dy*dy + dz*dz); } // Scale provided vector @@ -295,19 +400,18 @@ RMDEF void VectorNormalize(Vector3 *v) v->z *= ilength; } -// Calculate distance between two points -RMDEF float VectorDistance(Vector3 v1, Vector3 v2) +// Transforms a Vector3 by a given Matrix +// TODO: Review math (matrix transpose required?) +RMDEF void VectorTransform(Vector3 *v, Matrix mat) { - float result; + float x = v->x; + float y = v->y; + float z = v->z; - float dx = v2.x - v1.x; - float dy = v2.y - v1.y; - float dz = v2.z - v1.z; - - result = sqrtf(dx*dx + dy*dy + dz*dz); - - return result; -} + v->x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12; + v->y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13; + v->z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14; +}; // Calculate linear interpolation between two vectors RMDEF Vector3 VectorLerp(Vector3 v1, Vector3 v2, float amount) @@ -339,27 +443,6 @@ RMDEF Vector3 VectorReflect(Vector3 vector, Vector3 normal) return result; } -// Transforms a Vector3 by a given Matrix -// TODO: Review math (matrix transpose required?) -RMDEF void VectorTransform(Vector3 *v, Matrix mat) -{ - float x = v->x; - float y = v->y; - float z = v->z; - - v->x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12; - v->y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13; - v->z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14; -}; - -// Return a Vector3 init to zero -RMDEF Vector3 VectorZero(void) -{ - Vector3 zero = { 0.0f, 0.0f, 0.0f }; - - return zero; -} - // Return min value for each pair of components RMDEF Vector3 VectorMin(Vector3 vec1, Vector3 vec2) { @@ -386,7 +469,7 @@ RMDEF Vector3 VectorMax(Vector3 vec1, Vector3 vec2) // Compute barycenter coordinates (u, v, w) for point p with respect to triangle (a, b, c) // NOTE: Assumes P is on the plane of the triangle -RMDEF Vector3 Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) +RMDEF Vector3 VectorBarycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) { //Vector v0 = b - a, v1 = c - a, v2 = p - a; @@ -663,49 +746,6 @@ RMDEF Matrix MatrixRotate(Vector3 axis, float angle) return result; } -/* -// Another implementation for MatrixRotate... -RMDEF Matrix MatrixRotate(float angle, float x, float y, float z) -{ - Matrix result = MatrixIdentity(); - - float c = cosf(angle); // cosine - float s = sinf(angle); // sine - float c1 = 1.0f - c; // 1 - c - - float m0 = result.m0, m4 = result.m4, m8 = result.m8, m12 = result.m12, - m1 = result.m1, m5 = result.m5, m9 = result.m9, m13 = result.m13, - 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; - - // multiply rotation matrix - result.m0 = r0*m0 + r4*m1 + r8*m2; - result.m1 = r1*m0 + r5*m1 + r9*m2; - result.m2 = r2*m0 + r6*m1 + r10*m2; - result.m4 = r0*m4 + r4*m5 + r8*m6; - result.m5 = r1*m4 + r5*m5 + r9*m6; - result.m6 = r2*m4 + r6*m5 + r10*m6; - result.m8 = r0*m8 + r4*m9 + r8*m10; - result.m9 = r1*m8 + r5*m9 + r9*m10; - result.m10 = r2*m8 + r6*m9 + r10*m10; - result.m12 = r0*m12+ r4*m13 + r8*m14; - result.m13 = r1*m12+ r5*m13 + r9*m14; - result.m14 = r2*m12+ r6*m13 + r10*m14; - - return result; -} -*/ - // Returns x-rotation matrix (angle in radians) RMDEF Matrix MatrixRotateX(float angle) { diff --git a/raylib/rlgl.c b/raylib/rlgl.c index 0099862..b336571 100644 --- a/raylib/rlgl.c +++ b/raylib/rlgl.c @@ -2,10 +2,8 @@ * * rlgl - raylib OpenGL abstraction layer * -* DESCRIPTION: -* -* rlgl allows usage of OpenGL 1.1 style functions (rlVertex) that are internally mapped to -* selected OpenGL version (1.1, 2.1, 3.3 Core, ES 2.0). +* rlgl is a wrapper for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) to +* pseudo-OpenGL 1.1 style functions (rlVertex, rlTranslate, rlRotate...). * * When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal * VBO buffers (and VAOs if available). It requires calling 3 functions: @@ -16,32 +14,19 @@ * CONFIGURATION: * * #define GRAPHICS_API_OPENGL_11 -* Use OpenGL 1.1 backend -* * #define GRAPHICS_API_OPENGL_21 -* Use OpenGL 2.1 backend -* * #define GRAPHICS_API_OPENGL_33 -* Use OpenGL 3.3 Core profile backend -* * #define GRAPHICS_API_OPENGL_ES2 -* Use OpenGL ES 2.0 backend +* Use selected OpenGL backend * * #define RLGL_STANDALONE * Use rlgl as standalone library (no raylib dependency) * -* #define RLGL_NO_DISTORTION_SHADER -* Avoid stereo rendering distortion sahder (shader_distortion.h) inclusion +* #define SUPPORT_VR_SIMULATOR +* Support VR simulation functionality (stereo rendering) * -* #define SUPPORT_SHADER_DEFAULT / ENABLE_SHADER_DEFAULT -* -* #define SUPPORT_SHADER_DISTORTION -* -* #define SUPPORT_VR_SIMULATION -* -* #define SUPPORT_STEREO_RENDERING -* -* #define RLGL_NO_DEFAULT_SHADER +* #define SUPPORT_DISTORTION_SHADER +* Include stereo rendering distortion shader (shader_distortion.h) * * DEPENDENCIES: * raymath - 3D math functionality (Vector3, Matrix, Quaternion) @@ -50,7 +35,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -69,6 +54,12 @@ * **********************************************************************************************/ +// Default configuration flags (supported features) +//------------------------------------------------- +#define SUPPORT_VR_SIMULATOR +#define SUPPORT_DISTORTION_SHADER +//------------------------------------------------- + #include "rlgl.h" #include // Required for: fopen(), fclose(), fread()... [Used only on LoadText()] @@ -115,7 +106,7 @@ #include // Required for: va_list, va_start(), vfprintf(), va_end() [Used only on TraceLog()] #endif -#if !defined(GRAPHICS_API_OPENGL_11) && !defined(RLGL_NO_DISTORTION_SHADER) +#if !defined(GRAPHICS_API_OPENGL_11) && defined(SUPPORT_DISTORTION_SHADER) #include "shader_distortion.h" // Distortion shader to be embedded #endif @@ -231,6 +222,7 @@ typedef struct DrawCall { //Guint fboId; } DrawCall; +#if defined(SUPPORT_VR_SIMULATOR) // Head-Mounted-Display device parameters typedef struct VrDeviceInfo { int hResolution; // HMD horizontal resolution in pixels @@ -253,6 +245,7 @@ typedef struct VrStereoConfig { Matrix eyesProjection[2]; // VR stereo rendering eyes projection matrices Matrix eyesViewOffset[2]; // VR stereo rendering eyes view offset matrices } VrStereoConfig; +#endif //---------------------------------------------------------------------------------- // Global Variables Definition @@ -266,7 +259,7 @@ static Matrix projection; static Matrix *currentMatrix; static int currentMatrixMode; -static DrawMode currentDrawMode; +static int currentDrawMode; static float currentDepth = -1.0f; @@ -295,7 +288,17 @@ static bool texCompETC1Supported = false; // ETC1 texture compression support static bool texCompETC2Supported = false; // ETC2/EAC texture compression support static bool texCompPVRTSupported = false; // PVR texture compression support static bool texCompASTCSupported = false; // ASTC texture compression support -#endif + +#if defined(SUPPORT_VR_SIMULATOR) +// VR global variables +static VrDeviceInfo hmd; // Current VR device info +static VrStereoConfig vrConfig; // VR stereo configuration for simulator +static bool vrSimulatorReady = false; // VR simulator ready flag +static bool vrStereoRender = false; // VR stereo rendering enabled/disabled flag + // NOTE: This flag is useful to render data over stereo image (i.e. FPS) +#endif // defined(SUPPORT_VR_SIMULATOR) + +#endif // defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) // Extension supported flag: Anisotropic filtering static bool texAnisotropicFilterSupported = false; // Anisotropic texture filtering support @@ -304,13 +307,6 @@ static float maxAnisotropicLevel = 0.0f; // Maximum anisotropy level supp // Extension supported flag: Clamp mirror wrap mode static bool texClampMirrorSupported = false; // Clamp mirror wrap mode supported -// VR global variables -static VrDeviceInfo hmd; // Current VR device info -static VrStereoConfig vrConfig; // VR stereo configuration for simulator -static bool vrSimulatorReady = false; // VR simulator ready flag -static bool vrStereoRender = false; // VR stereo rendering enabled/disabled flag - // NOTE: This flag is useful to render data over stereo image (i.e. FPS) - #if defined(GRAPHICS_API_OPENGL_ES2) // NOTE: VAO functionality is exposed through extensions (OES) static PFNGLGENVERTEXARRAYSOESPROC glGenVertexArrays; @@ -348,13 +344,13 @@ static void UpdateDefaultBuffers(void); // Update default internal buffers ( static void DrawDefaultBuffers(void); // Draw default internal buffers vertex data static void UnloadDefaultBuffers(void); // Unload default internal buffers vertex data from CPU and GPU -// Configure stereo rendering (including distortion shader) with HMD device parameters -static void SetStereoConfig(VrDeviceInfo info); - -// Set internal projection and modelview matrix depending on eyes tracking data -static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); +#if defined(SUPPORT_VR_SIMULATOR) +static void SetStereoConfig(VrDeviceInfo info); // Configure stereo rendering (including distortion shader) with HMD device parameters +static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView); // Set internal projection and modelview matrix depending on eye #endif +#endif // defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) + #if defined(GRAPHICS_API_OPENGL_11) static int GenerateMipmaps(unsigned char *data, int baseWidth, int baseHeight); static Color *GenNextMipmap(Color *srcData, int srcWidth, int srcHeight); @@ -1335,7 +1331,7 @@ Vector3 rlglUnproject(Vector3 source, Matrix proj, Matrix view) } // Convert image data to OpenGL texture (returns OpenGL valid Id) -unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount) +unsigned int rlglLoadTexture(void *data, int width, int height, int format, int mipmapCount) { glBindTexture(GL_TEXTURE_2D, 0); // Free any old binding @@ -1343,39 +1339,39 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma // Check texture format support by OpenGL 1.1 (compressed textures not supported) #if defined(GRAPHICS_API_OPENGL_11) - if (textureFormat >= 8) + if (format >= COMPRESSED_DXT1_RGB) { TraceLog(WARNING, "OpenGL 1.1 does not support GPU compressed texture formats"); return id; } #endif - if ((!texCompDXTSupported) && ((textureFormat == COMPRESSED_DXT1_RGB) || (textureFormat == COMPRESSED_DXT1_RGBA) || - (textureFormat == COMPRESSED_DXT3_RGBA) || (textureFormat == COMPRESSED_DXT5_RGBA))) + if ((!texCompDXTSupported) && ((format == COMPRESSED_DXT1_RGB) || (format == COMPRESSED_DXT1_RGBA) || + (format == COMPRESSED_DXT3_RGBA) || (format == COMPRESSED_DXT5_RGBA))) { TraceLog(WARNING, "DXT compressed texture format not supported"); return id; } #if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) - if ((!texCompETC1Supported) && (textureFormat == COMPRESSED_ETC1_RGB)) + if ((!texCompETC1Supported) && (format == COMPRESSED_ETC1_RGB)) { TraceLog(WARNING, "ETC1 compressed texture format not supported"); return id; } - if ((!texCompETC2Supported) && ((textureFormat == COMPRESSED_ETC2_RGB) || (textureFormat == COMPRESSED_ETC2_EAC_RGBA))) + if ((!texCompETC2Supported) && ((format == COMPRESSED_ETC2_RGB) || (format == COMPRESSED_ETC2_EAC_RGBA))) { TraceLog(WARNING, "ETC2 compressed texture format not supported"); return id; } - if ((!texCompPVRTSupported) && ((textureFormat == COMPRESSED_PVRT_RGB) || (textureFormat == COMPRESSED_PVRT_RGBA))) + if ((!texCompPVRTSupported) && ((format == COMPRESSED_PVRT_RGB) || (format == COMPRESSED_PVRT_RGBA))) { TraceLog(WARNING, "PVRT compressed texture format not supported"); return id; } - if ((!texCompASTCSupported) && ((textureFormat == COMPRESSED_ASTC_4x4_RGBA) || (textureFormat == COMPRESSED_ASTC_8x8_RGBA))) + if ((!texCompASTCSupported) && ((format == COMPRESSED_ASTC_4x4_RGBA) || (format == COMPRESSED_ASTC_8x8_RGBA))) { TraceLog(WARNING, "ASTC compressed texture format not supported"); return id; @@ -1403,7 +1399,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma // GL_RGBA8 GL_RGBA GL_UNSIGNED_BYTE // GL_RGB8 GL_RGB GL_UNSIGNED_BYTE - switch (textureFormat) + switch (format) { case UNCOMPRESSED_GRAYSCALE: { @@ -1444,7 +1440,7 @@ unsigned int rlglLoadTexture(void *data, int width, int height, int textureForma } #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 (textureFormat) + switch (format) { case UNCOMPRESSED_GRAYSCALE: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (unsigned char *)data); break; case UNCOMPRESSED_GRAY_ALPHA: glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (unsigned char *)data); break; @@ -2077,12 +2073,16 @@ void rlglDrawMesh(Mesh mesh, Material material, Matrix transform) } int eyesCount = 1; +#if defined(SUPPORT_VR_SIMULATOR) if (vrStereoRender) eyesCount = 2; +#endif for (int eye = 0; eye < eyesCount; eye++) { - if (eyesCount == 2) SetStereoView(eye, matProjection, matModelView); - else modelview = matModelView; + if (eyesCount == 1) modelview = matModelView; + #if defined(SUPPORT_VR_SIMULATOR) + else SetStereoView(eye, matProjection, matModelView); + #endif // Calculate model-view-projection matrix (MVP) Matrix matMVP = MatrixMultiply(modelview, projection); // Transform to screen-space coordinates @@ -2250,7 +2250,7 @@ void *rlglReadTexturePixels(Texture2D texture) pixels = (unsigned char *)malloc(texture.width*texture.height*4*sizeof(unsigned char)); - // NOTE: Despite FBO color texture is RGB, we read data as RGBA... reading as RGB doesn't work... o__O + // NOTE: We read data as RGBA because FBO texture is configured as RGBA, despite binding a RGB texture... glReadPixels(0, 0, texture.width, texture.height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // Re-attach internal FBO color texture before deleting it @@ -2543,6 +2543,7 @@ void EndBlendMode(void) BeginBlendMode(BLEND_ALPHA); } +#if defined(SUPPORT_VR_SIMULATOR) // Init VR simulator for selected device // NOTE: It modifies the global variable: VrDeviceInfo hmd void InitVrSimulator(int vrDevice) @@ -2568,7 +2569,7 @@ void InitVrSimulator(int vrDevice) hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 - TraceLog(WARNING, "Initializing VR Simulator (Oculus Rift DK2)"); + TraceLog(INFO, "Initializing VR Simulator (Oculus Rift DK2)"); } else if ((vrDevice == HMD_DEFAULT_DEVICE) || (vrDevice == HMD_OCULUS_RIFT_CV1)) { @@ -2595,21 +2596,23 @@ void InitVrSimulator(int vrDevice) hmd.chromaAbCorrection[2] = 1.014f; // HMD chromatic aberration correction parameter 2 hmd.chromaAbCorrection[3] = 0.0f; // HMD chromatic aberration correction parameter 3 - TraceLog(WARNING, "Initializing VR Simulator (Oculus Rift CV1)"); + TraceLog(INFO, "Initializing VR Simulator (Oculus Rift CV1)"); } else { - TraceLog(WARNING, "VR Simulator doesn't support current device yet,"); + TraceLog(WARNING, "VR Simulator doesn't support selected device parameters,"); TraceLog(WARNING, "using default VR Simulator parameters"); } // Initialize framebuffer and textures for stereo rendering // NOTE: screen size should match HMD aspect ratio vrConfig.stereoFbo = rlglLoadRenderTexture(screenWidth, screenHeight); - + +#if defined(SUPPORT_DISTORTION_SHADER) // Load distortion shader (initialized by default with Oculus Rift CV1 parameters) vrConfig.distortionShader.id = LoadShaderProgram(vDistortionShaderStr, fDistortionShaderStr); if (vrConfig.distortionShader.id != 0) LoadDefaultShaderLocations(&vrConfig.distortionShader); +#endif SetStereoConfig(hmd); @@ -2628,7 +2631,9 @@ void CloseVrSimulator(void) if (vrSimulatorReady) { rlDeleteRenderTextures(vrConfig.stereoFbo); // Unload stereo framebuffer and texture + #if defined(SUPPORT_DISTORTION_SHADER) UnloadShader(vrConfig.distortionShader); // Unload distortion shader + #endif } #endif } @@ -2636,7 +2641,11 @@ void CloseVrSimulator(void) // Detect if VR simulator is running bool IsVrSimulatorReady(void) { +#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) return vrSimulatorReady; +#else + return false; +#endif } // Enable/Disable VR experience (device or simulator) @@ -2711,8 +2720,12 @@ void EndVrDrawing(void) rlMatrixMode(RL_MODELVIEW); // Enable internal modelview matrix rlLoadIdentity(); // Reset internal modelview matrix +#if defined(SUPPORT_DISTORTION_SHADER) // Draw RenderTexture (stereoFbo) using distortion shader currentShader = vrConfig.distortionShader; +#else + currentShader = GetDefaultShader(); +#endif rlEnableTexture(vrConfig.stereoFbo.texture.id); @@ -2758,6 +2771,7 @@ void EndVrDrawing(void) } #endif } +#endif // SUPPORT_VR_SIMULATOR //---------------------------------------------------------------------------------- // Module specific Functions Definition @@ -3303,11 +3317,15 @@ static void DrawDefaultBuffers() Matrix matModelView = modelview; int eyesCount = 1; +#if defined(SUPPORT_VR_SIMULATOR) if (vrStereoRender) eyesCount = 2; +#endif for (int eye = 0; eye < eyesCount; eye++) { + #if defined(SUPPORT_VR_SIMULATOR) if (eyesCount == 2) SetStereoView(eye, matProjection, matModelView); + #endif // Set current shader and upload current MVP matrix if ((lines.vCounter > 0) || (triangles.vCounter > 0) || (quads.vCounter > 0)) @@ -3513,6 +3531,7 @@ static void UnloadDefaultBuffers(void) free(quads.indices); } +#if defined(SUPPORT_VR_SIMULATOR) // Configure stereo rendering (including distortion shader) with HMD device parameters static void SetStereoConfig(VrDeviceInfo hmd) { @@ -3547,6 +3566,7 @@ static void SetStereoConfig(VrDeviceInfo hmd) TraceLog(DEBUG, "VR: Distortion Shader: Scale = { %f, %f }", scale[0], scale[1]); TraceLog(DEBUG, "VR: Distortion Shader: ScaleIn = { %f, %f }", scaleIn[0], scaleIn[1]); +#if defined(SUPPORT_DISTORTION_SHADER) // Update distortion shader with lens and distortion-scale parameters SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "leftLensCenter"), leftLensCenter, 2); SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "rightLensCenter"), rightLensCenter, 2); @@ -3557,6 +3577,7 @@ static void SetStereoConfig(VrDeviceInfo hmd) SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "scaleIn"), scaleIn, 2); SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "hmdWarpParam"), hmd.distortionK, 4); SetShaderValue(vrConfig.distortionShader, GetShaderLocation(vrConfig.distortionShader, "chromaAbParam"), hmd.chromaAbCorrection, 4); +#endif // Fovy is normally computed with: 2*atan2(hmd.vScreenSize, 2*hmd.eyeToScreenDistance)*RAD2DEG // ...but with lens distortion it is increased (see Oculus SDK Documentation) @@ -3602,6 +3623,8 @@ static void SetStereoView(int eye, Matrix matProjection, Matrix matModelView) SetMatrixModelview(eyeModelView); SetMatrixProjection(eyeProjection); } +#endif // defined(SUPPORT_VR_SIMULATOR) + #endif //defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2) #if defined(GRAPHICS_API_OPENGL_11) diff --git a/raylib/rlgl.h b/raylib/rlgl.h index 344da98..f3fd6b2 100644 --- a/raylib/rlgl.h +++ b/raylib/rlgl.h @@ -2,8 +2,8 @@ * * rlgl - raylib OpenGL abstraction layer * -* rlgl allows usage of OpenGL 1.1 style functions (rlVertex) that are internally mapped to -* selected OpenGL version (1.1, 2.1, 3.3 Core, ES 2.0). +* rlgl is a wrapper for multiple OpenGL versions (1.1, 2.1, 3.3 Core, ES 2.0) to +* pseudo-OpenGL 1.1 style functions (rlVertex, rlTranslate, rlRotate...). * * When chosing an OpenGL version greater than OpenGL 1.1, rlgl stores vertex data on internal * VBO buffers (and VAOs if available). It requires calling 3 functions: @@ -11,18 +11,29 @@ * rlglDraw() - Process internal buffers and send required draw calls * rlglClose() - De-initialize internal buffers data and other auxiliar resources * -* External libs: +* CONFIGURATION: +* +* #define GRAPHICS_API_OPENGL_11 +* #define GRAPHICS_API_OPENGL_21 +* #define GRAPHICS_API_OPENGL_33 +* #define GRAPHICS_API_OPENGL_ES2 +* Use selected OpenGL backend +* +* #define RLGL_STANDALONE +* Use rlgl as standalone library (no raylib dependency) +* +* #define SUPPORT_VR_SIMULATION / SUPPORT_STEREO_RENDERING +* Support VR simulation functionality (stereo rendering) +* +* #define SUPPORT_SHADER_DISTORTION +* Include stereo rendering distortion shader (shader_distortion.h) +* +* DEPENDENCIES: * raymath - 3D math functionality (Vector3, Matrix, Quaternion) * GLAD - OpenGL extensions loading (OpenGL 3.3 Core only) * -* Module Configuration Flags: -* GRAPHICS_API_OPENGL_11 - Use OpenGL 1.1 backend -* GRAPHICS_API_OPENGL_21 - Use OpenGL 2.1 backend -* GRAPHICS_API_OPENGL_33 - Use OpenGL 3.3 Core profile backend -* GRAPHICS_API_OPENGL_ES2 - Use OpenGL ES 2.0 backend -* -* RLGL_STANDALONE - Use rlgl as standalone library (no raylib dependency) * +* LICENSE: zlib/libpng * * Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) * @@ -124,15 +135,21 @@ #define RL_WRAP_CLAMP 0x812F // GL_CLAMP_TO_EDGE #define RL_WRAP_CLAMP_MIRROR 0x8742 // GL_MIRROR_CLAMP_EXT +// Matrix modes (equivalent to OpenGL) +#define RL_MODELVIEW 0x1700 // GL_MODELVIEW +#define RL_PROJECTION 0x1701 // GL_PROJECTION +#define RL_TEXTURE 0x1702 // GL_TEXTURE + +// Primitive assembly draw modes +#define RL_LINES 0x0001 // GL_LINES +#define RL_TRIANGLES 0x0004 // GL_TRIANGLES +#define RL_QUADS 0x0007 // GL_QUADS + //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- typedef enum { OPENGL_11 = 1, OPENGL_21, OPENGL_33, OPENGL_ES_20 } GlVersion; -typedef enum { RL_PROJECTION, RL_MODELVIEW, RL_TEXTURE } MatrixMode; - -typedef enum { RL_LINES, RL_TRIANGLES, RL_QUADS } DrawMode; - typedef unsigned char byte; #if defined(RLGL_STANDALONE) @@ -349,7 +366,7 @@ void rlglClose(void); // De-init rlgl void rlglDraw(void); // Draw VAO/VBO void rlglLoadExtensions(void *loader); // Load OpenGL extensions -unsigned int rlglLoadTexture(void *data, int width, int height, int textureFormat, int mipmapCount); // Load texture in GPU +unsigned int rlglLoadTexture(void *data, int width, int height, int format, int mipmapCount); // Load texture in GPU RenderTexture2D rlglLoadRenderTexture(int width, int height); // Load a texture to be used for rendering (fbo with color and depth attachments) void rlglUpdateTexture(unsigned int id, int width, int height, int format, const void *data); // Update GPU texture with new data void rlglGenerateMipmaps(Texture2D *texture); // Generate mipmap data for selected texture diff --git a/raylib/rres.h b/raylib/rres.h index 362da10..65ebdbb 100644 --- a/raylib/rres.h +++ b/raylib/rres.h @@ -1,8 +1,6 @@ /********************************************************************************************** * -* rres - raylib Resource custom format management functions -* -* Basic functions to load/save rRES resource files +* rres v1.0 - raylib resource (rRES) custom fileformat management functions * * CONFIGURATION: * diff --git a/raylib/shapes.c b/raylib/shapes.c index 5ed633f..2a92447 100644 --- a/raylib/shapes.c +++ b/raylib/shapes.c @@ -13,7 +13,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. diff --git a/raylib/text.c b/raylib/text.c index 18ebf48..cba9a7d 100644 --- a/raylib/text.c +++ b/raylib/text.c @@ -5,12 +5,11 @@ * CONFIGURATION: * * #define SUPPORT_FILEFORMAT_FNT -* #define SUPPORT_FILEFORMAT_TTF / INCLUDE_STB_TRUETYPE -* #define SUPPORT_FILEFORMAT_IMAGE_FONT +* #define SUPPORT_FILEFORMAT_TTF * Selected desired fileformats to be supported for loading. Some of those formats are * supported by default, to remove support, just comment unrequired #define in this module * -* #define INCLUDE_DEFAULT_FONT / SUPPORT_DEFAULT_FONT +* #define SUPPORT_DEFAULT_FONT * * DEPENDENCIES: * stb_truetype - Load TTF file and rasterize characters data @@ -18,7 +17,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -37,6 +36,13 @@ * **********************************************************************************************/ +// Default supported features +//------------------------------------- +#define SUPPORT_DEFAULT_FONT +#define SUPPORT_FILEFORMAT_FNT +#define SUPPORT_FILEFORMAT_TTF +//------------------------------------- + #include "raylib.h" #include // Required for: malloc(), free() @@ -44,12 +50,14 @@ #include // Required for: va_list, va_start(), vfprintf(), va_end() #include // Required for: FILE, fopen(), fclose(), fscanf(), feof(), rewind(), fgets() -#include "utils.h" // Required for: GetExtension() +#include "utils.h" // Required for: fopen() Android mapping -// Following libs are used on LoadTTF() -#define STBTT_STATIC // Define stb_truetype functions static to this module -#define STB_TRUETYPE_IMPLEMENTATION -#include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap() +#if defined(SUPPORT_FILEFORMAT_TTF) + // Following libs are used on LoadTTF() + #define STBTT_STATIC // Define stb_truetype functions static to this module + #define STB_TRUETYPE_IMPLEMENTATION + #include "external/stb_truetype.h" // Required for: stbtt_BakeFontBitmap() +#endif // Rectangle packing functions (not used at the moment) //#define STB_RECT_PACK_IMPLEMENTATION @@ -61,8 +69,6 @@ #define MAX_FORMATTEXT_LENGTH 64 #define MAX_SUBTEXT_LENGTH 64 -#define BIT_CHECK(a,b) ((a) & (1 << (b))) - //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- @@ -71,8 +77,10 @@ //---------------------------------------------------------------------------------- // Global variables //---------------------------------------------------------------------------------- +#if defined(SUPPORT_DEFAULT_FONT) static SpriteFont defaultFont; // Default font provided by raylib // NOTE: defaultFont is loaded on InitWindow and disposed on CloseWindow [module: core] +#endif //---------------------------------------------------------------------------------- // Other Modules Functions Declaration (required by text) @@ -85,18 +93,28 @@ static SpriteFont defaultFont; // Default font provided by raylib static int GetCharIndex(SpriteFont font, int letter); static SpriteFont LoadImageFont(Image image, Color key, int firstChar); // Load a Image font file (XNA style) -static SpriteFont LoadRBMF(const char *fileName); // Load a rBMF font file (raylib BitMap Font) +#if defined(SUPPORT_FILEFORMAT_FNT) static SpriteFont LoadBMFont(const char *fileName); // Load a BMFont file (AngelCode font file) +#endif +#if defined(SUPPORT_FILEFORMAT_TTF) static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, int *fontChars); // Load spritefont from TTF data +#endif +#if defined(SUPPORT_DEFAULT_FONT) extern void LoadDefaultFont(void); extern void UnloadDefaultFont(void); +#endif //---------------------------------------------------------------------------------- // Module Functions Definition //---------------------------------------------------------------------------------- +#if defined(SUPPORT_DEFAULT_FONT) + +// Load raylib default font extern void LoadDefaultFont(void) { + #define BIT_CHECK(a,b) ((a) & (1 << (b))) + // NOTE: Using UTF8 encoding table for Unicode U+0000..U+00FF Basic Latin + Latin-1 Supplement // http://www.utf8-chartable.de/unicode-utf8-table.pl @@ -241,16 +259,23 @@ extern void LoadDefaultFont(void) TraceLog(INFO, "[TEX ID %i] Default font loaded successfully", defaultFont.texture.id); } +// Unload raylib default font extern void UnloadDefaultFont(void) { UnloadTexture(defaultFont.texture); free(defaultFont.chars); } +#endif // SUPPORT_DEFAULT_FONT // Get the default font, useful to be used with extended parameters SpriteFont GetDefaultFont() { +#if defined(SUPPORT_DEFAULT_FONT) return defaultFont; +#else + SpriteFont font = { 0 }; + return font; +#endif } // Load SpriteFont from file into GPU memory (VRAM) @@ -264,10 +289,7 @@ SpriteFont LoadSpriteFont(const char *fileName) SpriteFont spriteFont = { 0 }; // Check file extension - if (strcmp(GetExtension(fileName),"rbmf") == 0) spriteFont = LoadRBMF(fileName); // TODO: DELETE... SOON... - else if (strcmp(GetExtension(fileName),"ttf") == 0) spriteFont = LoadSpriteFontTTF(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL); - else if (strcmp(GetExtension(fileName),"fnt") == 0) spriteFont = LoadBMFont(fileName); - else if (strcmp(GetExtension(fileName),"rres") == 0) + if (IsFileExtension(fileName, ".rres")) { // TODO: Read multiple resource blocks from file (RRES_FONT_IMAGE, RRES_FONT_CHARDATA) RRES rres = LoadResource(fileName, 0); @@ -293,6 +315,12 @@ SpriteFont LoadSpriteFont(const char *fileName) // TODO: Do not free rres.data memory (chars info data!) //UnloadResource(rres[0]); } +#if defined(SUPPORT_FILEFORMAT_TTF) + else if (IsFileExtension(fileName, ".ttf")) spriteFont = LoadSpriteFontEx(fileName, DEFAULT_TTF_FONTSIZE, 0, NULL); +#endif +#if defined(SUPPORT_FILEFORMAT_FNT) + else if (IsFileExtension(fileName, ".fnt")) spriteFont = LoadBMFont(fileName); +#endif else { Image image = LoadImage(fileName); @@ -313,11 +341,12 @@ SpriteFont LoadSpriteFont(const char *fileName) // Load SpriteFont from TTF font file with generation parameters // NOTE: You can pass an array with desired characters, those characters should be available in the font // if array is NULL, default char set is selected 32..126 -SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int charsCount, int *fontChars) +SpriteFont LoadSpriteFontEx(const char *fileName, int fontSize, int charsCount, int *fontChars) { SpriteFont spriteFont = { 0 }; - if (strcmp(GetExtension(fileName),"ttf") == 0) +#if defined(SUPPORT_FILEFORMAT_TTF) + if (IsFileExtension(fileName, ".ttf")) { if ((fontChars == NULL) || (charsCount == 0)) { @@ -331,6 +360,7 @@ SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int charsCount, } else spriteFont = LoadTTF(fileName, fontSize, charsCount, fontChars); } +#endif if (spriteFont.texture.id == 0) { @@ -345,7 +375,7 @@ SpriteFont LoadSpriteFontTTF(const char *fileName, int fontSize, int charsCount, void UnloadSpriteFont(SpriteFont spriteFont) { // NOTE: Make sure spriteFont is not default font (fallback) - if (spriteFont.texture.id != defaultFont.texture.id) + if (spriteFont.texture.id != GetDefaultFont().texture.id) { UnloadTexture(spriteFont.texture); free(spriteFont.chars); @@ -360,7 +390,7 @@ void UnloadSpriteFont(SpriteFont spriteFont) void DrawText(const char *text, int posX, int posY, int fontSize, Color color) { // Check if default font has been loaded - if (defaultFont.texture.id != 0) + if (GetDefaultFont().texture.id != 0) { Vector2 position = { (float)posX, (float)posY }; @@ -471,7 +501,7 @@ int MeasureText(const char *text, int fontSize) Vector2 vec = { 0.0f, 0.0f }; // Check if default font has been loaded - if (defaultFont.texture.id != 0) + if (GetDefaultFont().texture.id != 0) { int defaultFontSize = 10; // Default Font chars height in pixel if (fontSize < defaultFontSize) fontSize = defaultFontSize; @@ -688,144 +718,7 @@ static SpriteFont LoadImageFont(Image image, Color key, int firstChar) return spriteFont; } -// Load a rBMF font file (raylib BitMap Font) -static SpriteFont LoadRBMF(const char *fileName) -{ - // rBMF Info Header (16 bytes) - typedef struct { - char id[4]; // rBMF file identifier - char version; // rBMF file version - // 4 MSB --> main version - // 4 LSB --> subversion - char firstChar; // First character in the font - // NOTE: Depending on charDataType, it could be useless - short imgWidth; // Image width - always POT (power-of-two) - short imgHeight; // Image height - always POT (power-of-two) - short numChars; // Number of characters contained - short charHeight; // Characters height - the same for all characters - char compType; // Compression type: - // 4 MSB --> image data compression - // 4 LSB --> chars data compression - char charsDataType; // Char data type provided - } rbmfInfoHeader; - - SpriteFont spriteFont = { 0 }; - - // REMOVE SOON!!! -/* - rbmfInfoHeader rbmfHeader; - unsigned int *rbmfFileData = NULL; - unsigned char *rbmfCharWidthData = NULL; - - int charsDivisor = 1; // Every char is separated from the consecutive by a 1 pixel divisor, horizontally and vertically - - FILE *rbmfFile = fopen(fileName, "rb"); // Define a pointer to bitmap file and open it in read-binary mode - - if (rbmfFile == NULL) - { - TraceLog(WARNING, "[%s] rBMF font file could not be opened, using default font", fileName); - - spriteFont = GetDefaultFont(); - } - else - { - fread(&rbmfHeader, sizeof(rbmfInfoHeader), 1, rbmfFile); - - TraceLog(DEBUG, "[%s] Loading rBMF file, size: %ix%i, numChars: %i, charHeight: %i", fileName, rbmfHeader.imgWidth, rbmfHeader.imgHeight, rbmfHeader.numChars, rbmfHeader.charHeight); - - spriteFont.numChars = (int)rbmfHeader.numChars; - - int numPixelBits = rbmfHeader.imgWidth*rbmfHeader.imgHeight/32; - - rbmfFileData = (unsigned int *)malloc(numPixelBits*sizeof(unsigned int)); - - for (int i = 0; i < numPixelBits; i++) fread(&rbmfFileData[i], sizeof(unsigned int), 1, rbmfFile); - - rbmfCharWidthData = (unsigned char *)malloc(spriteFont.numChars*sizeof(unsigned char)); - - for (int i = 0; i < spriteFont.numChars; i++) fread(&rbmfCharWidthData[i], sizeof(unsigned char), 1, rbmfFile); - - // Re-construct image from rbmfFileData - //----------------------------------------- - Color *imagePixels = (Color *)malloc(rbmfHeader.imgWidth*rbmfHeader.imgHeight*sizeof(Color)); - - for (int i = 0; i < rbmfHeader.imgWidth*rbmfHeader.imgHeight; i++) imagePixels[i] = BLANK; // Initialize array - - int counter = 0; // Font data elements counter - - // Fill image data (convert from bit to pixel!) - for (int i = 0; i < rbmfHeader.imgWidth*rbmfHeader.imgHeight; i += 32) - { - for (int j = 31; j >= 0; j--) - { - if (BIT_CHECK(rbmfFileData[counter], j)) imagePixels[i+j] = WHITE; - } - - counter++; - } - - Image image = LoadImageEx(imagePixels, rbmfHeader.imgWidth, rbmfHeader.imgHeight); - ImageFormat(&image, UNCOMPRESSED_GRAY_ALPHA); - - free(imagePixels); - - TraceLog(DEBUG, "[%s] Image reconstructed correctly, now converting it to texture", fileName); - - // Create spritefont with all data read from rbmf file - spriteFont.texture = LoadTextureFromImage(image); - UnloadImage(image); // Unload image data - - //TraceLog(INFO, "[%s] Starting chars set reconstruction", fileName); - - // Get characters data using rbmfCharWidthData, rbmfHeader.charHeight, charsDivisor, rbmfHeader.numChars - spriteFont.chars = (CharInfo *)malloc(spriteFont.charsCount*sizeof(CharInfo)); - - int currentLine = 0; - int currentPosX = charsDivisor; - int testPosX = charsDivisor; - - for (int i = 0; i < spriteFont.charsCount; i++) - { - spriteFont.chars[i].value = (int)rbmfHeader.firstChar + i; - - spriteFont.chars[i].rec.x = currentPosX; - spriteFont.chars[i].rec.y = charsDivisor + currentLine*((int)rbmfHeader.charHeight + charsDivisor); - spriteFont.chars[i].rec.width = (int)rbmfCharWidthData[i]; - spriteFont.chars[i].rec.height = (int)rbmfHeader.charHeight; - - // NOTE: On image based fonts (XNA style), character offsets and xAdvance are not required (set to 0) - spriteFont.chars[i].offsetX = 0; - spriteFont.chars[i].offsetY = 0; - spriteFont.chars[i].advanceX = 0; - - testPosX += (spriteFont.chars[i].rec.width + charsDivisor); - - if (testPosX > spriteFont.texture.width) - { - currentLine++; - currentPosX = 2*charsDivisor + (int)rbmfCharWidthData[i]; - testPosX = currentPosX; - - spriteFont.chars[i].rec.x = charsDivisor; - spriteFont.chars[i].rec.y = charsDivisor + currentLine*(rbmfHeader.charHeight + charsDivisor); - } - else currentPosX = testPosX; - } - - spriteFont.baseSize = spriteFont.charRecs[0].height; - - TraceLog(INFO, "[%s] rBMF file loaded correctly as SpriteFont", fileName); - } - - fclose(rbmfFile); - - free(rbmfFileData); // Now we can free loaded data from RAM memory - free(rbmfCharWidthData); -*/ - - return spriteFont; -} - +#if defined(SUPPORT_FILEFORMAT_FNT) // Load a BMFont file (AngelCode font file) static SpriteFont LoadBMFont(const char *fileName) { @@ -943,7 +836,9 @@ static SpriteFont LoadBMFont(const char *fileName) return font; } +#endif +#if defined(SUPPORT_FILEFORMAT_TTF) // 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, int charsCount, int *fontChars) @@ -1035,4 +930,5 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, in free(charData); return font; -} \ No newline at end of file +} +#endif diff --git a/raylib/text.go b/raylib/text.go index a001097..5188a8a 100644 --- a/raylib/text.go +++ b/raylib/text.go @@ -68,7 +68,7 @@ func GetDefaultFont() SpriteFont { return v } -// LoadSpriteFont - Load a SpriteFont image into GPU memory +// LoadSpriteFont - Load a SpriteFont image into GPU memory (VRAM) func LoadSpriteFont(fileName string) SpriteFont { cfileName := C.CString(fileName) defer C.free(unsafe.Pointer(cfileName)) @@ -77,19 +77,19 @@ func LoadSpriteFont(fileName string) SpriteFont { return v } -// LoadSpriteFontTTF - Load a SpriteFont from TTF font with parameters -func LoadSpriteFontTTF(fileName string, fontSize int32, charsCount int32, fontChars *int32) SpriteFont { +// LoadSpriteFontEx - Load SpriteFont from file with extended parameters +func LoadSpriteFontEx(fileName string, fontSize int32, charsCount int32, fontChars *int32) SpriteFont { cfileName := C.CString(fileName) defer C.free(unsafe.Pointer(cfileName)) cfontSize := (C.int)(fontSize) ccharsCount := (C.int)(charsCount) cfontChars := (*C.int)(unsafe.Pointer(fontChars)) - ret := C.LoadSpriteFontTTF(cfileName, cfontSize, ccharsCount, cfontChars) + ret := C.LoadSpriteFontEx(cfileName, cfontSize, ccharsCount, cfontChars) v := NewSpriteFontFromPointer(unsafe.Pointer(&ret)) return v } -// UnloadSpriteFont - Unload SpriteFont from GPU memory +// UnloadSpriteFont - Unload SpriteFont from GPU memory (VRAM) func UnloadSpriteFont(spriteFont SpriteFont) { cspriteFont := spriteFont.cptr() C.UnloadSpriteFont(*cspriteFont) diff --git a/raylib/textures.c b/raylib/textures.c index 7db3bf5..6c56d6c 100644 --- a/raylib/textures.c +++ b/raylib/textures.c @@ -4,24 +4,24 @@ * * CONFIGURATION: * -* #define SUPPORT_STB_IMAGE / INCLUDE_STB_IMAGE -* -* #define SUPPORT_FILEFORMAT_BMP / SUPPORT_LOAD_BMP -* #define SUPPORT_FILEFORMAT_PNG / SUPPORT_LOAD_PNG +* #define SUPPORT_FILEFORMAT_BMP +* #define SUPPORT_FILEFORMAT_PNG * #define SUPPORT_FILEFORMAT_TGA -* #define SUPPORT_FILEFORMAT_JPG / ENABLE_LOAD_JPG +* #define SUPPORT_FILEFORMAT_JPG * #define SUPPORT_FILEFORMAT_GIF +* #define SUPPORT_FILEFORMAT_PSD * #define SUPPORT_FILEFORMAT_HDR -* #define SUPPORT_FILEFORMAT_DDS / ENABLE_LOAD_DDS +* #define SUPPORT_FILEFORMAT_DDS * #define SUPPORT_FILEFORMAT_PKM * #define SUPPORT_FILEFORMAT_KTX * #define SUPPORT_FILEFORMAT_PVR * #define SUPPORT_FILEFORMAT_ASTC -* Selected desired fileformats to be supported for loading. Some of those formats are +* Selecte desired fileformats to be supported for image data loading. Some of those formats are * supported by default, to remove support, just comment unrequired #define in this module * -* #define SUPPORT_IMAGE_RESIZE / INCLUDE_STB_IMAGE_RESIZE * #define SUPPORT_IMAGE_MANIPULATION +* Support multiple image editing functions to scale, adjust colors, flip, draw on images, crop... +* If not defined only three image editing functions supported: ImageFormat(), ImageAlphaMask(), ImageToPOT() * * DEPENDENCIES: * stb_image - Multiple image formats loading (JPEG, PNG, BMP, TGA, PSD, GIF, PIC) @@ -31,7 +31,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -50,6 +50,12 @@ * **********************************************************************************************/ +// Default configuration flags (supported features) +//------------------------------------------------- +#define SUPPORT_FILEFORMAT_PNG +#define SUPPORT_IMAGE_MANIPULATION +//------------------------------------------------- + #include "raylib.h" #include // Required for: malloc(), free() @@ -59,25 +65,48 @@ // Required for: rlglLoadTexture() rlDeleteTextures(), // rlglGenerateMipmaps(), some funcs for DrawTexturePro() -#include "utils.h" // Required for: fopen() Android mapping, TraceLog() +#include "utils.h" // Required for: fopen() Android mapping -// Support only desired texture formats, by default: JPEG, PNG, BMP, TGA -//#define STBI_NO_JPEG // Image format .jpg and .jpeg -//#define STBI_NO_PNG -//#define STBI_NO_BMP -//#define STBI_NO_TGA -#define STBI_NO_PSD -#define STBI_NO_GIF -#define STBI_NO_HDR +// Support only desired texture formats on stb_image +#if !defined(SUPPORT_FILEFORMAT_BMP) + #define STBI_NO_BMP +#endif +#if !defined(SUPPORT_FILEFORMAT_PNG) + #define STBI_NO_PNG +#endif +#if !defined(SUPPORT_FILEFORMAT_TGA) + #define STBI_NO_TGA +#endif +#if !defined(SUPPORT_FILEFORMAT_JPG) + #define STBI_NO_JPEG // Image format .jpg and .jpeg +#endif +#if !defined(SUPPORT_FILEFORMAT_PSD) + #define STBI_NO_PSD +#endif +#if !defined(SUPPORT_FILEFORMAT_GIF) + #define STBI_NO_GIF +#endif +#if !defined(SUPPORT_FILEFORMAT_HDR) + #define STBI_NO_HDR +#endif + +// Image fileformats not supported by default #define STBI_NO_PIC #define STBI_NO_PNM // Image format .ppm and .pgm -#define STB_IMAGE_IMPLEMENTATION -#include "external/stb_image.h" // Required for: stbi_load() - // NOTE: Used to read image data (multiple formats support) -#define STB_IMAGE_RESIZE_IMPLEMENTATION -#include "external/stb_image_resize.h" // Required for: stbir_resize_uint8() - // NOTE: Used for image scaling on ImageResize() +#if (defined(SUPPORT_FILEFORMAT_BMP) || defined(SUPPORT_FILEFORMAT_PNG) || defined(SUPPORT_FILEFORMAT_TGA) || \ + defined(SUPPORT_FILEFORMAT_JPG) || defined(SUPPORT_FILEFORMAT_PSD) || defined(SUPPORT_FILEFORMAT_GIF) || \ + defined(SUPPORT_FILEFORMAT_HDR)) + #define STB_IMAGE_IMPLEMENTATION + #include "external/stb_image.h" // Required for: stbi_load() + // NOTE: Used to read image data (multiple formats support) +#endif + +#if defined(SUPPORT_IMAGE_MANIPULATION) + #define STB_IMAGE_RESIZE_IMPLEMENTATION + #include "external/stb_image_resize.h" // Required for: stbir_resize_uint8() + // NOTE: Used for image scaling on ImageResize() +#endif //---------------------------------------------------------------------------------- // Defines and Macros @@ -102,11 +131,21 @@ //---------------------------------------------------------------------------------- // Module specific Functions Declaration //---------------------------------------------------------------------------------- +#if defined(SUPPORT_FILEFORMAT_DDS) static Image LoadDDS(const char *fileName); // Load DDS file +#endif +#if defined(SUPPORT_FILEFORMAT_PKM) static Image LoadPKM(const char *fileName); // Load PKM file +#endif +#if defined(SUPPORT_FILEFORMAT_KTX) static Image LoadKTX(const char *fileName); // Load KTX file +#endif +#if defined(SUPPORT_FILEFORMAT_PVR) static Image LoadPVR(const char *fileName); // Load PVR file +#endif +#if defined(SUPPORT_FILEFORMAT_ASTC) static Image LoadASTC(const char *fileName); // Load ASTC file +#endif //---------------------------------------------------------------------------------- // Module Functions Definition @@ -124,43 +163,7 @@ Image LoadImage(const char *fileName) image.mipmaps = 0; image.format = 0; - if ((strcmp(GetExtension(fileName),"png") == 0) || - (strcmp(GetExtension(fileName),"bmp") == 0) || - (strcmp(GetExtension(fileName),"tga") == 0) || - (strcmp(GetExtension(fileName),"jpg") == 0) -#ifndef STBI_NO_GIF - || (strcmp(GetExtension(fileName),"gif") == 0) -#endif -#ifndef STBI_NO_PSD - || (strcmp(GetExtension(fileName),"psd") == 0) -#endif -#ifndef STBI_NO_PIC - || (strcmp(GetExtension(fileName),"pic") == 0) -#endif - ) - { - int imgWidth = 0; - int imgHeight = 0; - int imgBpp = 0; - - // NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...) - image.data = stbi_load(fileName, &imgWidth, &imgHeight, &imgBpp, 0); - - image.width = imgWidth; - image.height = imgHeight; - image.mipmaps = 1; - - if (imgBpp == 1) image.format = UNCOMPRESSED_GRAYSCALE; - else if (imgBpp == 2) image.format = UNCOMPRESSED_GRAY_ALPHA; - else if (imgBpp == 3) image.format = UNCOMPRESSED_R8G8B8; - else if (imgBpp == 4) image.format = UNCOMPRESSED_R8G8B8A8; - } - else if (strcmp(GetExtension(fileName),"dds") == 0) image = LoadDDS(fileName); - else if (strcmp(GetExtension(fileName),"pkm") == 0) image = LoadPKM(fileName); - else if (strcmp(GetExtension(fileName),"ktx") == 0) image = LoadKTX(fileName); - else if (strcmp(GetExtension(fileName),"pvr") == 0) image = LoadPVR(fileName); - else if (strcmp(GetExtension(fileName),"astc") == 0) image = LoadASTC(fileName); - else if (strcmp(GetExtension(fileName),"rres") == 0) + if (IsFileExtension(fileName, ".rres")) { RRES rres = LoadResource(fileName, 0); @@ -171,6 +174,60 @@ Image LoadImage(const char *fileName) UnloadResource(rres); } + else if ((IsFileExtension(fileName, ".png")) +#if defined(SUPPORT_FILEFORMAT_BMP) + || (IsFileExtension(fileName, ".bmp")) +#endif +#if defined(SUPPORT_FILEFORMAT_TGA) + || (IsFileExtension(fileName, ".tga")) +#endif +#if defined(SUPPORT_FILEFORMAT_JPG) + || (IsFileExtension(fileName, ".jpg")) +#endif +#if defined(SUPPORT_FILEFORMAT_DDS) + || (IsFileExtension(fileName, ".gif")) +#endif +#if defined(SUPPORT_FILEFORMAT_PSD) + || (IsFileExtension(fileName, ".psd")) +#endif + ) + { + int imgWidth = 0; + int imgHeight = 0; + int imgBpp = 0; + + FILE *imFile = fopen(fileName, "rb"); + + // NOTE: Using stb_image to load images (Supports: BMP, TGA, PNG, JPG, ...) + image.data = stbi_load_from_file(imFile, &imgWidth, &imgHeight, &imgBpp, 0); + + fclose(imFile); + + image.width = imgWidth; + image.height = imgHeight; + image.mipmaps = 1; + + if (imgBpp == 1) image.format = UNCOMPRESSED_GRAYSCALE; + else if (imgBpp == 2) image.format = UNCOMPRESSED_GRAY_ALPHA; + else if (imgBpp == 3) image.format = UNCOMPRESSED_R8G8B8; + else if (imgBpp == 4) image.format = UNCOMPRESSED_R8G8B8A8; + } +#if defined(SUPPORT_FILEFORMAT_DDS) + else if (IsFileExtension(fileName, ".dds")) image = LoadDDS(fileName); +#endif +#if defined(SUPPORT_FILEFORMAT_PKM) + else if (IsFileExtension(fileName, ".pkm")) image = LoadPKM(fileName); +#endif +#if defined(SUPPORT_FILEFORMAT_KTX) + else if (IsFileExtension(fileName, ".ktx")) image = LoadKTX(fileName); +#endif +#if defined(SUPPORT_FILEFORMAT_PVR) + else if (IsFileExtension(fileName, ".pvr")) image = LoadPVR(fileName); +#endif +#if defined(SUPPORT_FILEFORMAT_ASTC) + else if (IsFileExtension(fileName, ".astc")) image = LoadASTC(fileName); +#endif + else TraceLog(WARNING, "[%s] Image fileformat not supported", fileName); if (image.data != NULL) TraceLog(INFO, "[%s] Image loaded successfully (%ix%i)", fileName, image.width, image.height); else TraceLog(WARNING, "[%s] Image could not be loaded", fileName); @@ -322,6 +379,8 @@ Texture2D LoadTextureFromImage(Image image) texture.height = image.height; texture.mipmaps = image.mipmaps; texture.format = image.format; + + TraceLog(INFO, "[TEX %i] Parameters: %ix%i, %i mips, format %i", texture.id, texture.width, texture.height, texture.mipmaps, texture.format); return texture; } @@ -463,12 +522,14 @@ Image GetTextureData(Texture2D texture) image.width = texture.width; image.height = texture.height; image.mipmaps = 1; -#if defined(GRAPHICS_API_OPENGL_ES2) - // NOTE: Data retrieved on OpenGL ES 2.0 comes as RGB (from framebuffer) - image.format = UNCOMPRESSED_R8G8B8A8; -#else - image.format = texture.format; -#endif + + if (rlGetVersion() == OPENGL_ES_20) + { + // NOTE: Data retrieved on OpenGL ES 2.0 comes as RGBA (from framebuffer) + image.format = UNCOMPRESSED_R8G8B8A8; + } + else image.format = texture.format; + TraceLog(INFO, "Texture pixel data obtained successfully"); } else TraceLog(WARNING, "Texture pixel data could not be obtained"); @@ -664,115 +725,6 @@ void ImageAlphaMask(Image *image, Image alphaMask) } } -// 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 >= COMPRESSED_DXT1_RGB) - { - 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 rError, gError, bError; - unsigned short rPixel, gPixel, bPixel, aPixel; // 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]; - - // NOTE: 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... - rError = (int)oldPixel.r - (int)(newPixel.r << (8 - rBpp)); - gError = (int)oldPixel.g - (int)(newPixel.g << (8 - gBpp)); - bError = (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)rError*7.0f/16), 0xff); - pixels[y*image->width + x+1].g = MIN((int)pixels[y*image->width + x+1].g + (int)((float)gError*7.0f/16), 0xff); - pixels[y*image->width + x+1].b = MIN((int)pixels[y*image->width + x+1].b + (int)((float)bError*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)rError*3.0f/16), 0xff); - pixels[(y+1)*image->width + x-1].g = MIN((int)pixels[(y+1)*image->width + x-1].g + (int)((float)gError*3.0f/16), 0xff); - pixels[(y+1)*image->width + x-1].b = MIN((int)pixels[(y+1)*image->width + x-1].b + (int)((float)bError*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)rError*5.0f/16), 0xff); - pixels[(y+1)*image->width + x].g = MIN((int)pixels[(y+1)*image->width + x].g + (int)((float)gError*5.0f/16), 0xff); - pixels[(y+1)*image->width + x].b = MIN((int)pixels[(y+1)*image->width + x].b + (int)((float)bError*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)rError*1.0f/16), 0xff); - pixels[(y+1)*image->width + x+1].g = MIN((int)pixels[(y+1)*image->width + x+1].g + (int)((float)gError*1.0f/16), 0xff); - pixels[(y+1)*image->width + x+1].b = MIN((int)pixels[(y+1)*image->width + x+1].b + (int)((float)bError*1.0f/16), 0xff); - } - - rPixel = (unsigned short)newPixel.r; - gPixel = (unsigned short)newPixel.g; - bPixel = (unsigned short)newPixel.b; - aPixel = (unsigned short)newPixel.a; - - ((unsigned short *)image->data)[y*image->width + x] = (rPixel << (gBpp + bBpp + aBpp)) | (gPixel << (bBpp + aBpp)) | (bPixel << aBpp) | aPixel; - } - } - - free(pixels); - } -} - // Convert image to POT (power-of-two) // NOTE: It could be useful on OpenGL ES 2.0 (RPI, HTML5) void ImageToPOT(Image *image, Color fillColor) @@ -818,6 +770,7 @@ void ImageToPOT(Image *image, Color fillColor) } } +#if defined(SUPPORT_IMAGE_MANIPULATION) // Copy an image to a new image Image ImageCopy(Image image) { @@ -1203,6 +1156,115 @@ void ImageFlipHorizontal(Image *image) image->data = processed.data; } +// 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 >= COMPRESSED_DXT1_RGB) + { + 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 rError, gError, bError; + unsigned short rPixel, gPixel, bPixel, aPixel; // 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]; + + // NOTE: 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... + rError = (int)oldPixel.r - (int)(newPixel.r << (8 - rBpp)); + gError = (int)oldPixel.g - (int)(newPixel.g << (8 - gBpp)); + bError = (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)rError*7.0f/16), 0xff); + pixels[y*image->width + x+1].g = MIN((int)pixels[y*image->width + x+1].g + (int)((float)gError*7.0f/16), 0xff); + pixels[y*image->width + x+1].b = MIN((int)pixels[y*image->width + x+1].b + (int)((float)bError*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)rError*3.0f/16), 0xff); + pixels[(y+1)*image->width + x-1].g = MIN((int)pixels[(y+1)*image->width + x-1].g + (int)((float)gError*3.0f/16), 0xff); + pixels[(y+1)*image->width + x-1].b = MIN((int)pixels[(y+1)*image->width + x-1].b + (int)((float)bError*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)rError*5.0f/16), 0xff); + pixels[(y+1)*image->width + x].g = MIN((int)pixels[(y+1)*image->width + x].g + (int)((float)gError*5.0f/16), 0xff); + pixels[(y+1)*image->width + x].b = MIN((int)pixels[(y+1)*image->width + x].b + (int)((float)bError*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)rError*1.0f/16), 0xff); + pixels[(y+1)*image->width + x+1].g = MIN((int)pixels[(y+1)*image->width + x+1].g + (int)((float)gError*1.0f/16), 0xff); + pixels[(y+1)*image->width + x+1].b = MIN((int)pixels[(y+1)*image->width + x+1].b + (int)((float)bError*1.0f/16), 0xff); + } + + rPixel = (unsigned short)newPixel.r; + gPixel = (unsigned short)newPixel.g; + bPixel = (unsigned short)newPixel.b; + aPixel = (unsigned short)newPixel.a; + + ((unsigned short *)image->data)[y*image->width + x] = (rPixel << (gBpp + bBpp + aBpp)) | (gPixel << (bBpp + aBpp)) | (bPixel << aBpp) | aPixel; + } + } + + free(pixels); + } +} + // Modify image color: tint void ImageColorTint(Image *image, Color color) { @@ -1359,6 +1421,7 @@ void ImageColorBrightness(Image *image, int brightness) image->data = processed.data; } +#endif // SUPPORT_IMAGE_MANIPULATION // Generate GPU mipmaps for a texture void GenTextureMipmaps(Texture2D *texture) @@ -1547,6 +1610,7 @@ void DrawTexturePro(Texture2D texture, Rectangle sourceRec, Rectangle destRec, V // Module specific Functions Definition //---------------------------------------------------------------------------------- +#if defined(SUPPORT_FILEFORMAT_DDS) // Loading DDS image data (compressed or uncompressed) static Image LoadDDS(const char *fileName) { @@ -1744,7 +1808,9 @@ static Image LoadDDS(const char *fileName) return image; } +#endif +#if defined(SUPPORT_FILEFORMAT_PKM) // Loading PKM image data (ETC1/ETC2 compression) // NOTE: KTX is the standard Khronos Group compression format (ETC1/ETC2, mipmaps) // PKM is a much simpler file format used mainly to contain a single ETC1/ETC2 compressed image (no mipmaps) @@ -1836,7 +1902,9 @@ static Image LoadPKM(const char *fileName) return image; } +#endif +#if defined(SUPPORT_FILEFORMAT_KTX) // Load KTX compressed image data (ETC1/ETC2 compression) static Image LoadKTX(const char *fileName) { @@ -1929,7 +1997,9 @@ static Image LoadKTX(const char *fileName) return image; } +#endif +#if defined(SUPPORT_FILEFORMAT_PVR) // Loading PVR image data (uncompressed or PVRT compression) // NOTE: PVR v2 not supported, use PVR v3 instead static Image LoadPVR(const char *fileName) @@ -2087,7 +2157,9 @@ static Image LoadPVR(const char *fileName) return image; } +#endif +#if defined(SUPPORT_FILEFORMAT_ASTC) // Load ASTC compressed image data (ASTC compression) static Image LoadASTC(const char *fileName) { @@ -2170,3 +2242,4 @@ static Image LoadASTC(const char *fileName) return image; } +#endif \ No newline at end of file diff --git a/raylib/utils.c b/raylib/utils.c index 9a2a723..c86c9c8 100644 --- a/raylib/utils.c +++ b/raylib/utils.c @@ -4,22 +4,28 @@ * * CONFIGURATION: * -* #define SUPPORT_SAVE_PNG -* Enable saving PNG fileformat +* #define SUPPORT_SAVE_PNG (defined by default) +* Support saving image data as PNG fileformat * NOTE: Requires stb_image_write library * * #define SUPPORT_SAVE_BMP +* Support saving image data as BMP fileformat +* NOTE: Requires stb_image_write library * -* #define DO_NOT_TRACE_DEBUG_MSGS -* Avoid showing DEBUG TraceLog() messages +* #define SUPPORT_TRACELOG +* Show TraceLog() output messages +* NOTE: By default DEBUG traces not shown +* +* #define SUPPORT_TRACELOG_DEBUG +* Show TraceLog() DEBUG messages * * DEPENDENCIES: -* stb_image_write - PNG writting functions +* stb_image_write - BMP/PNG writting functions * * * LICENSE: zlib/libpng * -* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) +* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -38,6 +44,9 @@ * **********************************************************************************************/ +#define SUPPORT_TRACELOG // Output tracelog messages +//#define SUPPORT_TRACELOG_DEBUG // Avoid DEBUG messages tracing + #include "utils.h" #if defined(PLATFORM_ANDROID) @@ -59,9 +68,6 @@ #define RRES_IMPLEMENTATION #include "rres.h" -//#define NO_TRACELOG // Avoid TraceLog() output (any type) -#define DO_NOT_TRACE_DEBUG_MSGS // Avoid DEBUG messages tracing - //---------------------------------------------------------------------------------- // Global Variables Definition //---------------------------------------------------------------------------------- @@ -82,15 +88,16 @@ static int android_close(void *cookie); //---------------------------------------------------------------------------------- // Module Functions Definition - Utilities //---------------------------------------------------------------------------------- -// Outputs a trace log message + +// Output trace log messages void TraceLog(int msgType, const char *text, ...) { -#if !defined(NO_TRACELOG) +#if defined(SUPPORT_TRACELOG) static char buffer[128]; - int traceDebugMsgs = 1; + int traceDebugMsgs = 0; -#ifdef DO_NOT_TRACE_DEBUG_MSGS - traceDebugMsgs = 0; +#if defined(SUPPORT_TRACELOG_DEBUG) + traceDebugMsgs = 1; #endif switch(msgType) @@ -125,22 +132,37 @@ void TraceLog(int msgType, const char *text, ...) if (msgType == ERROR) exit(1); // If ERROR message, exit program -#endif // NO_TRACELOG +#endif // SUPPORT_TRACELOG } #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) + +#if defined(SUPPORT_SAVE_BMP) // Creates a BMP image file from an array of pixel data void SaveBMP(const char *fileName, unsigned char *imgData, int width, int height, int compSize) { stbi_write_bmp(fileName, width, height, compSize, imgData); } +#endif +#if defined(SUPPORT_SAVE_PNG) // Creates a PNG image file from an array of pixel data void SavePNG(const char *fileName, unsigned char *imgData, int width, int height, int compSize) { stbi_write_png(fileName, width, height, compSize, imgData, width*compSize); } #endif +#endif + +// Keep track of memory allocated +// NOTE: mallocType defines the type of data allocated +/* +void RecordMalloc(int mallocType, int mallocSize, const char *msg) +{ + // TODO: Investigate how to record memory allocation data... + // Maybe creating my own malloc function... +} +*/ #if defined(PLATFORM_ANDROID) // Initialize asset manager from android app @@ -162,24 +184,6 @@ FILE *android_fopen(const char *fileName, const char *mode) } #endif -// Keep track of memory allocated -// NOTE: mallocType defines the type of data allocated -/* -void RecordMalloc(int mallocType, int mallocSize, const char *msg) -{ - // TODO: Investigate how to record memory allocation data... - // Maybe creating my own malloc function... -} -*/ - -// Get the extension for a filename -const char *GetExtension(const char *fileName) -{ - const char *dot = strrchr(fileName, '.'); - if (!dot || dot == fileName) return ""; - return (dot + 1); -} - //---------------------------------------------------------------------------------- // Module specific Functions Definition //---------------------------------------------------------------------------------- diff --git a/raylib/utils.go b/raylib/utils.go index c7e901d..761351b 100644 --- a/raylib/utils.go +++ b/raylib/utils.go @@ -10,8 +10,8 @@ import ( // Log message types const ( LogInfo = iota - LogError LogWarning + LogError LogDebug ) @@ -22,16 +22,16 @@ func SetDebug(enabled bool) { traceDebugMsgs = enabled } -// TraceLog - Trace log messages showing (INFO, WARNING, ERROR, DEBUG) +// TraceLog - Show trace log messages (INFO, WARNING, ERROR, DEBUG) func TraceLog(msgType int, text string, v ...interface{}) { switch msgType { case LogInfo: fmt.Printf("INFO: "+text+"\n", v...) + case LogWarning: + fmt.Printf("WARNING: "+text+"\n", v...) case LogError: fmt.Printf("ERROR: "+text+"\n", v...) os.Exit(1) - case LogWarning: - fmt.Printf("WARNING: "+text+"\n", v...) case LogDebug: if traceDebugMsgs { fmt.Printf("DEBUG: "+text+"\n", v...) diff --git a/raylib/utils.h b/raylib/utils.h index 3ffd025..64592c7 100644 --- a/raylib/utils.h +++ b/raylib/utils.h @@ -1,10 +1,11 @@ /********************************************************************************************** * -* raylib.utils +* raylib.utils - Some common utility functions * -* Some utility functions * -* Copyright (c) 2014-2016 Ramon Santamaria (@raysan5) +* LICENSE: zlib/libpng +* +* Copyright (c) 2014-2017 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -33,6 +34,8 @@ #include "rres.h" +#define SUPPORT_SAVE_PNG + //---------------------------------------------------------------------------------- // Some basic Defines //---------------------------------------------------------------------------------- @@ -43,8 +46,6 @@ //---------------------------------------------------------------------------------- // Types and Structures Definition //---------------------------------------------------------------------------------- -typedef enum { INFO = 0, ERROR, WARNING, DEBUG, OTHER } TraceLogType; - #ifdef __cplusplus extern "C" { // Prevents name mangling of functions #endif @@ -57,17 +58,18 @@ extern "C" { // Prevents name mangling of functions //---------------------------------------------------------------------------------- // Module Functions Declaration //---------------------------------------------------------------------------------- -void TraceLog(int msgType, const char *text, ...); // Outputs a trace log message -const char *GetExtension(const char *fileName); // Returns extension of a filename - #if defined(PLATFORM_DESKTOP) || defined(PLATFORM_RPI) +#if defined(SUPPORT_SAVE_BMP) void SaveBMP(const char *fileName, unsigned char *imgData, int width, int height, int compSize); +#endif +#if defined(SUPPORT_SAVE_PNG) void SavePNG(const char *fileName, unsigned char *imgData, int width, int height, int compSize); #endif +#endif #if defined(PLATFORM_ANDROID) void InitAssetManager(AAssetManager *manager); // Initialize asset manager from android app -FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen() +FILE *android_fopen(const char *fileName, const char *mode); // Replacement for fopen() #endif #ifdef __cplusplus