feature: Implement display rotation

This commit is contained in:
Tera << 8 2025-06-27 22:08:51 -04:00
parent 6911afb6e0
commit 0efaf19b40
Signed by: imterah
GPG key ID: 8FA7DD57BA6CEA37
3 changed files with 75 additions and 17 deletions

View file

@ -9,6 +9,8 @@ type DisplayConfig struct {
Angle *int `yaml:"angle"`
FOV *int `yaml:"fov"`
Spacing *float32 `yaml:"spacing"`
RadiusMultiplier *float32 `yaml:"circle_radius_multiplier"`
UseCircularSpacing *bool `yaml:"use_circular_spacing"`
Count *int `yaml:"count"`
}
@ -41,6 +43,8 @@ var DefaultConfig = &Config{
Angle: getPtrToInt(45),
FOV: getPtrToInt(45),
Spacing: getPtrToFloat32(0.5),
RadiusMultiplier: getPtrToFloat32(2),
UseCircularSpacing: getPtrToBool(true),
Count: getPtrToInt(3),
},
Overrides: AppOverrides{

View file

@ -9,7 +9,9 @@
display:
angle: 45 # Angle of the virtual displays
fov: 45 # FOV of the 3D camera
spacing: 0.5 # Spacing between virtual displays
spacing: 0.5 # Raw spacing between virtual displays. Does not use circles in the layout. Purely flat plane.
circle_radius_multiplier: 2 # Multiplier for the radius of the circle used to calculate the spacing between virtual displays. "Rounded" plane of sorts.
use_circular_spacing: true # If true, uses a circular layout for the virtual displays.
count: 3 # Count of virtual displays
overrides:
allow_unsupported_devices: false # If true, allows unsupported devices to be used as long as they're a compatible vendor (Xreal)

View file

@ -35,6 +35,15 @@ func findOptimalHorizontalRes(verticalDisplayRes float32, horizontalDisplayRes f
return horizontalSize
}
func findHfovFromVfov(vfovDeg, w, h float64) float64 {
vfovRad := vfovDeg * math.Pi / 180
ar := w / h
hfovRad := 2 * math.Atan(math.Tan(vfovRad/2)*ar)
return hfovRad * 180 / math.Pi
}
func EnterRenderLoop(config *libconfig.Config, displayMetadata *edidtools.DisplayMetadata, evdiCards []*EvdiDisplayMetadata) {
log.Info("Initializing AR driver")
headset, err := ardriver.GetDevice()
@ -99,7 +108,9 @@ func EnterRenderLoop(config *libconfig.Config, displayMetadata *edidtools.Displa
headset.RegisterEventListeners(arEventListner)
fovY := float32(45.0)
fovY := float32(*config.DisplayConfig.FOV)
fovX := findHfovFromVfov(float64(fovY), float64(displayMetadata.MaxWidth), float64(displayMetadata.MaxHeight))
verticalSize := findMaxVerticalSize(fovY, 5.0)
camera := rl.NewCamera3D(
@ -125,6 +136,21 @@ func EnterRenderLoop(config *libconfig.Config, displayMetadata *edidtools.Displa
horizontalSize := findOptimalHorizontalRes(float32(displayMetadata.MaxHeight), float32(displayMetadata.MaxWidth), verticalSize)
coreMesh := rl.GenMeshPlane(horizontalSize, verticalSize, 1, 1)
var radius float32
if *config.DisplayConfig.UseCircularSpacing == true {
radiusX := (horizontalSize / 2) / float32(math.Tan((float64(fovX)*math.Pi/180.0)/2))
radiusY := (verticalSize / 2) / float32(math.Tan((float64(fovY)*math.Pi/180.0)/2))
if radiusY > radiusX {
radius = radiusY
} else {
radius = radiusX
}
radius *= *config.DisplayConfig.RadiusMultiplier
}
movementVector := rl.Vector3{
X: 0.0,
Y: 0.0,
@ -171,6 +197,17 @@ func EnterRenderLoop(config *libconfig.Config, displayMetadata *edidtools.Displa
texture := rl.LoadTextureFromImage(image)
model := rl.LoadModelFromMesh(coreMesh)
// spin up/down
pitchRad := float32(-90 * rl.Deg2rad)
// spin left/right
yawRad := currentAngle * rl.Deg2rad
rotX := rl.MatrixRotateX(pitchRad)
rotY := rl.MatrixRotateY(yawRad)
transform := rl.MatrixMultiply(rotX, rotY)
model.Transform = transform
rl.SetMaterialTexture(model.Materials, rl.MapAlbedo, texture)
rects[i] = &TextureModelPair{
@ -235,20 +272,35 @@ func EnterRenderLoop(config *libconfig.Config, displayMetadata *edidtools.Displa
card.EvdiNode.RequestUpdate(card.Buffer)
}
rl.DrawModelEx(
rect.Model,
rl.Vector3{
X: rect.CurrentDisplaySpacing,
worldPos := rl.Vector3{
X: 0,
Y: verticalSize / 2,
Z: 0,
},
}
if *config.DisplayConfig.UseCircularSpacing == true {
yawRad := float32(rl.Deg2rad * rect.CurrentAngle)
// WTF?
posX := float32(math.Sin(float64(yawRad))) * radius
posZ := -float32(math.Cos(float64(yawRad))) * radius
worldPos.X = posX
worldPos.Z = posZ + radius
} else {
worldPos.X = rect.CurrentDisplaySpacing
}
rl.DrawModelEx(
rect.Model,
worldPos,
// rotate around X to make it vertical
rl.Vector3{
X: 1,
X: 0,
Y: 0,
Z: 0,
},
90,
0,
rl.Vector3{
X: 1,
Y: 1,