github.com/df-mc/dragonfly@v0.9.13/server/block/cube/rotation.go (about)

     1  package cube
     2  
     3  import (
     4  	"github.com/go-gl/mathgl/mgl64"
     5  	"math"
     6  )
     7  
     8  // Rotation describes the rotation of an object in the world. It holds a yaw
     9  // (r[0]) and pitch value (r[1]). Yaw is in the range (-180, 180) while pitch is
    10  // in the range (-90, 90). A positive pitch implies an entity is looking
    11  // downwards, while a negative pitch implies it is looking upwards.
    12  type Rotation [2]float64
    13  
    14  // Yaw returns the yaw of r (r[0]).
    15  func (r Rotation) Yaw() float64 {
    16  	return r[0]
    17  }
    18  
    19  // Pitch returns the pitch of r (r[1]).
    20  func (r Rotation) Pitch() float64 {
    21  	return r[1]
    22  }
    23  
    24  // Elem extracts the elements of the Rotation for direct value assignment.
    25  func (r Rotation) Elem() (yaw, pitch float64) {
    26  	return r[0], r[1]
    27  }
    28  
    29  // Add adds the values of two Rotations element-wise and returns a new Rotation.
    30  // If the yaw or pitch would otherwise exceed their respective range as
    31  // described, they are 'overflown' to the other end of the allowed range.
    32  func (r Rotation) Add(r2 Rotation) Rotation {
    33  	return Rotation{r[0] + r2[0], r[1] + r2[1]}.fix()
    34  }
    35  
    36  // Opposite returns the Rotation opposite r, so that
    37  // r.Vec3().Add(r.Opposite().Vec3()).Len() is equal to 0.
    38  func (r Rotation) Opposite() Rotation {
    39  	return Rotation{r[0] + 180, -r[1]}.fix()
    40  }
    41  
    42  // Direction returns the horizontal Direction that r points towards based on the
    43  // yaw of r.
    44  func (r Rotation) Direction() Direction {
    45  	yaw := r.fix().Yaw()
    46  	switch {
    47  	case yaw > 45 && yaw <= 135:
    48  		return West
    49  	case yaw > -45 && yaw <= 45:
    50  		return South
    51  	case yaw > -135 && yaw <= -45:
    52  		return East
    53  	case yaw <= -135 || yaw > 135:
    54  		return North
    55  	}
    56  	return 0
    57  }
    58  
    59  // Orientation returns an Orientation value that most closely matches the yaw
    60  // of r.
    61  func (r Rotation) Orientation() Orientation {
    62  	const step = 360 / 16.0
    63  
    64  	yaw := r.fix().Yaw()
    65  	if yaw < -step/2 {
    66  		yaw += 360
    67  	}
    68  	return Orientation(math.Round(yaw / step))
    69  }
    70  
    71  // Vec3 returns the direction vector of r. The length of the mgl64.Vec3 returned
    72  // is always 1.
    73  func (r Rotation) Vec3() mgl64.Vec3 {
    74  	yaw, pitch := r.fix().Elem()
    75  	yawRad, pitchRad := mgl64.DegToRad(yaw), mgl64.DegToRad(pitch)
    76  
    77  	m := math.Cos(pitchRad)
    78  	return mgl64.Vec3{
    79  		-m * math.Sin(yawRad),
    80  		-math.Sin(pitchRad),
    81  		m * math.Cos(yawRad),
    82  	}
    83  }
    84  
    85  // fix 'overflows' the Rotation's values to make sure they are within the range
    86  // as described above.
    87  func (r Rotation) fix() Rotation {
    88  	return Rotation{
    89  		math.Mod(r[0]+180, 360) - 180,
    90  		math.Mod(r[1]+90, 180) - 90,
    91  	}
    92  }