cube/chatgpt.go

185 lines
3.4 KiB
Go
Raw Normal View History

2025-01-26 07:48:03 +04:00
package main
import (
2025-01-26 23:04:52 +04:00
"fmt"
2025-01-26 07:48:03 +04:00
"image"
"image/color"
"image/draw"
"math"
2025-01-26 23:04:52 +04:00
"time"
2025-01-26 07:48:03 +04:00
"git.niplace.ru/XoxJlopeZi4BB/dev/fb"
2025-01-26 23:04:52 +04:00
"github.com/golang/freetype"
"github.com/golang/freetype/truetype"
"golang.org/x/image/font"
"golang.org/x/image/font/gofont/gomono"
2025-01-26 07:48:03 +04:00
)
var Width, Height = fb.Resolution()
2025-01-26 23:04:52 +04:00
2025-01-26 07:48:03 +04:00
const (
cubeSize = 50
Zoom = 1000.0
FOV = 350
frameCount = 120
rotationStep = math.Pi / 60
)
type Point3D struct {
X, Y, Z float64
}
type Point2D struct {
X, Y int
}
func rotateX(p Point3D, angle float64) Point3D {
cosA := math.Cos(angle)
sinA := math.Sin(angle)
return Point3D{
X: p.X,
Y: p.Y*cosA - p.Z*sinA,
Z: p.Y*sinA + p.Z*cosA,
}
}
func rotateY(p Point3D, angle float64) Point3D {
cosA := math.Cos(angle)
sinA := math.Sin(angle)
return Point3D{
X: p.X*cosA + p.Z*sinA,
Y: p.Y,
Z: -p.X*sinA + p.Z*cosA,
}
}
func project(p Point3D) Point2D {
scale := Zoom / (p.Z + FOV)
return Point2D{
X: int(p.X*scale + float64(Width)/2),
Y: int(p.Y*scale + float64(Height)/2),
}
}
func drawLine(img *image.Paletted, p1, p2 Point2D, col color.Color) {
dx := abs(p2.X - p1.X)
dy := abs(p2.Y - p1.Y)
sx := -1
if p1.X < p2.X {
sx = 1
}
sy := -1
if p1.Y < p2.Y {
sy = 1
}
err := dx - dy
for {
img.Set(p1.X, p1.Y, col)
if p1.X == p2.X && p1.Y == p2.Y {
break
}
e2 := 2 * err
if e2 > -dy {
err -= dy
p1.X += sx
}
if e2 < dx {
err += dx
p1.Y += sy
}
}
}
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
/*
func Map[S, T any](v S, f func(T) T) S {
}
*/
func main() {
// Define the vertices of the cube
vertices := []Point3D{
{-cubeSize, -cubeSize, -cubeSize},
{cubeSize, -cubeSize, -cubeSize},
{cubeSize, cubeSize, -cubeSize},
{-cubeSize, cubeSize, -cubeSize},
{-cubeSize, -cubeSize, cubeSize},
{cubeSize, -cubeSize, cubeSize},
{cubeSize, cubeSize, cubeSize},
{-cubeSize, cubeSize, cubeSize},
}
// Define the edges of the cube
edges := [][2]int{
{0, 1}, {1, 2}, {2, 3}, {3, 0},
{4, 5}, {5, 6}, {6, 7}, {7, 4},
{0, 4}, {1, 5}, {2, 6}, {3, 7},
}
// Palette for the GIF
palette := []color.Color{color.Black, color.White}
2025-01-26 23:04:52 +04:00
var (
fontSize = 96.0
DPI = 72.0
spacing = 1.5
)
f, err := truetype.Parse(gomono.TTF)
if err != nil {
panic(err)
}
ctx := freetype.NewContext()
ctx.SetDPI(DPI)
ctx.SetFont(f)
ctx.SetFontSize(fontSize)
ctx.SetClip(image.Rect(0, 0, Width, Height))
ctx.SetSrc(image.NewUniform(palette[1]))
ctx.SetHinting(font.HintingNone)
var text string = "text"
var fps int
2025-01-26 07:48:03 +04:00
// Generate frames
for i := 0; i < frameCount; i++ {
angle := float64(i) * rotationStep
img := image.NewPaletted(image.Rect(0, 0, Width, Height), palette)
draw.Draw(img, img.Bounds(), &image.Uniform{color.Black}, image.Point{}, draw.Src)
2025-01-26 23:04:52 +04:00
ctx.SetDst(img)
2025-01-26 07:48:03 +04:00
// Rotate and project vertices
projVertices := make([]Point2D, len(vertices))
for j, v := range vertices {
rotated := rotateY(rotateX(v, angle), angle)
projVertices[j] = project(rotated)
}
// Draw edges
for _, edge := range edges {
p1 := projVertices[edge[0]]
p2 := projVertices[edge[1]]
drawLine(img, p1, p2, color.White)
}
2025-01-26 23:04:52 +04:00
text = fmt.Sprint(fps)
pt := freetype.Pt(30, 30+int(ctx.PointToFixed(fontSize)>>6))
_, err = ctx.DrawString(text, pt)
if err != nil {
panic(err)
}
pt.Y += ctx.PointToFixed(fontSize * spacing)
t := time.Now()
2025-01-26 07:48:03 +04:00
err := fb.Draw(img)
if err != nil {
panic(err)
}
2025-01-26 23:04:52 +04:00
d := time.Since(t)
fps = int(time.Second / d)
2025-01-26 07:48:03 +04:00
}
}