handle different projections
This commit is contained in:
parent
f5219da56f
commit
e4c15fcd5d
5 changed files with 48 additions and 25 deletions
|
@ -26,37 +26,47 @@ type drawList struct {
|
||||||
|
|
||||||
// edge reports if there is a draw ordering constraint between u and v (where
|
// edge reports if there is a draw ordering constraint between u and v (where
|
||||||
// u draws before v).
|
// u draws before v).
|
||||||
func edge(u, v Drawer) bool {
|
func edge(u, v Drawer, πsign image.Point) bool {
|
||||||
// Common logic for known interfaces (BoundingBoxer, ZPositioner), to
|
// Common logic for known interfaces (BoundingBoxer, ZPositioner), to
|
||||||
// simplify DrawOrderer implementations.
|
// simplify DrawOrderer implementations.
|
||||||
switch x := u.(type) {
|
switch u := u.(type) {
|
||||||
case BoundingBoxer:
|
case BoundingBoxer:
|
||||||
xb := x.BoundingBox()
|
ub := u.BoundingBox()
|
||||||
switch y := v.(type) {
|
switch v := v.(type) {
|
||||||
case BoundingBoxer:
|
case BoundingBoxer:
|
||||||
yb := y.BoundingBox()
|
vb := v.BoundingBox()
|
||||||
if xb.Min.Z >= yb.Max.Z { // x is in front of y
|
if ub.Min.Z >= vb.Max.Z { // u is in front of v
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if xb.Max.Z <= yb.Min.Z { // x is behind y
|
if ub.Max.Z <= vb.Min.Z { // u is behind v
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if xb.Max.Y <= yb.Min.Y { // x is above y
|
if πsign.X != 0 {
|
||||||
return false
|
if ub.Max.X*πsign.X <= vb.Min.X*πsign.X { // u is to the left of v
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ub.Min.X*πsign.X >= vb.Max.X*πsign.X { // u is to the right of v
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if xb.Min.Y >= yb.Max.Y { // x is below y
|
if πsign.Y != 0 {
|
||||||
return true
|
if ub.Max.Y*πsign.Y <= vb.Min.Y*πsign.Y { // u is above v
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if ub.Min.Y*πsign.Y >= vb.Max.Y*πsign.Y { // u is below v
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case ZPositioner:
|
case ZPositioner:
|
||||||
return xb.Max.Z < y.ZPos() // x is before y
|
return ub.Max.Z < v.ZPos() // u is before v
|
||||||
}
|
}
|
||||||
|
|
||||||
case ZPositioner:
|
case ZPositioner:
|
||||||
switch y := v.(type) {
|
switch y := v.(type) {
|
||||||
case BoundingBoxer:
|
case BoundingBoxer:
|
||||||
return x.ZPos() < y.BoundingBox().Min.Z
|
return u.ZPos() < y.BoundingBox().Min.Z
|
||||||
case ZPositioner:
|
case ZPositioner:
|
||||||
return x.ZPos() < y.ZPos()
|
return u.ZPos() < y.ZPos()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +82,8 @@ func edge(u, v Drawer) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var wholePlane = image.Rect(math.MinInt, math.MinInt, math.MaxInt, math.MaxInt)
|
||||||
|
|
||||||
// Topological sort. Uses a projection π to flatten bounding boxes for
|
// Topological sort. Uses a projection π to flatten bounding boxes for
|
||||||
// overlap tests, in order to reduce edge count.
|
// overlap tests, in order to reduce edge count.
|
||||||
func (d *drawList) topsort(π geom.Projector) {
|
func (d *drawList) topsort(π geom.Projector) {
|
||||||
|
@ -86,7 +98,7 @@ func (d *drawList) topsort(π geom.Projector) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// If we can't get a more specific bounding rect, assume entire plane.
|
// If we can't get a more specific bounding rect, assume entire plane.
|
||||||
ub := image.Rect(math.MinInt, math.MinInt, math.MaxInt, math.MaxInt)
|
ub := wholePlane
|
||||||
if x, ok := u.(BoundingBoxer); ok {
|
if x, ok := u.(BoundingBoxer); ok {
|
||||||
ub = x.BoundingBox().BoundingRect(π)
|
ub = x.BoundingBox().BoundingRect(π)
|
||||||
}
|
}
|
||||||
|
@ -103,7 +115,7 @@ func (d *drawList) topsort(π geom.Projector) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the edge goes u->v, add it.
|
// If the edge goes u->v, add it.
|
||||||
if edge(u, v) {
|
if edge(u, v, π.Sign()) {
|
||||||
edges[i] = append(edges[i], j)
|
edges[i] = append(edges[i], j)
|
||||||
indegree[j]++
|
indegree[j]++
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ type Game struct {
|
||||||
Hides
|
Hides
|
||||||
ScreenSize image.Point
|
ScreenSize image.Point
|
||||||
Root interface{} // typically a *Scene or SceneRef though
|
Root interface{} // typically a *Scene or SceneRef though
|
||||||
Projection geom.IntProjection
|
Projection geom.Projector
|
||||||
VoxelScale geom.Float3
|
VoxelScale geom.Float3
|
||||||
|
|
||||||
dbmu sync.RWMutex
|
dbmu sync.RWMutex
|
||||||
|
|
|
@ -196,15 +196,15 @@ func (aw *Awakeman) realUpdate() error {
|
||||||
// Left, right, away, toward
|
// Left, right, away, toward
|
||||||
aw.vel.X, aw.vel.Z = 0, 0
|
aw.vel.X, aw.vel.Z = 0, 0
|
||||||
switch {
|
switch {
|
||||||
case ebiten.IsKeyPressed(ebiten.KeyLeft):
|
case ebiten.IsKeyPressed(ebiten.KeyLeft) || ebiten.IsKeyPressed(ebiten.KeyJ):
|
||||||
aw.vel.X = -runVelocity
|
aw.vel.X = -runVelocity
|
||||||
case ebiten.IsKeyPressed(ebiten.KeyRight):
|
case ebiten.IsKeyPressed(ebiten.KeyRight) || ebiten.IsKeyPressed(ebiten.KeyL):
|
||||||
aw.vel.X = runVelocity
|
aw.vel.X = runVelocity
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case ebiten.IsKeyPressed(ebiten.KeyUp):
|
case ebiten.IsKeyPressed(ebiten.KeyUp) || ebiten.IsKeyPressed(ebiten.KeyI):
|
||||||
aw.vel.Z = -runVelocity
|
aw.vel.Z = -runVelocity
|
||||||
case ebiten.IsKeyPressed(ebiten.KeyDown):
|
case ebiten.IsKeyPressed(ebiten.KeyDown) || ebiten.IsKeyPressed(ebiten.KeyK):
|
||||||
aw.vel.Z = runVelocity
|
aw.vel.Z = runVelocity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,10 +71,6 @@ func (b Box) Canon() Box {
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
type Projector interface {
|
|
||||||
Project(Int3) image.Point
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoundingRect returns an image.Rectangle that bounds the box if it were
|
// BoundingRect returns an image.Rectangle that bounds the box if it were
|
||||||
// projected.
|
// projected.
|
||||||
func (b Box) BoundingRect(π Projector) image.Rectangle {
|
func (b Box) BoundingRect(π Projector) image.Rectangle {
|
||||||
|
|
|
@ -2,9 +2,22 @@ package geom
|
||||||
|
|
||||||
import "image"
|
import "image"
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// Project projects a 3D point into 2D.
|
||||||
|
Project(Int3) image.Point
|
||||||
|
}
|
||||||
|
|
||||||
// Projection uses floats to define a projection.
|
// Projection uses floats to define a projection.
|
||||||
type Projection struct{ X, Y float64 }
|
type Projection struct{ X, Y float64 }
|
||||||
|
|
||||||
|
func (π Projection) Sign() (s image.Point) {
|
||||||
|
return image.Pt(int(FSign(π.X)), int(FSign(π.Y)))
|
||||||
|
}
|
||||||
|
|
||||||
// Project performs a parallel projection of a 3D coordiante into 2D.
|
// Project performs a parallel projection of a 3D coordiante into 2D.
|
||||||
// x projects to (x + z*π.X), and y to (y + z*π.Y)
|
// x projects to (x + z*π.X), and y to (y + z*π.Y)
|
||||||
func (π Projection) Project(p Int3) image.Point {
|
func (π Projection) Project(p Int3) image.Point {
|
||||||
|
@ -19,6 +32,8 @@ func (π Projection) Project(p Int3) image.Point {
|
||||||
// be used in e.g. a diametric projection (IntProjection{X:0, Y:-2}).
|
// be used in e.g. a diametric projection (IntProjection{X:0, Y:-2}).
|
||||||
type IntProjection image.Point
|
type IntProjection image.Point
|
||||||
|
|
||||||
|
func (π IntProjection) Sign() image.Point { return image.Point(π) }
|
||||||
|
|
||||||
// Project performs an integer parallel projection of a 3D coordinate into 2D.
|
// Project performs an integer parallel projection of a 3D coordinate into 2D.
|
||||||
// If π.X = 0, the x returned is p.X; similarly for π.Y and y.
|
// If π.X = 0, the x returned is p.X; similarly for π.Y and y.
|
||||||
// Otherwise, x projects to x + z/π.X and y projects to y + z/π.Y.
|
// Otherwise, x projects to x + z/π.X and y projects to y + z/π.Y.
|
||||||
|
|
Loading…
Reference in a new issue