feature: Add primitive version of multiple displays
This commit is contained in:
parent
322e00b3b9
commit
9f9c8b4be7
7 changed files with 48 additions and 22 deletions
|
@ -6,10 +6,10 @@ import _ "embed"
|
||||||
var InitialConfig []byte
|
var InitialConfig []byte
|
||||||
|
|
||||||
type DisplayConfig struct {
|
type DisplayConfig struct {
|
||||||
Angle *int `yaml:"angle"`
|
Angle *int `yaml:"angle"`
|
||||||
FOV *int `yaml:"fov"`
|
FOV *int `yaml:"fov"`
|
||||||
Spacing *int `yaml:"spacing"`
|
Spacing *float32 `yaml:"spacing"`
|
||||||
Count *int `yaml:"count"`
|
Count *int `yaml:"count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppOverrides struct {
|
type AppOverrides struct {
|
||||||
|
@ -28,6 +28,10 @@ func getPtrToInt(int int) *int {
|
||||||
return &int
|
return &int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getPtrToFloat32(float32 float32) *float32 {
|
||||||
|
return &float32
|
||||||
|
}
|
||||||
|
|
||||||
func getPtrToBool(bool bool) *bool {
|
func getPtrToBool(bool bool) *bool {
|
||||||
return &bool
|
return &bool
|
||||||
}
|
}
|
||||||
|
@ -36,7 +40,7 @@ var DefaultConfig = &Config{
|
||||||
DisplayConfig: DisplayConfig{
|
DisplayConfig: DisplayConfig{
|
||||||
Angle: getPtrToInt(45),
|
Angle: getPtrToInt(45),
|
||||||
FOV: getPtrToInt(45),
|
FOV: getPtrToInt(45),
|
||||||
Spacing: getPtrToInt(1),
|
Spacing: getPtrToFloat32(0.5),
|
||||||
Count: getPtrToInt(3),
|
Count: getPtrToInt(3),
|
||||||
},
|
},
|
||||||
Overrides: AppOverrides{
|
Overrides: AppOverrides{
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
display:
|
display:
|
||||||
angle: 45 # Angle of the virtual displays
|
angle: 45 # Angle of the virtual displays
|
||||||
fov: 45 # FOV of the 3D camera
|
fov: 45 # FOV of the 3D camera
|
||||||
spacing: 1 # Spacing between virtual displays
|
spacing: 0.5 # Spacing between virtual displays
|
||||||
count: 3 # Count of virtual displays
|
count: 3 # Count of virtual displays
|
||||||
overrides:
|
overrides:
|
||||||
allow_unsupported_devices: false # If true, allows unsupported devices to be used as long as they're a compatible vendor (Xreal)
|
allow_unsupported_devices: false # If true, allows unsupported devices to be used as long as they're a compatible vendor (Xreal)
|
||||||
|
|
|
@ -155,7 +155,13 @@ func mainEntrypoint(context.Context, *cli.Command) error {
|
||||||
Y2: displayMetadata.MaxHeight,
|
Y2: displayMetadata.MaxHeight,
|
||||||
}
|
}
|
||||||
|
|
||||||
displayBuffer := openedDevice.CreateBuffer(displayMetadata.MaxWidth, displayMetadata.MaxHeight, libevdi.StridePixelFormatRGBA32, displayRect)
|
displayBuffer, err := openedDevice.CreateBuffer(displayMetadata.MaxWidth, displayMetadata.MaxHeight, libevdi.StridePixelFormatRGBA32, displayRect)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("Failed to create buffer for display %d: %s", currentDisplay, err.Error())
|
||||||
|
atexit.Exit(1)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
displayMetadata := &renderer.EvdiDisplayMetadata{
|
displayMetadata := &renderer.EvdiDisplayMetadata{
|
||||||
EvdiNode: openedDevice,
|
EvdiNode: openedDevice,
|
||||||
|
|
|
@ -17,8 +17,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type TextureModelPair struct {
|
type TextureModelPair struct {
|
||||||
Texture rl.Texture2D
|
Texture rl.Texture2D
|
||||||
Model rl.Model
|
Model rl.Model
|
||||||
|
CurrentAngle float32
|
||||||
|
CurrentDisplaySpacing float32
|
||||||
}
|
}
|
||||||
|
|
||||||
func findMaxVerticalSize(fovyDeg float32, distance float32) float32 {
|
func findMaxVerticalSize(fovyDeg float32, distance float32) float32 {
|
||||||
|
@ -125,7 +127,8 @@ func EnterRenderLoop(config *libconfig.Config, displayMetadata *edidtools.Displa
|
||||||
rl.DisableBackfaceCulling()
|
rl.DisableBackfaceCulling()
|
||||||
rl.DisableDepthTest()
|
rl.DisableDepthTest()
|
||||||
|
|
||||||
coreMesh := rl.GenMeshPlane(findOptimalHorizontalRes(float32(displayMetadata.MaxHeight), float32(displayMetadata.MaxWidth), verticalSize), verticalSize, 1, 1)
|
horizontalSize := findOptimalHorizontalRes(float32(displayMetadata.MaxHeight), float32(displayMetadata.MaxWidth), verticalSize)
|
||||||
|
coreMesh := rl.GenMeshPlane(horizontalSize, verticalSize, 1, 1)
|
||||||
|
|
||||||
movementVector := rl.Vector3{
|
movementVector := rl.Vector3{
|
||||||
X: 0.0,
|
X: 0.0,
|
||||||
|
@ -156,7 +159,18 @@ func EnterRenderLoop(config *libconfig.Config, displayMetadata *edidtools.Displa
|
||||||
|
|
||||||
rects := make([]*TextureModelPair, len(evdiCards))
|
rects := make([]*TextureModelPair, len(evdiCards))
|
||||||
|
|
||||||
|
displayAngle := float32(*config.DisplayConfig.Angle)
|
||||||
|
displaySpacing := *config.DisplayConfig.Spacing + horizontalSize
|
||||||
|
|
||||||
|
highestPossibleAngleOnBothSides := float32((*config.DisplayConfig.Count)-1) * displayAngle
|
||||||
|
highestPossibleDisplaySpacingOnBothSides := float32((*config.DisplayConfig.Count)-1) * displaySpacing
|
||||||
|
|
||||||
for i, card := range evdiCards {
|
for i, card := range evdiCards {
|
||||||
|
currentAngle := (-highestPossibleAngleOnBothSides) + (displayAngle * float32(i+1))
|
||||||
|
currentDisplaySpacing := (-highestPossibleDisplaySpacingOnBothSides) + (displaySpacing * float32(i+1))
|
||||||
|
|
||||||
|
log.Debugf("display #%d: currentAngle=%f, currentDisplaySpacing=%f", i, currentAngle, currentDisplaySpacing)
|
||||||
|
|
||||||
image := rl.NewImage(card.Buffer.Buffer, int32(displayMetadata.MaxWidth), int32(displayMetadata.MaxHeight), 1, rl.UncompressedR8g8b8a8)
|
image := rl.NewImage(card.Buffer.Buffer, int32(displayMetadata.MaxWidth), int32(displayMetadata.MaxHeight), 1, rl.UncompressedR8g8b8a8)
|
||||||
|
|
||||||
texture := rl.LoadTextureFromImage(image)
|
texture := rl.LoadTextureFromImage(image)
|
||||||
|
@ -165,8 +179,10 @@ func EnterRenderLoop(config *libconfig.Config, displayMetadata *edidtools.Displa
|
||||||
rl.SetMaterialTexture(model.Materials, rl.MapAlbedo, texture)
|
rl.SetMaterialTexture(model.Materials, rl.MapAlbedo, texture)
|
||||||
|
|
||||||
rects[i] = &TextureModelPair{
|
rects[i] = &TextureModelPair{
|
||||||
Texture: texture,
|
Texture: texture,
|
||||||
Model: model,
|
Model: model,
|
||||||
|
CurrentAngle: currentAngle,
|
||||||
|
CurrentDisplaySpacing: currentDisplaySpacing,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,13 +216,13 @@ func EnterRenderLoop(config *libconfig.Config, displayMetadata *edidtools.Displa
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed to wait for display events: %s", err.Error())
|
log.Errorf("Failed to wait for display events: %s", err.Error())
|
||||||
break
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if ready {
|
if ready {
|
||||||
if err := card.EvdiNode.HandleEvents(card.EventContext); err != nil {
|
if err := card.EvdiNode.HandleEvents(card.EventContext); err != nil {
|
||||||
log.Errorf("Failed to handle display events: %s", err.Error())
|
log.Errorf("Failed to handle display events: %s", err.Error())
|
||||||
break
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
card.EvdiNode.GrabPixels(card.Rect)
|
card.EvdiNode.GrabPixels(card.Rect)
|
||||||
|
@ -223,7 +239,7 @@ func EnterRenderLoop(config *libconfig.Config, displayMetadata *edidtools.Displa
|
||||||
rl.DrawModelEx(
|
rl.DrawModelEx(
|
||||||
rect.Model,
|
rect.Model,
|
||||||
rl.Vector3{
|
rl.Vector3{
|
||||||
X: 0,
|
X: rect.CurrentDisplaySpacing,
|
||||||
Y: verticalSize / 2,
|
Y: verticalSize / 2,
|
||||||
Z: 0,
|
Z: 0,
|
||||||
},
|
},
|
||||||
|
@ -241,8 +257,6 @@ func EnterRenderLoop(config *libconfig.Config, displayMetadata *edidtools.Displa
|
||||||
},
|
},
|
||||||
rl.White,
|
rl.White,
|
||||||
)
|
)
|
||||||
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rl.EndMode3D()
|
rl.EndMode3D()
|
||||||
|
|
|
@ -5,8 +5,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type EvdiDisplayMetadata struct {
|
type EvdiDisplayMetadata struct {
|
||||||
EvdiNode *libevdi.EvdiNode
|
EvdiNode *libevdi.EvdiNode
|
||||||
Rect *libevdi.EvdiDisplayRect
|
Rect *libevdi.EvdiDisplayRect
|
||||||
Buffer *libevdi.EvdiBuffer
|
Buffer *libevdi.EvdiBuffer
|
||||||
EventContext *libevdi.EvdiEventContext
|
EventContext *libevdi.EvdiEventContext
|
||||||
}
|
}
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -4,7 +4,6 @@ go 1.24.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.terah.dev/UnrealXR/raylib-go/raylib v0.55.2-0.20250623002739-1468af2636e1
|
git.terah.dev/UnrealXR/raylib-go/raylib v0.55.2-0.20250623002739-1468af2636e1
|
||||||
git.terah.dev/imterah/goevdi v1.14.11-0.20250626004148-bdbef2a68ff9
|
|
||||||
github.com/anoopengineer/edidparser v0.0.0-20240602223913-86ca9ed3d2b0
|
github.com/anoopengineer/edidparser v0.0.0-20240602223913-86ca9ed3d2b0
|
||||||
github.com/charmbracelet/log v0.4.2
|
github.com/charmbracelet/log v0.4.2
|
||||||
github.com/goccy/go-yaml v1.18.0
|
github.com/goccy/go-yaml v1.18.0
|
||||||
|
@ -15,6 +14,7 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
git.terah.dev/imterah/goevdi/libevdi v0.1.0-evdi1.14.10 // indirect
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
|
||||||
github.com/charmbracelet/lipgloss v1.1.0 // indirect
|
github.com/charmbracelet/lipgloss v1.1.0 // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -2,6 +2,8 @@ git.terah.dev/UnrealXR/raylib-go/raylib v0.55.2-0.20250623002739-1468af2636e1 h1
|
||||||
git.terah.dev/UnrealXR/raylib-go/raylib v0.55.2-0.20250623002739-1468af2636e1/go.mod h1:ZRirF2UuVWSbl2ux7oyHwXcinni9msejCvtIsXbT8yY=
|
git.terah.dev/UnrealXR/raylib-go/raylib v0.55.2-0.20250623002739-1468af2636e1/go.mod h1:ZRirF2UuVWSbl2ux7oyHwXcinni9msejCvtIsXbT8yY=
|
||||||
git.terah.dev/imterah/goevdi v1.14.11-0.20250626004148-bdbef2a68ff9 h1:TYcPZ62CR3keYf/dE9KyV5X5krh+riDyZ3fnhkeSRyA=
|
git.terah.dev/imterah/goevdi v1.14.11-0.20250626004148-bdbef2a68ff9 h1:TYcPZ62CR3keYf/dE9KyV5X5krh+riDyZ3fnhkeSRyA=
|
||||||
git.terah.dev/imterah/goevdi v1.14.11-0.20250626004148-bdbef2a68ff9/go.mod h1:4scjAuFakx/2gTRSeCtTNHnj1v9FdF3XiOMmWsz4FDs=
|
git.terah.dev/imterah/goevdi v1.14.11-0.20250626004148-bdbef2a68ff9/go.mod h1:4scjAuFakx/2gTRSeCtTNHnj1v9FdF3XiOMmWsz4FDs=
|
||||||
|
git.terah.dev/imterah/goevdi/libevdi v0.1.0-evdi1.14.10 h1:M+Wja0b6Ks3mZXMGoBs3KZXsKRRWolUelITLQ/kaIFw=
|
||||||
|
git.terah.dev/imterah/goevdi/libevdi v0.1.0-evdi1.14.10/go.mod h1:7zdodqq+tECNHTljD5l7x0PvcGglLCa+mD2eQj0vkEg=
|
||||||
github.com/anoopengineer/edidparser v0.0.0-20240602223913-86ca9ed3d2b0 h1:rTfysyBCL7LPbq9GFpQbllvKT8vEI93lQUwksMMxHMI=
|
github.com/anoopengineer/edidparser v0.0.0-20240602223913-86ca9ed3d2b0 h1:rTfysyBCL7LPbq9GFpQbllvKT8vEI93lQUwksMMxHMI=
|
||||||
github.com/anoopengineer/edidparser v0.0.0-20240602223913-86ca9ed3d2b0/go.mod h1:fEt61NePh3ZMxA+g3iC4CaGzY9lEsHRUkYJY2x0lBAw=
|
github.com/anoopengineer/edidparser v0.0.0-20240602223913-86ca9ed3d2b0/go.mod h1:fEt61NePh3ZMxA+g3iC4CaGzY9lEsHRUkYJY2x0lBAw=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue