raylib-go
raylib-go copied to clipboard
Accessing OpenGL methods from within raylib-go
Is it possible to access OpenGL methods from within raylib-go
? I'm trying to port some c camera code (rlFPCamera.c) and I need access to methods like rlDrawRenderBatchActive
, rlMatrixMode
, rlPushMatrix
, and rlLoadIdentity
.
This is a duplicate of https://github.com/gen2brain/raylib-go/issues/171. If someone actually adds support I may reconsider.
I'm trying to add some basic support but I'm kind of stuck on why my code isn't working. For reference I ported all of the correct functions in this commit https://github.com/Technerder/raylib-go/commit/f565649967231ee4fa0162dbd6e8058605475b46 but my test code doesn't actually seem to be working. As far as I can tell I directly ported the code almost line by line from https://github.com/raylib-extras/extras-c/tree/main/cameras/rlFPCamera, but when I try to run the example code, the game window is initialized and displays the 2D elements like the FPS counter and XYZ coordinates but I don't see the example plane grid rendering at all. Would you be able to help me understand what it is that I'm doing wrong?
Reference Testing Code:
main.go
package main
import (
"fmt"
"github.com/gen2brain/raylib-go/raylib"
)
type Game struct {
ShouldRun bool
Camera *FirstPersonCamera
ScreenWidth int
ScreenHeight int
}
func (game *Game) HandleInput() {
if rl.IsKeyDown(rl.KeyEscape) {
game.ShouldRun = false
}
if rl.IsKeyPressed(rl.KeyF) {
rl.ToggleFullscreen()
}
}
func (game *Game) Render3D() {
game.Camera.Update()
rl.BeginDrawing()
game.Camera.BeginMode3D()
rl.ClearBackground(rl.RayWhite)
rl.DrawGrid(50, 1)
game.Camera.EndMode3D()
rl.EndDrawing()
}
func (game *Game) Render2D() {
rl.BeginDrawing()
rl.DrawFPS(5, 0)
rl.DrawText(fmt.Sprintf("X: %v", game.Camera.CameraPosition.X), 5, 20, 20, rl.Lime)
rl.DrawText(fmt.Sprintf("Y: %v", game.Camera.CameraPosition.Y), 5, 40, 20, rl.Lime)
rl.DrawText(fmt.Sprintf("Z: %v", game.Camera.CameraPosition.Z), 5, 60, 20, rl.Lime)
rl.EndDrawing()
}
func (game *Game) Init() {
rl.SetConfigFlags(rl.FlagFullscreenMode | rl.FlagVsyncHint)
rl.SetTraceLog(rl.LogNone)
rl.InitWindow(int32(rl.GetScreenWidth()), int32(rl.GetScreenHeight()), "Test")
rl.SetTargetFPS(144)
game.Camera = &FirstPersonCamera{}
game.Camera.Init(45, rl.NewVector3(0, 2, 0))
game.Camera.MoveSpeed.Z = 10
game.Camera.MoveSpeed.X = 5
game.Camera.FarPlane = 5000
game.Camera.AllowFlight = true
rl.SetMouseScale(0.5, 0.5)
rl.SetCameraMoveControls(rl.KeyW, rl.KeyS, rl.KeyD, rl.KeyA, rl.KeySpace, rl.KeyLeftShift)
}
func (game *Game) Start() {
game.ShouldRun = true
for !rl.WindowShouldClose() && game.ShouldRun {
game.HandleInput()
game.Render3D()
game.Render2D()
}
rl.CloseWindow()
}
func main() {
var game Game
game.Init()
game.Start()
}
first_person_camera.go
package main
import "C"
import (
rl "github.com/gen2brain/raylib-go/raylib"
"math"
)
type FirstPersonCameraControls int64
const (
MOVE_FRONT FirstPersonCameraControls = iota
MOVE_BACK
MOVE_RIGHT
MOVE_LEFT
MOVE_UP
MOVE_DOWN
TURN_LEFT
TURN_RIGHT
TURN_UP
TURN_DOWN
SPRINT
LAST_CONTROL
)
type FirstPersonCamera struct {
ControlKeys []int32
MoveSpeed rl.Vector3
TurnSpeed rl.Vector2
UseMouse bool
MouseSensitivity float32
MinimumViewY float32
MaximumViewY float32
ViewBobbleFreq float32
ViewBobbleMagnitude float32
ViewBobbleWaverMagnitude float32
CameraPosition rl.Vector3
PlayerEyesPosition float32
FOV rl.Vector2
TargetDistance float32
ViewAngles rl.Vector2
CurrentBobble float32
Focused bool
AllowFlight bool
ViewCamera rl.Camera3D
Forward rl.Vector3
Right rl.Vector3
NearPlane float32
FarPlane float32
}
func (camera *FirstPersonCamera) Init(fovY float32, position rl.Vector3) {
camera.ControlKeys = make([]int32, LAST_CONTROL)
camera.ControlKeys[0] = 'W'
camera.ControlKeys[1] = 'S'
camera.ControlKeys[2] = 'D'
camera.ControlKeys[3] = 'A'
camera.ControlKeys[4] = 'E'
camera.ControlKeys[5] = 'Q'
camera.ControlKeys[6] = rl.KeyLeft
camera.ControlKeys[7] = rl.KeyRight
camera.ControlKeys[8] = rl.KeyUp
camera.ControlKeys[9] = rl.KeyDown
camera.ControlKeys[10] = rl.KeyLeftShift
camera.MoveSpeed = rl.NewVector3(1, 1, 1)
camera.TurnSpeed = rl.NewVector2(90, 90)
camera.UseMouse = true
camera.MouseSensitivity = 600
camera.MinimumViewY = -89.0
camera.MaximumViewY = 89.0
camera.ViewBobbleFreq = 0.0
camera.ViewBobbleMagnitude = 0.02
camera.ViewBobbleWaverMagnitude = 0.002
camera.CurrentBobble = 0
camera.Focused = rl.IsWindowFocused()
camera.TargetDistance = 1
camera.PlayerEyesPosition = 0.5
camera.ViewAngles = rl.NewVector2(0, 0)
camera.CameraPosition = position
camera.FOV.Y = fovY
camera.ViewCamera.Position = position
camera.ViewCamera.Position.Y += camera.PlayerEyesPosition
camera.ViewCamera.Target = rl.Vector3Add(camera.ViewCamera.Position, rl.NewVector3(0, 0, camera.TargetDistance))
camera.ViewCamera.Up = rl.NewVector3(0.0, 1.0, 0.0)
camera.ViewCamera.Fovy = fovY
camera.ViewCamera.Projection = rl.CameraPerspective
camera.AllowFlight = true
camera.NearPlane = 0.01
camera.FarPlane = 1000.0
camera.ResizeView()
camera.SetUseMouse(camera.UseMouse)
}
func (camera *FirstPersonCamera) ResizeView() {
width := float32(rl.GetScreenWidth())
height := float32(rl.GetScreenHeight())
if height != 0 {
camera.FOV.X = camera.FOV.Y * (width / height)
}
}
func (camera *FirstPersonCamera) SetUseMouse(useMouse bool) {
camera.UseMouse = useMouse
if useMouse && rl.IsWindowFocused() {
rl.DisableCursor()
} else {
rl.EnableCursor()
}
}
func (camera *FirstPersonCamera) GetPosition() rl.Vector3 {
return camera.CameraPosition
}
func (camera *FirstPersonCamera) SetPosition(pos rl.Vector3) {
camera.CameraPosition = pos
forward := rl.Vector3Subtract(camera.ViewCamera.Target, camera.ViewCamera.Position)
camera.ViewCamera.Position = camera.CameraPosition
camera.ViewCamera.Target = rl.Vector3Add(camera.CameraPosition, forward)
}
func (camera *FirstPersonCamera) GetViewRay() rl.Ray {
return rl.NewRay(camera.CameraPosition, camera.Forward)
}
func (camera *FirstPersonCamera) BeginMode3D() {
aspect := float32(rl.GetScreenWidth()) / float32(rl.GetScreenHeight())
camera.SetupCamera(aspect)
}
func (camera *FirstPersonCamera) EndMode3D() {
rl.EndMode3D()
}
func (camera *FirstPersonCamera) SetupCamera(aspect float32) {
rl.DrawRenderBatchActive() // rlDrawRenderBatchActive(); // Draw Buffers (Only OpenGL 3+ and ES2)
rl.MatrixMode(rl.RL_PROJECTION) // rlMatrixMode(RL_PROJECTION); // Switch to projection matrix
rl.PushMatrix() // rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection
rl.LoadIdentity() // rlLoadIdentity(); // Reset current matrix (projection)
if camera.ViewCamera.Projection == rl.CameraPerspective {
// Setup perspective projection
top := float32(rl.RL_CULL_DISTANCE_NEAR * math.Tan(float64(camera.ViewCamera.Fovy*0.5*rl.Deg2rad))) //double top = RL_CULL_DISTANCE_NEAR * tan(camera->ViewCamera.fovy * 0.5 * DEG2RAD);
right := top * aspect //double right = top * aspect;
rl.Frustum(-right, right, -top, top, camera.NearPlane, camera.FarPlane) //rlFrustum(-right, right, -top, top, camera->NearPlane, camera->FarPlane);
} else if camera.ViewCamera.Projection == rl.CameraOrthographic {
// Setup orthographic projection
top := camera.ViewCamera.Fovy //double top = camera->ViewCamera.fovy / 2.0;
right := top * aspect //double right = top * aspect;
rl.Ortho(-right, right, -top, top, camera.NearPlane, camera.FarPlane) //rlOrtho(-right, right, -top, top, camera->NearPlane, camera->FarPlane);
}
rl.MatrixMode(rl.RL_MODELVIEW) //rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix
rl.LoadIdentity() //rlLoadIdentity(); // Reset current matrix (modelview)
matView := rl.MatrixLookAt(camera.ViewCamera.Position, camera.ViewCamera.Target, camera.ViewCamera.Up) //Matrix matView = MatrixLookAt(camera->ViewCamera.position, camera->ViewCamera.target, camera->ViewCamera.up);
rl.MultMatrixf(rl.MatrixToFloatV(matView).V) //rlMultMatrixf(MatrixToFloatV(matView).v); // Multiply modelview matrix by view matrix (camera)
rl.EnableDepthTest() //rlEnableDepthTest(); // Enable DEPTH_TEST for 3D
}
func GetSpeedForAxis(camera *FirstPersonCamera, axis FirstPersonCameraControls, speed float32) float32 {
key := camera.ControlKeys[axis]
if key == -1 {
return 0
}
var factor float32
factor = 1.0
if rl.IsKeyDown(camera.ControlKeys[SPRINT]) {
factor = 2
}
if rl.IsKeyDown(camera.ControlKeys[axis]) {
return speed * rl.GetFrameTime() * factor
}
return 0.0
}
func (camera *FirstPersonCamera) Update() {
if rl.IsWindowFocused() != camera.Focused && camera.UseMouse {
camera.Focused = rl.IsWindowFocused()
if camera.Focused {
rl.DisableCursor()
} else {
rl.EnableCursor()
}
}
mousePositionDelta := rl.GetMouseDelta()
direction := make([]float32, MOVE_DOWN+1)
direction[0] = GetSpeedForAxis(camera, MOVE_FRONT, camera.MoveSpeed.Z)
direction[1] = GetSpeedForAxis(camera, MOVE_BACK, camera.MoveSpeed.Z)
direction[2] = GetSpeedForAxis(camera, MOVE_RIGHT, camera.MoveSpeed.X)
direction[3] = GetSpeedForAxis(camera, MOVE_LEFT, camera.MoveSpeed.X)
direction[4] = GetSpeedForAxis(camera, MOVE_UP, camera.MoveSpeed.Y)
direction[5] = GetSpeedForAxis(camera, MOVE_DOWN, camera.MoveSpeed.Y)
turnRotation := GetSpeedForAxis(camera, TURN_RIGHT, camera.TurnSpeed.X) - GetSpeedForAxis(camera, TURN_LEFT, camera.TurnSpeed.X)
tiltRotation := GetSpeedForAxis(camera, TURN_UP, camera.TurnSpeed.Y) - GetSpeedForAxis(camera, TURN_DOWN, camera.TurnSpeed.Y)
if turnRotation != 0 {
camera.ViewAngles.X -= turnRotation * rl.Deg2rad
} else {
camera.ViewAngles.X += mousePositionDelta.X / -camera.MouseSensitivity
}
if tiltRotation != 0 {
camera.ViewAngles.Y += tiltRotation * rl.Deg2rad
} else if camera.UseMouse && camera.Focused {
camera.ViewAngles.Y += mousePositionDelta.Y / -camera.MouseSensitivity
}
target := rl.Vector3Transform(rl.NewVector3(0, 0, 1), rl.MatrixRotateXYZ(rl.NewVector3(camera.ViewAngles.Y, -camera.ViewAngles.X, 0)))
if camera.AllowFlight {
camera.Forward = target
} else {
camera.Forward = rl.Vector3Transform(rl.NewVector3(0, 0, 1), rl.MatrixRotateXYZ(rl.NewVector3(0, -camera.ViewAngles.X, 0)))
}
camera.Right = rl.NewVector3(camera.Forward.Z*-1.0, 0, camera.Forward.X)
camera.CameraPosition = rl.Vector3Add(camera.CameraPosition, rl.Vector3Scale(camera.Forward, direction[MOVE_FRONT]-direction[MOVE_BACK]))
camera.CameraPosition = rl.Vector3Add(camera.CameraPosition, rl.Vector3Scale(camera.Right, direction[MOVE_RIGHT]-direction[MOVE_LEFT]))
camera.CameraPosition.Y += direction[MOVE_UP] - direction[MOVE_DOWN]
camera.ViewCamera.Position = camera.CameraPosition
eyeOffset := camera.PlayerEyesPosition
if camera.ViewBobbleFreq > 0 {
swingDelta := float32(math.Max(math.Abs(float64(direction[MOVE_FRONT]-direction[MOVE_BACK])), math.Abs(float64(direction[MOVE_RIGHT]-direction[MOVE_LEFT]))))
camera.CurrentBobble += swingDelta * camera.ViewBobbleFreq
viewBobbleDampen := float32(8.0)
eyeOffset -= float32(math.Sin(float64(camera.CurrentBobble/viewBobbleDampen)) * rl.FlagFullscreenMode)
camera.ViewCamera.Up.X = float32(math.Sin(float64(camera.CurrentBobble/(viewBobbleDampen*2)))) * camera.ViewBobbleWaverMagnitude
camera.ViewCamera.Up.Z = float32(-math.Sin(float64(camera.CurrentBobble/(viewBobbleDampen*2)))) * camera.ViewBobbleWaverMagnitude
} else {
camera.CurrentBobble = 0
camera.ViewCamera.Up.X = 0
camera.ViewCamera.Up.Z = 0
}
camera.ViewCamera.Position.Y += eyeOffset
camera.ViewCamera.Target.X = camera.ViewCamera.Position.X + target.X
camera.ViewCamera.Target.Y = camera.ViewCamera.Position.Y + target.Y
camera.ViewCamera.Target.Z = camera.ViewCamera.Position.Z + target.Z
}
Are there any simpler examples to test rlgl
functions? Did you add all functions or just what is needed for this concrete example?
Sorry, I never even tried those raylib extras.
I just ported all functions needed for this one example, as its the example I was working with at the time and that worked "out of the box" in C.
I fixed some silly bugs in f963d74 and f565649 and added a proper example to my fork here https://github.com/Technerder/raylib-go/tree/master/examples/c_extras_ports/first_person_camera, and the world actually renders now but the camera movement seems to be broken. I've double checked the reference implementation and I'm rather confused as to why mine doesn't work properly.
https://user-images.githubusercontent.com/15988124/181679745-2c80cedb-2890-41de-9aae-ee94d69506fb.mp4
Implementation and 2d_camera_mouse_zoom example are added to the repo.