ichigo/geom/projection.go

60 lines
1.6 KiB
Go
Raw Normal View History

2021-09-08 20:08:57 +10:00
package geom
2021-09-05 17:22:46 +10:00
2021-09-07 13:14:42 +10:00
import "image"
2021-09-05 17:22:46 +10:00
2021-09-17 16:47:18 +10:00
// Projector is used by Box and others to accept arbitrary
type Projector interface {
// Sign returns a {-1, 0, 1}-valued 2D vector pointing in the direction that
// positive Z values are projected to.
Sign() image.Point
2021-09-19 15:51:35 +10:00
// Project projects a Z coordinate into 2D offset.
Project(int) image.Point
}
// Project is shorthand for π.Project(p.Z).Add(p.XY()).
func Project(π Projector, p Int3) image.Point {
return π.Project(p.Z).Add(p.XY())
2021-09-17 16:47:18 +10:00
}
2021-09-16 10:28:58 +10:00
// Projection uses floats to define a projection.
type Projection struct{ X, Y float64 }
2021-09-17 16:47:18 +10:00
func (π Projection) Sign() (s image.Point) {
return image.Pt(int(FSign(π.X)), int(FSign(π.Y)))
}
2021-09-19 15:51:35 +10:00
// Project returns (z*π.X, z*π.Y).
func (π Projection) Project(z int) image.Point {
2021-09-16 10:28:58 +10:00
return image.Pt(
2021-09-19 15:51:35 +10:00
int(π.X*float64(z)),
int(π.Y*float64(z)),
2021-09-16 10:28:58 +10:00
)
}
2021-09-07 14:00:50 +10:00
// IntProjection holds an integer projection definition.
// It is designed for projecting Z onto X and Y with integer fractions as would
2021-09-19 15:51:35 +10:00
// be used in e.g. a diametric projection (IntProjection{X:0, Y:2}).
2021-09-07 13:14:42 +10:00
type IntProjection image.Point
2021-09-05 17:22:46 +10:00
2021-09-17 16:47:18 +10:00
func (π IntProjection) Sign() image.Point { return image.Point(π) }
2021-09-19 15:51:35 +10:00
// Project returns (z/π.X, z/π.Y), unless π.X or π.Y are 0, in which case that
// component is zero
func (π IntProjection) Project(z int) image.Point {
2021-09-07 13:14:42 +10:00
/*
Dividing is used because there's little reason for an isometric
projection in a game to exaggerate the Z position.
2021-09-05 17:22:46 +10:00
2021-09-09 19:11:25 +10:00
Integers are used to preserve "pixel perfect" calculation in case you
are making the next Celeste.
2021-09-07 13:14:42 +10:00
*/
2021-09-19 15:51:35 +10:00
var q image.Point
2021-09-07 13:14:42 +10:00
if π.X != 0 {
2021-09-19 15:51:35 +10:00
q.X = z / π.X
2021-09-07 13:14:42 +10:00
}
if π.Y != 0 {
2021-09-19 15:51:35 +10:00
q.Y = z / π.Y
2021-09-07 13:14:42 +10:00
}
return q
2021-09-05 17:22:46 +10:00
}