automated snapshot

This commit is contained in:
sumi
2025-12-15 22:29:06 -06:00
parent 80b59f4e82
commit 73c0471d54
3 changed files with 195 additions and 110 deletions

184
main.go
View File

@@ -1,11 +1,14 @@
package main package main
import ( import (
"fmt"
"log" "log"
"math"
"os" "os"
"time"
"github.com/gen2brain/raylib-go/raylib" "github.com/gen2brain/raylib-go/raylib"
"github.com/ojrac/opensimplex-go" "github.com/ojrac/opensimplex-go"
"math"
) )
func clamp01(v float64) float64 { func clamp01(v float64) float64 {
@@ -24,31 +27,6 @@ func GrayCurve(v, k float64) rl.Color {
return rl.Color{R: c, G: c, B: c, A: 255} return rl.Color{R: c, G: c, B: c, A: 255}
} }
func sierpinskiArrow(order int, length float64) {
rl.Scalef(1, -1, 1)
//rl.Rotatef(180, 0, 0, 1)
if order == 0 {
curve(order, length, 60)
} else {
rl.Rotatef(60, 0, 0, 1)
curve(order, length, -60)
}
}
func curve(order int, length float64, angle float64) {
if order == 0 {
len := int32(length)
rl.DrawLine(0, 0, len, 0, rl.Black)
rl.Translatef(float32(len), 0, 0)
} else {
curve(order-1, length/2, -angle)
rl.Rotatef(float32(angle), 0, 0, 1)
curve(order-1, length/2, angle)
rl.Rotatef(float32(angle), 0, 0, 1)
curve(order-1, length/2, -angle)
}
}
func main() { func main() {
const ( const (
@@ -69,6 +47,10 @@ func main() {
rl.InitWindow(screenWidth, screenHeight, "sumi sierpinski arrow") rl.InitWindow(screenWidth, screenHeight, "sumi sierpinski arrow")
sketches := []Sketch {
SierpinskiArrow{},
}
var camera = rl.Camera2D{ var camera = rl.Camera2D{
Target: rl.Vector2{X: 0, Y: 0}, Target: rl.Vector2{X: 0, Y: 0},
Offset: rl.Vector2{X: float32(screenWidth) / 2, Y: float32(screenHeight) / 2}, Offset: rl.Vector2{X: float32(screenWidth) / 2, Y: float32(screenHeight) / 2},
@@ -78,29 +60,72 @@ func main() {
rl.SetTargetFPS(60) rl.SetTargetFPS(60)
angles := make([]float32, 1000) t0 := time.Now()
noise := opensimplex.NewNormalized(0)
for i := range len(angles) { ports := MakePorts()
angles[i] = float32(noise.Eval2(float64(i)*0.05, 0.00))*0.1 - 0.05 ports["sierpinskiArrowLength"] = Sine {
Amp: 1000.0,
Freq: 0.001,
} }
frameNum := 0 ports["sierpinskiArrowDepth"] = Saw {
Min: 1, Max: 9, Period: 10,
}
for !rl.WindowShouldClose() { for !rl.WindowShouldClose() {
updateCamera(&camera)
frameNum++ // begin drawing
rl.BeginDrawing()
rl.ClearBackground(rl.RayWhite)
rl.BeginMode2D(camera)
rl.PushMatrix()
t := time.Since(t0).Seconds()
// set up RenderCtx
renderCtx := &RenderCtx {
Width: screenWidth,
Height: screenHeight,
Time: t,
Ports: ports.Eval(t),
}
/**
MAIN DRAWING
**/
for _, s := range sketches {
s.Draw(renderCtx)
}
if rl.IsKeyDown(rl.KeySpace) {
if _, err := storage.Save(); err != nil {
log.Printf("Error saving snapshot: %v\n", err)
}
}
rl.PopMatrix()
rl.EndMode2D()
// HUD
rl.DrawText("Mouse right button drag to move, mouse wheel to zoom", 10, 10, 20, rl.White)
rl.EndDrawing()
}
rl.CloseWindow()
}
func updateCamera(camera *rl.Camera2D) {
if rl.IsMouseButtonDown(rl.MouseRightButton) { if rl.IsMouseButtonDown(rl.MouseRightButton) {
delta := rl.GetMouseDelta() delta := rl.GetMouseDelta()
delta = rl.Vector2Scale(delta, -1.0/camera.Zoom) delta = rl.Vector2Scale(delta, -1.0/camera.Zoom)
camera.Target = rl.Vector2Add(camera.Target, delta) camera.Target = rl.Vector2Add(camera.Target, delta)
} }
// Zoom based on mouse wheel // Zoom based on mouse wheel
wheel := rl.GetMouseWheelMove() wheel := rl.GetMouseWheelMove()
if wheel != 0 { if wheel != 0 {
// Get the world point that is under the mouse // Get the world point that is under the mouse
mouseWorldPos := rl.GetScreenToWorld2D(rl.GetMousePosition(), camera) mouseWorldPos := rl.GetScreenToWorld2D(rl.GetMousePosition(), *camera)
// Set the offset to where the mouse is // Set the offset to where the mouse is
camera.Offset = rl.GetMousePosition() camera.Offset = rl.GetMousePosition()
@@ -117,73 +142,66 @@ func main() {
camera.Zoom = zoomIncrement camera.Zoom = zoomIncrement
} }
} }
}
rl.BeginDrawing()
rl.ClearBackground(rl.RayWhite)
rl.BeginMode2D(camera)
type SierpinskiArrow struct {}
func (s SierpinskiArrow) Draw(ctx *RenderCtx) {
rl.PushMatrix() rl.PushMatrix()
sierpinskiArrow(ctx, int(ctx.Ports["sierpinskiArrowDepth"]), ctx.Ports["sierpinskiArrowLength"])
rl.PopMatrix()
}
/** func sierpinskiArrow(ctx *RenderCtx, order int, length float64) {
for x := range screenWidth { if order == 0 {
for y := range screenHeight { curve(ctx, order, length, 60)
sp := rl.Vector2 { X: float32(x), Y: float32(y) }; } else {
wp := rl.GetScreenToWorld2D(sp, camera); rl.Rotatef(60, 0, 0, 1)
normVal := noise.Eval2(float64(wp.X), float64(wp.Y)) curve(ctx, order, length, -60)
rl.DrawPixelV(wp, GrayCurve(normVal, 0.8));
} }
}
func curve(ctx *RenderCtx, order int, length float64, angle float64) {
if order == 0 {
len := int32(length)
rl.DrawLine(0, 0, len, 0, rl.Black)
rl.Translatef(float32(len), 0, 0)
} else {
curve(ctx, order-1, length/2, -angle)
rl.Rotatef(float32(angle), 0, 0, 1)
curve(ctx, order-1, length/2, angle)
rl.Rotatef(float32(angle), 0, 0, 1)
curve(ctx, order-1, length/2, -angle)
} }
**/ }
func main2() {
angles := make([]float32, 1000)
noise := opensimplex.NewNormalized(0)
for i := range len(angles) {
angles[i] = float32(noise.Eval2(float64(i)*0.05, 0.00))*0.1 - 0.05
}
frameNum := 0
for !rl.WindowShouldClose() {
frameNum++
// initial transform by halfway again through angle array // initial transform by halfway again through angle array
angleIndex := frameNum % len(angles) angleIndex := (frameNum/10) % len(angles)
angle := angles[angleIndex] angle := angles[angleIndex]
initAngle := angles[(angleIndex+len(angles)/2)%len(angles)] initAngle := angles[(angleIndex+len(angles)/2)%len(angles)]
rl.Rotatef(2500*initAngle, 0, 0, 1) rl.Rotatef(2500*initAngle, 0, 0, 1)
rl.Translatef(100*initAngle, 100*initAngle, 0) rl.Translatef(100*initAngle, 100*initAngle, 0)
stepSize := int32(1) fmt.Printf("%.3f", angle)
for range 1000 {
rl.DrawLine(0, 0, stepSize, 0, rl.Black)
rl.Translatef(float32(stepSize), 0, 0)
rl.Rotatef(angle, 0, 0, 1)
angleIndex++
angleIndex = angleIndex % len(angles)
angle += angles[angleIndex]
}
rl.PopMatrix()
rl.PushMatrix()
//rl.Translatef(-screenWidth/2, screenHeight/2, 0)
sierpinskiArrow(9, 800)
rl.PopMatrix()
/*
rl.PushMatrix()
rl.Translatef(0, 25*50, 0)
rl.Rotatef(90, 1, 0, 0)
rl.DrawGrid(100, 50)
rl.PopMatrix()
*/
rl.EndMode2D() rl.EndMode2D()
if rl.IsKeyDown(rl.KeySpace) {
if _, err := storage.Save(); err != nil {
log.Printf("Error saving snapshot: %v\n", err)
}
} }
rl.DrawText("Mouse right button drag to move, mouse wheel to zoom", 10, 10, 20, rl.White)
rl.EndDrawing()
}
rl.CloseWindow()
} }

28
signals.go Normal file
View File

@@ -0,0 +1,28 @@
package main
import (
"math"
)
type Signal interface {
Eval(t float64) float64
}
type Const struct{ V float64 }
func (s Const) Eval(t float64) float64 { return s.V }
type Sine struct {
Amp, Freq, Phase, Bias float64
}
func (s Sine) Eval(t float64) float64 {
return s.Bias + s.Amp*math.Sin(2*math.Pi*s.Freq*t+s.Phase)
}
type Saw struct {
Min, Max, Period float64
}
func (s Saw) Eval(t float64) float64 {
u := math.Mod(t, s.Period) / s.Period // 0..1
return s.Min + (s.Max-s.Min)*u
}

39
sketch.go Normal file
View File

@@ -0,0 +1,39 @@
package main
import (
"github.com/gen2brain/raylib-go/raylib"
)
type Sketch interface {
Draw(ctx *RenderCtx)
}
/** Ports **/
type Ports map[string]Signal
func MakePorts() Ports {
return make(Ports)
}
/**
* materialize current value for all ports
**/
func (p Ports) Eval(t float64) map[string]float64 {
out := make(map[string]float64, len(p))
for name, sig := range(p) {
out[name] = sig.Eval(t)
}
return out
}
/** RenderCtx **/
type RenderCtx struct {
Width int32
Height int32
Time float64
Ports map[string]float64
Cam rl.Camera2D
}