Update C sources and examples
58
examples/core/vr_simulator/main.go
Normal file
|
@ -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()
|
||||
}
|
BIN
examples/shaders/shapes_textures/fudesumi.png
Normal file
After Width: | Height: | Size: 218 KiB |
|
@ -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.UnloadTexture(fudesumi) // Unload texture
|
||||
|
||||
raylib.CloseWindow() // Close window and OpenGL context
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 114 KiB |
36
examples/shapes/lines_bezier/main.go
Normal file
|
@ -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()
|
||||
}
|
|
@ -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()
|
||||
}
|
BIN
examples/text/raylib_fonts/fonts/alagard.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
examples/text/raylib_fonts/fonts/alpha_beta.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
examples/text/raylib_fonts/fonts/jupiter_crash.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
examples/text/raylib_fonts/fonts/mecha.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
examples/text/raylib_fonts/fonts/pixantiqua.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
examples/text/raylib_fonts/fonts/pixelplay.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
examples/text/raylib_fonts/fonts/romulus.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
examples/text/raylib_fonts/fonts/setback.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
|
@ -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])
|
||||
}
|
||||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
Before Width: | Height: | Size: 114 KiB |
|
@ -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)
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
@ -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,17 +46,17 @@ 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(fudesumi) // Texture unloading
|
||||
raylib.UnloadTexture(checked) // Texture unloading
|
||||
|
||||
raylib.CloseWindow()
|
||||
|
|
BIN
examples/textures/raw_data/texture_formats/fudesumi.raw
Normal file
Before Width: | Height: | Size: 83 KiB |
|
@ -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()
|
||||
}
|
||||
|
|
BIN
examples/textures/rectangle/scarfy.png
Normal file
After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 83 KiB |
|
@ -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()
|
||||
}
|
||||
|
|
BIN
examples/textures/srcrec_dstrec/scarfy.png
Normal file
After Width: | Height: | Size: 32 KiB |
151
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 <stdarg.h> // 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 <string.h> // Required for: strcmp(), strncmp()
|
||||
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fread()
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_OGG)
|
||||
//#define STB_VORBIS_HEADER_ONLY
|
||||
#include "external/stb_vorbis.h" // OGG loading functions
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_XM)
|
||||
#define JAR_XM_IMPLEMENTATION
|
||||
#include "external/jar_xm.h" // XM loading functions
|
||||
#endif
|
||||
|
||||
#if defined(SUPPORT_FILEFORMAT_MOD)
|
||||
#define JAR_MOD_IMPLEMENTATION
|
||||
#include "external/jar_mod.h" // MOD loading functions
|
||||
#endif
|
||||
|
||||
#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)
|
||||
|
|
|
@ -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.
|
||||
|
@ -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
|
||||
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
|
||||
|
|
|
@ -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.
|
||||
|
|
195
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
|
||||
|
||||
#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 <stdint.h> // Required for: typedef unsigned long long int uint64_t, used by hi-res timer
|
||||
#include <time.h> // Required for: time() - Android/RPI hi-res timer (NOTE: Linux only!)
|
||||
#include <math.h> // Required for: tan() [Used in Begin3dMode() to set perspective]
|
||||
#include <string.h> // Required for: strcmp()
|
||||
#include <string.h> // Required for: strrchr(), strcmp()
|
||||
//#include <errno.h> // Macros for reporting and retrieving error conditions through error codes
|
||||
|
||||
#if defined __linux || defined(PLATFORM_WEB)
|
||||
#if defined __linux__ || defined(PLATFORM_WEB)
|
||||
#include <sys/time.h> // Required for: timespec, nanosleep(), select() - POSIX
|
||||
#elif defined __APPLE__
|
||||
#include <unistd.h> // Required for: usleep()
|
||||
|
@ -96,7 +115,7 @@
|
|||
//#define GLFW_INCLUDE_NONE // Disable the standard OpenGL header inclusion on GLFW3
|
||||
#include <GLFW/glfw3.h> // 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 <GLFW/glfw3native.h> // 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();
|
||||
|
@ -379,15 +398,21 @@ void InitWindow(int width, int height, const char *title)
|
|||
#if defined(PLATFORM_WEB)
|
||||
emscripten_set_fullscreenchange_callback(0, 0, 1, EmscriptenFullscreenChangeCallback);
|
||||
|
||||
// NOTE: Some code examples
|
||||
// Support keyboard events
|
||||
emscripten_set_keypress_callback("#canvas", NULL, 1, EmscriptenKeyboardCallback);
|
||||
|
||||
// Support mouse events
|
||||
emscripten_set_click_callback("#canvas", NULL, 1, EmscriptenMouseCallback);
|
||||
|
||||
// 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++)
|
||||
|
|
|
@ -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)
|
||||
|
|
545
raylib/external/stb_image.h
vendored
|
@ -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,110 +42,14 @@
|
|||
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
|
||||
|
@ -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 <stdio.h>
|
||||
#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");
|
||||
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,12 +3608,61 @@ 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];
|
||||
out[3] = 255; // not used if n==3
|
||||
out += n;
|
||||
}
|
||||
} else {
|
||||
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)
|
||||
|
@ -3689,10 +3671,11 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
|
|||
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];
|
||||
|
@ -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 );
|
||||
|
@ -6646,9 +6654,9 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
|
|||
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,9 +6846,13 @@ 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;
|
||||
|
||||
if (!x) x = &dummy;
|
||||
if (!y) y = &dummy;
|
||||
if (!comp) comp = &dummy;
|
||||
|
||||
stbi__rewind(s);
|
||||
|
||||
// Get identifier
|
||||
|
@ -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.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
194
raylib/external/stb_image_resize.h
vendored
|
@ -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
|
||||
|
@ -534,9 +534,10 @@ typedef struct
|
|||
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_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);
|
||||
}
|
||||
|
||||
|
@ -1716,18 +1715,22 @@ 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)
|
||||
{
|
||||
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.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
61
raylib/external/stb_image_write.h
vendored
|
@ -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.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
70
raylib/external/stb_rect_pack.h
vendored
|
@ -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.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
65
raylib/external/stb_truetype.h
vendored
|
@ -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.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
92
raylib/external/stb_vorbis.c
vendored
|
@ -166,12 +166,14 @@
|
|||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh))
|
||||
|
||||
// find definition of alloca if it's not in stdlib.h:
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__)
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
#endif
|
||||
#else // STB_VORBIS_NO_CRT
|
||||
#define NULL 0
|
||||
#define malloc(s) 0
|
||||
|
@ -597,6 +599,8 @@ 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 ];
|
||||
|
@ -606,8 +610,7 @@ static int ilog(int32 n)
|
|||
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 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);
|
||||
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.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
|
12
raylib/external/stb_vorbis.h
vendored
|
@ -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);
|
||||
|
|
|
@ -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 <sys/time.h> // Required for: timespec
|
||||
#include <time.h> // 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);
|
||||
|
|
220
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
|
||||
|
|
108
raylib/raylib.h
|
@ -1,24 +1,24 @@
|
|||
/**********************************************************************************************
|
||||
*
|
||||
* 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)
|
||||
|
@ -29,6 +29,9 @@
|
|||
* 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]
|
||||
* 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]
|
||||
|
@ -36,8 +39,7 @@
|
|||
* 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]
|
||||
* 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)
|
||||
|
||||
|
|
258
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,26 +112,48 @@ 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 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 VectorDotProduct(Vector3 v1, Vector3 v2); // Calculate two vectors dot product
|
||||
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 float VectorDistance(Vector3 v1, Vector3 v2); // Calculate distance between two points
|
||||
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 VectorBarycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c); // Barycenter coords for p in triangle abc
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
// Functions Declaration to work with Matrix
|
||||
|
@ -179,32 +201,113 @@ RMDEF void QuaternionTransform(Quaternion *q, Matrix mat); // Transfo
|
|||
|
||||
#include <math.h> // 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
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
131
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 <stdio.h> // Required for: fopen(), fclose(), fread()... [Used only on LoadText()]
|
||||
|
@ -115,7 +106,7 @@
|
|||
#include <stdarg.h> // 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,11 +2596,11 @@ 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");
|
||||
}
|
||||
|
||||
|
@ -2607,9 +2608,11 @@ void InitVrSimulator(int vrDevice)
|
|||
// 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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
*
|
||||
|
|
|
@ -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.
|
||||
|
|
206
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 <stdlib.h> // Required for: malloc(), free()
|
||||
|
@ -44,12 +50,14 @@
|
|||
#include <stdarg.h> // Required for: va_list, va_start(), vfprintf(), va_end()
|
||||
#include <stdio.h> // Required for: FILE, fopen(), fclose(), fscanf(), feof(), rewind(), fgets()
|
||||
|
||||
#include "utils.h" // Required for: GetExtension()
|
||||
#include "utils.h" // Required for: fopen() Android mapping
|
||||
|
||||
#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)
|
||||
|
@ -1036,3 +931,4 @@ static SpriteFont LoadTTF(const char *fileName, int fontSize, int charsCount, in
|
|||
|
||||
return font;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 <stdlib.h> // 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
|
||||
// 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
|
||||
|
||||
#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);
|
||||
|
@ -323,6 +380,8 @@ Texture2D LoadTextureFromImage(Image image)
|
|||
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)
|
||||
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
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
|
|
@ -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
|
||||
//----------------------------------------------------------------------------------
|
||||
|
|
|
@ -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...)
|
||||
|
|
|
@ -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,13 +58,14 @@ 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
|
||||
|
|