dep -> govendor
This commit is contained in:
59
vendor/github.com/go-gl/mathgl/mgl32/matstack/matstack.go
generated
vendored
Normal file
59
vendor/github.com/go-gl/mathgl/mgl32/matstack/matstack.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
package matstack
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/go-gl/mathgl/mgl32"
|
||||
)
|
||||
|
||||
// A MatStack is an OpenGL-style matrix stack,
|
||||
// usually used for things like scenegraphs. This allows you
|
||||
// to easily maintain matrix state per call level.
|
||||
type MatStack []mgl32.Mat4
|
||||
|
||||
func NewMatStack() *MatStack {
|
||||
return &MatStack{mgl32.Ident4()}
|
||||
}
|
||||
|
||||
// Copies the top element and pushes it on the stack.
|
||||
func (ms *MatStack) Push() {
|
||||
(*ms) = append(*ms, (*ms)[len(*ms)-1])
|
||||
}
|
||||
|
||||
// Removes the first element of the matrix from the stack, if there is only one element left
|
||||
// there is an error.
|
||||
func (ms *MatStack) Pop() error {
|
||||
if len(*ms) == 1 {
|
||||
return errors.New("Cannot pop from mat stack, at minimum stack length of 1")
|
||||
}
|
||||
(*ms) = (*ms)[:len(*ms)-1]
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Right multiplies the current top of the matrix by the
|
||||
// argument.
|
||||
func (ms *MatStack) RightMul(m mgl32.Mat4) {
|
||||
(*ms)[len(*ms)-1] = (*ms)[len(*ms)-1].Mul4(m)
|
||||
}
|
||||
|
||||
// Left multiplies the current top of the matrix by the
|
||||
// argument.
|
||||
func (ms *MatStack) LeftMul(m mgl32.Mat4) {
|
||||
(*ms)[len(*ms)-1] = m.Mul4((*ms)[len(*ms)-1])
|
||||
}
|
||||
|
||||
// Returns the top element.
|
||||
func (ms *MatStack) Peek() mgl32.Mat4 {
|
||||
return (*ms)[len(*ms)-1]
|
||||
}
|
||||
|
||||
// Rewrites the top element of the stack with m
|
||||
func (ms *MatStack) Load(m mgl32.Mat4) {
|
||||
(*ms)[len(*ms)-1] = m
|
||||
}
|
||||
|
||||
// A shortcut for Load(mgl.Ident4())
|
||||
func (ms *MatStack) LoadIdent() {
|
||||
(*ms)[len(*ms)-1] = mgl32.Ident4()
|
||||
}
|
174
vendor/github.com/go-gl/mathgl/mgl32/matstack/transformStack.go
generated
vendored
Normal file
174
vendor/github.com/go-gl/mathgl/mgl32/matstack/transformStack.go
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
package matstack
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-gl/mathgl/mgl32"
|
||||
)
|
||||
|
||||
// A transform stack is a linear fully-persistent data structure of matrix multiplications
|
||||
// Each push to a TransformStack multiplies the current top of the stack with thew new matrix
|
||||
// and appends it to the top. Each pop undoes the previous multiplication.
|
||||
//
|
||||
// This allows arbitrary unwinding of transformations, at the cost of a lot of memory. A notable feature
|
||||
// is the reseed and rebase, which allow invertible transformations to be rewritten as if a different transform
|
||||
// had been made in the middle.
|
||||
type TransformStack []mgl32.Mat4
|
||||
|
||||
// Returns a matrix stack where the top element is the identity.
|
||||
func NewTransformStack() *TransformStack {
|
||||
ms := make(TransformStack, 1)
|
||||
ms[0] = mgl32.Ident4()
|
||||
|
||||
return &ms
|
||||
}
|
||||
|
||||
// Multiplies the current top matrix by m, and pushes the result
|
||||
// on the stack.
|
||||
func (ms *TransformStack) Push(m mgl32.Mat4) {
|
||||
prev := (*ms)[len(*ms)-1]
|
||||
(*ms) = append(*ms, prev.Mul4(m))
|
||||
}
|
||||
|
||||
// Pops the current matrix off the top of the stack and returns it.
|
||||
// If the matrix stack only has one element left, this will return an error.
|
||||
func (ms *TransformStack) Pop() (mgl32.Mat4, error) {
|
||||
if len(*ms) == 1 {
|
||||
return mgl32.Mat4{}, errors.New("attempt to pop last element of the stack; Matrix Stack must have at least one element")
|
||||
}
|
||||
|
||||
retVal := (*ms)[len(*ms)-1]
|
||||
|
||||
(*ms) = (*ms)[:len(*ms)-1]
|
||||
|
||||
return retVal, nil
|
||||
}
|
||||
|
||||
// Returns the value of the current top element of the stack, without
|
||||
// removing it.
|
||||
func (ms *TransformStack) Peek() mgl32.Mat4 {
|
||||
return (*ms)[len(*ms)-1]
|
||||
}
|
||||
|
||||
// Returns the size of the matrix stack. This value will never be less
|
||||
// than 1.
|
||||
func (ms *TransformStack) Len() int {
|
||||
return len(*ms)
|
||||
}
|
||||
|
||||
// This cuts down the matrix as if Pop had been called n times. If n would
|
||||
// bring the matrix down below 1 element, this does nothing and returns an error.
|
||||
func (ms *TransformStack) Unwind(n int) error {
|
||||
if n > len(*ms)-1 {
|
||||
return errors.New("Cannot unwind a matrix to below 1 value")
|
||||
}
|
||||
|
||||
(*ms) = (*ms)[:len(*ms)-n]
|
||||
return nil
|
||||
}
|
||||
|
||||
// Copy will create a new "branch" of the current matrix stack,
|
||||
// the copy will contain all elements of the current stack in a new stack. Changes to
|
||||
// one will never affect the other.
|
||||
func (ms *TransformStack) Copy() *TransformStack {
|
||||
v := append(TransformStack{}, (*ms)...)
|
||||
return &v
|
||||
}
|
||||
|
||||
// Reseed is tricky. It attempts to seed an arbitrary point in the matrix and replay all transformations
|
||||
// as if that point in the push had been the argument "change" instead of the original value.
|
||||
// The matrix stack does NOT keep track of arguments so this is done via consecutive inverses.
|
||||
// If the inverse of element i can be found, we can calculate the transformation that was given at point i+1.
|
||||
// This transformation can then be multiplied by the NEW matrix at point i to complete the "what if".
|
||||
// If no such inverse can be found at any given point along the rebase, it will be aborted, and the original
|
||||
// stack will NOT be visibly affected. The error returned will be of type NoInverseError.
|
||||
//
|
||||
// If n is out of bounds (n <= 0 || n >= len(*ms)), a generic error from the errors package will be returned.
|
||||
//
|
||||
// If you have the old transformations retained, it is recommended
|
||||
// that you use Unwind followed by Push(change) and then further calling Push for each transformation. Rebase is
|
||||
// imprecise by nature, and sometimes impossible. It's also expensive due to the inverse calculation at each point.
|
||||
func (ms *TransformStack) Reseed(n int, change mgl32.Mat4) error {
|
||||
if n >= len(*ms) || n <= 0 {
|
||||
return errors.New("Cannot rebase at the given point on the stack, it is out of bounds.")
|
||||
}
|
||||
|
||||
return ms.reseed(n, change)
|
||||
}
|
||||
|
||||
// Operates like reseed with no bounds checking; allows us to overwrite
|
||||
// the leading identity matrix with Rebase.
|
||||
func (ms *TransformStack) reseed(n int, change mgl32.Mat4) error {
|
||||
backup := []mgl32.Mat4((*ms)[n:])
|
||||
backup = append([]mgl32.Mat4{}, backup...) // copy into new slice
|
||||
|
||||
curr := (*ms)[n]
|
||||
(*ms)[n] = (*ms)[n-1].Mul4(change)
|
||||
|
||||
for i := n + 1; i < len(*ms); i++ {
|
||||
inv := curr.Inv()
|
||||
|
||||
blank := mgl32.Mat4{}
|
||||
if inv == blank {
|
||||
ms.undoRebase(n, backup)
|
||||
return NoInverseError{Loc: i - 1, Mat: curr}
|
||||
}
|
||||
|
||||
ghost := inv.Mul4((*ms)[i])
|
||||
|
||||
curr = (*ms)[i]
|
||||
(*ms)[i] = (*ms)[i-1].Mul4(ghost)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ms *TransformStack) undoRebase(n int, prev []mgl32.Mat4) {
|
||||
for i := n; i < len(*ms); i++ {
|
||||
(*ms)[i] = prev[i-n]
|
||||
}
|
||||
}
|
||||
|
||||
// Rebase replays the current matrix stack as if the transformation that occurred at index "from"
|
||||
// in ms had instead started at the top of m.
|
||||
//
|
||||
// This returns a brand new stack containing all of m followed by all transformations
|
||||
// at from and after on ms as if they has been done on m instead.
|
||||
func Rebase(ms *TransformStack, from int, m *TransformStack) (*TransformStack, error) {
|
||||
if from <= 0 || from >= len(*ms) {
|
||||
return nil, errors.New("Cannot rebase, index out of range")
|
||||
}
|
||||
|
||||
// Shift tmp so that the element immediately
|
||||
// preceding our target is the "top" element of the list.
|
||||
tmp := ms.Copy()
|
||||
if from == 1 {
|
||||
(*tmp) = append(*tmp, mgl32.Mat4{})
|
||||
}
|
||||
copy((*tmp)[1:], (*tmp)[from-1:])
|
||||
if from-2 > 0 {
|
||||
(*tmp) = (*tmp)[:len(*tmp)-(from-2)]
|
||||
}
|
||||
|
||||
err := tmp.Reseed(1, m.Peek())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
(*tmp) = append(*m, (*tmp)[2:]...)
|
||||
|
||||
return tmp, nil
|
||||
}
|
||||
|
||||
// A NoInverseError is returned on rebase when an inverse cannot be found along the chain,
|
||||
// due to a transformation projecting the matrix into a singularity. The values include the matrix
|
||||
// no inverse can be found for, and the location of that matrix.
|
||||
type NoInverseError struct {
|
||||
Mat mgl32.Mat4
|
||||
Loc int
|
||||
}
|
||||
|
||||
func (nie NoInverseError) Error() string {
|
||||
return fmt.Sprintf("cannot find inverse of matrix %v at location %d in matrix stack, aborting rebase/reseed", nie.Mat, nie.Loc)
|
||||
}
|
Reference in New Issue
Block a user