Use dep to vendor things
This commit is contained in:
21
vendor/github.com/go-gl/gl/LICENSE
generated
vendored
Normal file
21
vendor/github.com/go-gl/gl/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Eric Woroshow
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
109
vendor/github.com/go-gl/gl/v3.3-core/gl/conversions.go
generated
vendored
Normal file
109
vendor/github.com/go-gl/gl/v3.3-core/gl/conversions.go
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
// Glow automatically generated OpenGL binding: http://github.com/go-gl/glow
|
||||
|
||||
package gl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
// Ptr takes a slice or pointer (to a singular scalar value or the first
|
||||
// element of an array or slice) and returns its GL-compatible address.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// var data []uint8
|
||||
// ...
|
||||
// gl.TexImage2D(gl.TEXTURE_2D, ..., gl.UNSIGNED_BYTE, gl.Ptr(&data[0]))
|
||||
func Ptr(data interface{}) unsafe.Pointer {
|
||||
if data == nil {
|
||||
return unsafe.Pointer(nil)
|
||||
}
|
||||
var addr unsafe.Pointer
|
||||
v := reflect.ValueOf(data)
|
||||
switch v.Type().Kind() {
|
||||
case reflect.Ptr:
|
||||
e := v.Elem()
|
||||
switch e.Kind() {
|
||||
case
|
||||
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64:
|
||||
addr = unsafe.Pointer(e.UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported pointer to type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", e.Kind()))
|
||||
}
|
||||
case reflect.Uintptr:
|
||||
addr = unsafe.Pointer(v.Pointer())
|
||||
case reflect.Slice:
|
||||
addr = unsafe.Pointer(v.Index(0).UnsafeAddr())
|
||||
default:
|
||||
panic(fmt.Errorf("unsupported type %s; must be a slice or pointer to a singular scalar value or the first element of an array or slice", v.Type()))
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
||||
// PtrOffset takes a pointer offset and returns a GL-compatible pointer.
|
||||
// Useful for functions such as glVertexAttribPointer that take pointer
|
||||
// parameters indicating an offset rather than an absolute memory address.
|
||||
func PtrOffset(offset int) unsafe.Pointer {
|
||||
return unsafe.Pointer(uintptr(offset))
|
||||
}
|
||||
|
||||
// Str takes a null-terminated Go string and returns its GL-compatible address.
|
||||
// This function reaches into Go string storage in an unsafe way so the caller
|
||||
// must ensure the string is not garbage collected.
|
||||
func Str(str string) *uint8 {
|
||||
if !strings.HasSuffix(str, "\x00") {
|
||||
panic("str argument missing null terminator: " + str)
|
||||
}
|
||||
header := (*reflect.StringHeader)(unsafe.Pointer(&str))
|
||||
return (*uint8)(unsafe.Pointer(header.Data))
|
||||
}
|
||||
|
||||
// GoStr takes a null-terminated string returned by OpenGL and constructs a
|
||||
// corresponding Go string.
|
||||
func GoStr(cstr *uint8) string {
|
||||
return C.GoString((*C.char)(unsafe.Pointer(cstr)))
|
||||
}
|
||||
|
||||
// Strs takes a list of Go strings (with or without null-termination) and
|
||||
// returns their C counterpart.
|
||||
//
|
||||
// The returned free function must be called once you are done using the strings
|
||||
// in order to free the memory.
|
||||
//
|
||||
// If no strings are provided as a parameter this function will panic.
|
||||
func Strs(strs ...string) (cstrs **uint8, free func()) {
|
||||
if len(strs) == 0 {
|
||||
panic("Strs: expected at least 1 string")
|
||||
}
|
||||
|
||||
// Allocate a contiguous array large enough to hold all the strings' contents.
|
||||
n := 0
|
||||
for i := range strs {
|
||||
n += len(strs[i])
|
||||
}
|
||||
data := C.malloc(C.size_t(n))
|
||||
|
||||
// Copy all the strings into data.
|
||||
dataSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: uintptr(data),
|
||||
Len: n,
|
||||
Cap: n,
|
||||
}))
|
||||
css := make([]*uint8, len(strs)) // Populated with pointers to each string.
|
||||
offset := 0
|
||||
for i := range strs {
|
||||
copy(dataSlice[offset:offset+len(strs[i])], strs[i][:]) // Copy strs[i] into proper data location.
|
||||
css[i] = (*uint8)(unsafe.Pointer(&dataSlice[offset])) // Set a pointer to it.
|
||||
offset += len(strs[i])
|
||||
}
|
||||
|
||||
return (**uint8)(&css[0]), func() { C.free(data) }
|
||||
}
|
31
vendor/github.com/go-gl/gl/v3.3-core/gl/debug.go
generated
vendored
Normal file
31
vendor/github.com/go-gl/gl/v3.3-core/gl/debug.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Glow automatically generated OpenGL binding: http://github.com/go-gl/glow
|
||||
|
||||
package gl
|
||||
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
type DebugProc func(
|
||||
source uint32,
|
||||
gltype uint32,
|
||||
id uint32,
|
||||
severity uint32,
|
||||
length int32,
|
||||
message string,
|
||||
userParam unsafe.Pointer)
|
||||
|
||||
var userDebugCallback DebugProc
|
||||
|
||||
//export glowDebugCallback_glcore33
|
||||
func glowDebugCallback_glcore33(
|
||||
source uint32,
|
||||
gltype uint32,
|
||||
id uint32,
|
||||
severity uint32,
|
||||
length int32,
|
||||
message *uint8,
|
||||
userParam unsafe.Pointer) {
|
||||
if userDebugCallback != nil {
|
||||
userDebugCallback(source, gltype, id, severity, length, GoStr(message), userParam)
|
||||
}
|
||||
}
|
9882
vendor/github.com/go-gl/gl/v3.3-core/gl/package.go
generated
vendored
Normal file
9882
vendor/github.com/go-gl/gl/v3.3-core/gl/package.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
65
vendor/github.com/go-gl/gl/v3.3-core/gl/procaddr.go
generated
vendored
Normal file
65
vendor/github.com/go-gl/gl/v3.3-core/gl/procaddr.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// This file implements GlowGetProcAddress for every supported platform. The
|
||||
// correct version is chosen automatically based on build tags:
|
||||
// windows: WGL
|
||||
// darwin: CGL
|
||||
// linux freebsd: GLX
|
||||
// Use of EGL instead of the platform's default (listed above) is made possible
|
||||
// via the "egl" build tag.
|
||||
// It is also possible to install your own function outside this package for
|
||||
// retrieving OpenGL function pointers, to do this see InitWithProcAddrFunc.
|
||||
package gl
|
||||
|
||||
/*
|
||||
#cgo windows CFLAGS: -DTAG_WINDOWS
|
||||
#cgo windows LDFLAGS: -lopengl32
|
||||
#cgo darwin CFLAGS: -DTAG_DARWIN
|
||||
#cgo darwin LDFLAGS: -framework OpenGL
|
||||
#cgo linux freebsd CFLAGS: -DTAG_POSIX
|
||||
#cgo linux freebsd LDFLAGS: -lGL
|
||||
#cgo egl CFLAGS: -DTAG_EGL
|
||||
#cgo egl LDFLAGS: -lEGL
|
||||
// Check the EGL tag first as it takes priority over the platform's default
|
||||
// configuration of WGL/GLX/CGL.
|
||||
#if defined(TAG_EGL)
|
||||
#include <stdlib.h>
|
||||
#include <EGL/egl.h>
|
||||
void* GlowGetProcAddress_glcore33(const char* name) {
|
||||
return eglGetProcAddress(name);
|
||||
}
|
||||
#elif defined(TAG_WINDOWS)
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
static HMODULE ogl32dll = NULL;
|
||||
void* GlowGetProcAddress_glcore33(const char* name) {
|
||||
void* pf = wglGetProcAddress((LPCSTR) name);
|
||||
if (pf) {
|
||||
return pf;
|
||||
}
|
||||
if (ogl32dll == NULL) {
|
||||
ogl32dll = LoadLibraryA("opengl32.dll");
|
||||
}
|
||||
return GetProcAddress(ogl32dll, (LPCSTR) name);
|
||||
}
|
||||
#elif defined(TAG_DARWIN)
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
void* GlowGetProcAddress_glcore33(const char* name) {
|
||||
return dlsym(RTLD_DEFAULT, name);
|
||||
}
|
||||
#elif defined(TAG_POSIX)
|
||||
#include <stdlib.h>
|
||||
#include <GL/glx.h>
|
||||
void* GlowGetProcAddress_glcore33(const char* name) {
|
||||
return glXGetProcAddress(name);
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func getProcAddress(namea string) unsafe.Pointer {
|
||||
cname := C.CString(namea)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
return C.GlowGetProcAddress_glcore33(cname)
|
||||
}
|
10
vendor/github.com/go-gl/glfw/AUTHORS
generated
vendored
Normal file
10
vendor/github.com/go-gl/glfw/AUTHORS
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
# This is the official list of glfw3-go authors for copyright purposes.
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Coşku Baş
|
||||
Dmitri Shuralyov
|
||||
James Gray
|
||||
Peter Waller <p@pwaller.net> (github:pwaller)
|
||||
Robin Eklind
|
||||
Stephen Gutekanst
|
27
vendor/github.com/go-gl/glfw/LICENSE
generated
vendored
Normal file
27
vendor/github.com/go-gl/glfw/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
Copyright (c) 2012 The glfw3-go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
22
vendor/github.com/go-gl/glfw/v3.1/glfw/glfw/COPYING.txt
generated
vendored
Normal file
22
vendor/github.com/go-gl/glfw/v3.1/glfw/glfw/COPYING.txt
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2002-2006 Marcus Geelnard
|
||||
Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would
|
||||
be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
1
vendor/github.com/go-gl/glfw/v3.2/glfw/GLFW_C_REVISION.txt
generated
vendored
Normal file
1
vendor/github.com/go-gl/glfw/v3.2/glfw/GLFW_C_REVISION.txt
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
999f3556fdd80983b10051746264489f2cb1ef16
|
43
vendor/github.com/go-gl/glfw/v3.2/glfw/build.go
generated
vendored
Normal file
43
vendor/github.com/go-gl/glfw/v3.2/glfw/build.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
package glfw
|
||||
|
||||
/*
|
||||
// Windows Build Tags
|
||||
// ----------------
|
||||
// GLFW Options:
|
||||
#cgo windows CFLAGS: -D_GLFW_WIN32 -Iglfw/deps/mingw
|
||||
|
||||
// Linker Options:
|
||||
#cgo windows LDFLAGS: -lopengl32 -lgdi32
|
||||
|
||||
|
||||
// Darwin Build Tags
|
||||
// ----------------
|
||||
// GLFW Options:
|
||||
#cgo darwin CFLAGS: -D_GLFW_COCOA -D_GLFW_USE_CHDIR -D_GLFW_USE_MENUBAR -D_GLFW_USE_RETINA -Wno-deprecated-declarations
|
||||
|
||||
// Linker Options:
|
||||
#cgo darwin LDFLAGS: -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo
|
||||
|
||||
|
||||
// Linux Build Tags
|
||||
// ----------------
|
||||
// GLFW Options:
|
||||
#cgo linux,!wayland CFLAGS: -D_GLFW_X11
|
||||
#cgo linux,wayland CFLAGS: -D_GLFW_WAYLAND
|
||||
|
||||
// Linker Options:
|
||||
#cgo linux,!wayland LDFLAGS: -lGL -lX11 -lXrandr -lXxf86vm -lXi -lXcursor -lm -lXinerama -ldl -lrt
|
||||
#cgo linux,wayland LDFLAGS: -lGL -lX11 -lXrandr -lXxf86vm -lXi -lXcursor -lm -lXinerama -ldl -lrt
|
||||
|
||||
|
||||
// FreeBSD Build Tags
|
||||
// ----------------
|
||||
// GLFW Options:
|
||||
#cgo freebsd,!wayland CFLAGS: -D_GLFW_X11 -D_GLFW_HAS_GLXGETPROCADDRESSARB -D_GLFW_HAS_DLOPEN
|
||||
#cgo freebsd,wayland CFLAGS: -D_GLFW_WAYLAND -D_GLFW_HAS_DLOPEN
|
||||
|
||||
// Linker Options:
|
||||
#cgo freebsd,!wayland LDFLAGS: -lGL -lX11 -lXrandr -lXxf86vm -lXi -lXcursor -lm -lXinerama
|
||||
#cgo freebsd,wayland LDFLAGS: -lGL -lX11 -lXrandr -lXxf86vm -lXi -lXcursor -lm -lXinerama
|
||||
*/
|
||||
import "C"
|
11
vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw.go
generated
vendored
Normal file
11
vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw.go
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
package glfw
|
||||
|
||||
/*
|
||||
#include "glfw/src/context.c"
|
||||
#include "glfw/src/init.c"
|
||||
#include "glfw/src/input.c"
|
||||
#include "glfw/src/monitor.c"
|
||||
#include "glfw/src/vulkan.c"
|
||||
#include "glfw/src/window.c"
|
||||
*/
|
||||
import "C"
|
13
vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw_darwin.go
generated
vendored
Normal file
13
vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
package glfw
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -x objective-c
|
||||
#include "glfw/src/cocoa_init.m"
|
||||
#include "glfw/src/cocoa_joystick.m"
|
||||
#include "glfw/src/cocoa_monitor.m"
|
||||
#include "glfw/src/cocoa_window.m"
|
||||
#include "glfw/src/cocoa_time.c"
|
||||
#include "glfw/src/posix_tls.c"
|
||||
#include "glfw/src/nsgl_context.m"
|
||||
*/
|
||||
import "C"
|
28
vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw_linbsd.go
generated
vendored
Normal file
28
vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw_linbsd.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// +build linux freebsd
|
||||
|
||||
package glfw
|
||||
|
||||
/*
|
||||
#ifdef _GLFW_MIR
|
||||
#include "glfw/src/mir_init.c"
|
||||
#include "glfw/src/mir_monitor.c"
|
||||
#include "glfw/src/mir_window.c"
|
||||
#endif
|
||||
#ifdef _GLFW_WAYLAND
|
||||
#include "glfw/src/wl_init.c"
|
||||
#include "glfw/src/wl_monitor.c"
|
||||
#include "glfw/src/wl_window.c"
|
||||
#endif
|
||||
#ifdef _GLFW_X11
|
||||
#include "glfw/src/x11_init.c"
|
||||
#include "glfw/src/x11_monitor.c"
|
||||
#include "glfw/src/x11_window.c"
|
||||
#include "glfw/src/glx_context.c"
|
||||
#endif
|
||||
#include "glfw/src/linux_joystick.c"
|
||||
#include "glfw/src/posix_time.c"
|
||||
#include "glfw/src/posix_tls.c"
|
||||
#include "glfw/src/xkb_unicode.c"
|
||||
#include "glfw/src/egl_context.c"
|
||||
*/
|
||||
import "C"
|
13
vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw_windows.go
generated
vendored
Normal file
13
vendor/github.com/go-gl/glfw/v3.2/glfw/c_glfw_windows.go
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
package glfw
|
||||
|
||||
/*
|
||||
#include "glfw/src/win32_init.c"
|
||||
#include "glfw/src/win32_joystick.c"
|
||||
#include "glfw/src/win32_monitor.c"
|
||||
#include "glfw/src/win32_time.c"
|
||||
#include "glfw/src/win32_tls.c"
|
||||
#include "glfw/src/win32_window.c"
|
||||
#include "glfw/src/wgl_context.c"
|
||||
#include "glfw/src/egl_context.c"
|
||||
*/
|
||||
import "C"
|
77
vendor/github.com/go-gl/glfw/v3.2/glfw/context.go
generated
vendored
Normal file
77
vendor/github.com/go-gl/glfw/v3.2/glfw/context.go
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
package glfw
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include "glfw/include/GLFW/glfw3.h"
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// MakeContextCurrent makes the context of the window current.
|
||||
// Originally GLFW 3 passes a null pointer to detach the context.
|
||||
// But since we're using receievers, DetachCurrentContext should
|
||||
// be used instead.
|
||||
func (w *Window) MakeContextCurrent() {
|
||||
C.glfwMakeContextCurrent(w.data)
|
||||
panicError()
|
||||
}
|
||||
|
||||
// DetachCurrentContext detaches the current context.
|
||||
func DetachCurrentContext() {
|
||||
C.glfwMakeContextCurrent(nil)
|
||||
panicError()
|
||||
}
|
||||
|
||||
// GetCurrentContext returns the window whose context is current.
|
||||
func GetCurrentContext() *Window {
|
||||
w := C.glfwGetCurrentContext()
|
||||
panicError()
|
||||
if w == nil {
|
||||
return nil
|
||||
}
|
||||
return windows.get(w)
|
||||
}
|
||||
|
||||
// SwapBuffers swaps the front and back buffers of the window. If the
|
||||
// swap interval is greater than zero, the GPU driver waits the specified number
|
||||
// of screen updates before swapping the buffers.
|
||||
func (w *Window) SwapBuffers() {
|
||||
C.glfwSwapBuffers(w.data)
|
||||
panicError()
|
||||
}
|
||||
|
||||
// SwapInterval sets the swap interval for the current context, i.e. the number
|
||||
// of screen updates to wait before swapping the buffers of a window and
|
||||
// returning from SwapBuffers. This is sometimes called
|
||||
// 'vertical synchronization', 'vertical retrace synchronization' or 'vsync'.
|
||||
//
|
||||
// Contexts that support either of the WGL_EXT_swap_control_tear and
|
||||
// GLX_EXT_swap_control_tear extensions also accept negative swap intervals,
|
||||
// which allow the driver to swap even if a frame arrives a little bit late.
|
||||
// You can check for the presence of these extensions using
|
||||
// ExtensionSupported. For more information about swap tearing,
|
||||
// see the extension specifications.
|
||||
//
|
||||
// Some GPU drivers do not honor the requested swap interval, either because of
|
||||
// user settings that override the request or due to bugs in the driver.
|
||||
func SwapInterval(interval int) {
|
||||
C.glfwSwapInterval(C.int(interval))
|
||||
panicError()
|
||||
}
|
||||
|
||||
// ExtensionSupported reports whether the specified OpenGL or context creation
|
||||
// API extension is supported by the current context. For example, on Windows
|
||||
// both the OpenGL and WGL extension strings are checked.
|
||||
//
|
||||
// As this functions searches one or more extension strings on each call, it is
|
||||
// recommended that you cache its results if it's going to be used frequently.
|
||||
// The extension strings will not change during the lifetime of a context, so
|
||||
// there is no danger in doing this.
|
||||
func ExtensionSupported(extension string) bool {
|
||||
e := C.CString(extension)
|
||||
defer C.free(unsafe.Pointer(e))
|
||||
ret := glfwbool(C.glfwExtensionSupported(e))
|
||||
panicError()
|
||||
return ret
|
||||
}
|
9
vendor/github.com/go-gl/glfw/v3.2/glfw/error.c
generated
vendored
Normal file
9
vendor/github.com/go-gl/glfw/v3.2/glfw/error.c
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "_cgo_export.h"
|
||||
|
||||
void glfwErrorCB(int code, const char *desc) {
|
||||
goErrorCB(code, (char*)desc);
|
||||
}
|
||||
|
||||
void glfwSetErrorCallbackCB() {
|
||||
glfwSetErrorCallback(glfwErrorCB);
|
||||
}
|
199
vendor/github.com/go-gl/glfw/v3.2/glfw/error.go
generated
vendored
Normal file
199
vendor/github.com/go-gl/glfw/v3.2/glfw/error.go
generated
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
package glfw
|
||||
|
||||
//#include "glfw/include/GLFW/glfw3.h"
|
||||
//void glfwSetErrorCallbackCB();
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
// ErrorCode corresponds to an error code.
|
||||
type ErrorCode int
|
||||
|
||||
// Error codes that are translated to panics and the programmer should not
|
||||
// expect to handle.
|
||||
const (
|
||||
notInitialized ErrorCode = C.GLFW_NOT_INITIALIZED // GLFW has not been initialized.
|
||||
noCurrentContext ErrorCode = C.GLFW_NO_CURRENT_CONTEXT // No context is current.
|
||||
invalidEnum ErrorCode = C.GLFW_INVALID_ENUM // One of the enum parameters for the function was given an invalid enum.
|
||||
invalidValue ErrorCode = C.GLFW_INVALID_VALUE // One of the parameters for the function was given an invalid value.
|
||||
outOfMemory ErrorCode = C.GLFW_OUT_OF_MEMORY // A memory allocation failed.
|
||||
platformError ErrorCode = C.GLFW_PLATFORM_ERROR // A platform-specific error occurred that does not match any of the more specific categories.
|
||||
)
|
||||
|
||||
const (
|
||||
// APIUnavailable is the error code used when GLFW could not find support
|
||||
// for the requested client API on the system.
|
||||
//
|
||||
// The installed graphics driver does not support the requested client API,
|
||||
// or does not support it via the chosen context creation backend. Below
|
||||
// are a few examples.
|
||||
//
|
||||
// Some pre-installed Windows graphics drivers do not support OpenGL. AMD
|
||||
// only supports OpenGL ES via EGL, while Nvidia and Intel only supports it
|
||||
// via a WGL or GLX extension. OS X does not provide OpenGL ES at all. The
|
||||
// Mesa EGL, OpenGL and OpenGL ES libraries do not interface with the
|
||||
// Nvidia binary driver.
|
||||
APIUnavailable ErrorCode = C.GLFW_API_UNAVAILABLE
|
||||
|
||||
// VersionUnavailable is the error code used when the requested OpenGL or
|
||||
// OpenGL ES (including any requested profile or context option) is not
|
||||
// available on this machine.
|
||||
//
|
||||
// The machine does not support your requirements. If your application is
|
||||
// sufficiently flexible, downgrade your requirements and try again.
|
||||
// Otherwise, inform the user that their machine does not match your
|
||||
// requirements.
|
||||
//
|
||||
// Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if
|
||||
// 5.0 comes out before the 4.x series gets that far, also fail with this
|
||||
// error and not GLFW_INVALID_VALUE, because GLFW cannot know what future
|
||||
// versions will exist.
|
||||
VersionUnavailable ErrorCode = C.GLFW_VERSION_UNAVAILABLE
|
||||
|
||||
// FormatUnavailable is the error code used for both window creation and
|
||||
// clipboard querying format errors.
|
||||
//
|
||||
// If emitted during window creation, the requested pixel format is not
|
||||
// supported. This means one or more hard constraints did not match any of
|
||||
// the available pixel formats. If your application is sufficiently
|
||||
// flexible, downgrade your requirements and try again. Otherwise, inform
|
||||
// the user that their machine does not match your requirements.
|
||||
//
|
||||
// If emitted when querying the clipboard, the contents of the clipboard
|
||||
// could not be converted to the requested format. You should ignore the
|
||||
// error or report it to the user, as appropriate.
|
||||
FormatUnavailable ErrorCode = C.GLFW_FORMAT_UNAVAILABLE
|
||||
)
|
||||
|
||||
func (e ErrorCode) String() string {
|
||||
switch e {
|
||||
case notInitialized:
|
||||
return "NotInitialized"
|
||||
case noCurrentContext:
|
||||
return "NoCurrentContext"
|
||||
case invalidEnum:
|
||||
return "InvalidEnum"
|
||||
case invalidValue:
|
||||
return "InvalidValue"
|
||||
case outOfMemory:
|
||||
return "OutOfMemory"
|
||||
case platformError:
|
||||
return "PlatformError"
|
||||
case APIUnavailable:
|
||||
return "APIUnavailable"
|
||||
case VersionUnavailable:
|
||||
return "VersionUnavailable"
|
||||
case FormatUnavailable:
|
||||
return "FormatUnavailable"
|
||||
default:
|
||||
return fmt.Sprintf("ErrorCode(%d)", e)
|
||||
}
|
||||
}
|
||||
|
||||
// Error holds error code and description.
|
||||
type Error struct {
|
||||
Code ErrorCode
|
||||
Desc string
|
||||
}
|
||||
|
||||
// Error prints the error code and description in a readable format.
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.Code.String(), e.Desc)
|
||||
}
|
||||
|
||||
// Note: There are many cryptic caveats to proper error handling here.
|
||||
// See: https://github.com/go-gl/glfw3/pull/86
|
||||
|
||||
// Holds the value of the last error.
|
||||
var lastError = make(chan *Error, 1)
|
||||
|
||||
//export goErrorCB
|
||||
func goErrorCB(code C.int, desc *C.char) {
|
||||
flushErrors()
|
||||
err := &Error{ErrorCode(code), C.GoString(desc)}
|
||||
select {
|
||||
case lastError <- err:
|
||||
default:
|
||||
fmt.Println("GLFW: An uncaught error has occurred:", err)
|
||||
fmt.Println("GLFW: Please report this bug in the Go package immediately.")
|
||||
}
|
||||
}
|
||||
|
||||
// Set the glfw callback internally
|
||||
func init() {
|
||||
C.glfwSetErrorCallbackCB()
|
||||
}
|
||||
|
||||
// flushErrors is called by Terminate before it actually calls C.glfwTerminate,
|
||||
// this ensures that any uncaught errors buffered in lastError are printed
|
||||
// before the program exits.
|
||||
func flushErrors() {
|
||||
err := fetchError()
|
||||
if err != nil {
|
||||
fmt.Println("GLFW: An uncaught error has occurred:", err)
|
||||
fmt.Println("GLFW: Please report this bug in the Go package immediately.")
|
||||
}
|
||||
}
|
||||
|
||||
// acceptError fetches the next error from the error channel, it accepts only
|
||||
// errors with one of the given error codes. If any other error is encountered,
|
||||
// a panic will occur.
|
||||
//
|
||||
// Platform errors are always printed, for information why please see:
|
||||
//
|
||||
// https://github.com/go-gl/glfw/issues/127
|
||||
//
|
||||
func acceptError(codes ...ErrorCode) error {
|
||||
// Grab the next error, if there is one.
|
||||
err := fetchError()
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Only if the error has the specific error code accepted by the caller, do
|
||||
// we return the error.
|
||||
for _, code := range codes {
|
||||
if err.Code == code {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// The error isn't accepted by the caller. If the error code is not a code
|
||||
// defined in the GLFW C documentation as a programmer error, then the
|
||||
// caller should have accepted it. This is effectively a bug in this
|
||||
// package.
|
||||
switch err.Code {
|
||||
case platformError:
|
||||
log.Println(err)
|
||||
return nil
|
||||
case notInitialized, noCurrentContext, invalidEnum, invalidValue, outOfMemory:
|
||||
panic(err)
|
||||
default:
|
||||
fmt.Println("GLFW: An invalid error was not accepted by the caller:", err)
|
||||
fmt.Println("GLFW: Please report this bug in the Go package immediately.")
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// panicError is a helper used by functions which expect no errors (except
|
||||
// programmer errors) to occur. It will panic if it finds any such error.
|
||||
func panicError() {
|
||||
err := acceptError()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// fetchError fetches the next error from the error channel, it does not block
|
||||
// and returns nil if there is no error present.
|
||||
func fetchError() *Error {
|
||||
select {
|
||||
case err := <-lastError:
|
||||
return err
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
76
vendor/github.com/go-gl/glfw/v3.2/glfw/glfw.go
generated
vendored
Normal file
76
vendor/github.com/go-gl/glfw/v3.2/glfw/glfw.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package glfw
|
||||
|
||||
//#include "glfw/include/GLFW/glfw3.h"
|
||||
import "C"
|
||||
|
||||
// Version constants.
|
||||
const (
|
||||
VersionMajor = C.GLFW_VERSION_MAJOR // This is incremented when the API is changed in non-compatible ways.
|
||||
VersionMinor = C.GLFW_VERSION_MINOR // This is incremented when features are added to the API but it remains backward-compatible.
|
||||
VersionRevision = C.GLFW_VERSION_REVISION // This is incremented when a bug fix release is made that does not contain any API changes.
|
||||
)
|
||||
|
||||
// Init initializes the GLFW library. Before most GLFW functions can be used,
|
||||
// GLFW must be initialized, and before a program terminates GLFW should be
|
||||
// terminated in order to free any resources allocated during or after
|
||||
// initialization.
|
||||
//
|
||||
// If this function fails, it calls Terminate before returning. If it succeeds,
|
||||
// you should call Terminate before the program exits.
|
||||
//
|
||||
// Additional calls to this function after successful initialization but before
|
||||
// termination will succeed but will do nothing.
|
||||
//
|
||||
// This function may take several seconds to complete on some systems, while on
|
||||
// other systems it may take only a fraction of a second to complete.
|
||||
//
|
||||
// On Mac OS X, this function will change the current directory of the
|
||||
// application to the Contents/Resources subdirectory of the application's
|
||||
// bundle, if present.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func Init() error {
|
||||
C.glfwInit()
|
||||
return acceptError(APIUnavailable)
|
||||
}
|
||||
|
||||
// Terminate destroys all remaining windows, frees any allocated resources and
|
||||
// sets the library to an uninitialized state. Once this is called, you must
|
||||
// again call Init successfully before you will be able to use most GLFW
|
||||
// functions.
|
||||
//
|
||||
// If GLFW has been successfully initialized, this function should be called
|
||||
// before the program exits. If initialization fails, there is no need to call
|
||||
// this function, as it is called by Init before it returns failure.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func Terminate() {
|
||||
flushErrors()
|
||||
C.glfwTerminate()
|
||||
}
|
||||
|
||||
// GetVersion retrieves the major, minor and revision numbers of the GLFW
|
||||
// library. It is intended for when you are using GLFW as a shared library and
|
||||
// want to ensure that you are using the minimum required version.
|
||||
//
|
||||
// This function may be called before Init.
|
||||
func GetVersion() (major, minor, revision int) {
|
||||
var (
|
||||
maj C.int
|
||||
min C.int
|
||||
rev C.int
|
||||
)
|
||||
|
||||
C.glfwGetVersion(&maj, &min, &rev)
|
||||
return int(maj), int(min), int(rev)
|
||||
}
|
||||
|
||||
// GetVersionString returns a static string generated at compile-time according
|
||||
// to which configuration macros were defined. This is intended for use when
|
||||
// submitting bug reports, to allow developers to see which code paths are
|
||||
// enabled in a binary.
|
||||
//
|
||||
// This function may be called before Init.
|
||||
func GetVersionString() string {
|
||||
return C.GoString(C.glfwGetVersionString())
|
||||
}
|
22
vendor/github.com/go-gl/glfw/v3.2/glfw/glfw/COPYING.txt
generated
vendored
Normal file
22
vendor/github.com/go-gl/glfw/v3.2/glfw/glfw/COPYING.txt
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2002-2006 Marcus Geelnard
|
||||
Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would
|
||||
be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not
|
||||
be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
81
vendor/github.com/go-gl/glfw/v3.2/glfw/input.c
generated
vendored
Normal file
81
vendor/github.com/go-gl/glfw/v3.2/glfw/input.c
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
#include "_cgo_export.h"
|
||||
|
||||
void glfwJoystickCB(int joy, int event) {
|
||||
goJoystickCB(joy, event);
|
||||
}
|
||||
|
||||
void glfwMouseButtonCB(GLFWwindow* window, int button, int action, int mods) {
|
||||
goMouseButtonCB(window, button, action, mods);
|
||||
}
|
||||
|
||||
void glfwCursorPosCB(GLFWwindow* window, double xpos, double ypos) {
|
||||
goCursorPosCB(window, xpos, ypos);
|
||||
}
|
||||
|
||||
void glfwCursorEnterCB(GLFWwindow* window, int entered) {
|
||||
goCursorEnterCB(window, entered);
|
||||
}
|
||||
|
||||
void glfwScrollCB(GLFWwindow* window, double xoff, double yoff) {
|
||||
goScrollCB(window, xoff, yoff);
|
||||
}
|
||||
|
||||
void glfwKeyCB(GLFWwindow* window, int key, int scancode, int action, int mods) {
|
||||
goKeyCB(window, key, scancode, action, mods);
|
||||
}
|
||||
|
||||
void glfwCharCB(GLFWwindow* window, unsigned int character) {
|
||||
goCharCB(window, character);
|
||||
}
|
||||
|
||||
void glfwCharModsCB(GLFWwindow* window, unsigned int character, int mods) {
|
||||
goCharModsCB(window, character, mods);
|
||||
}
|
||||
|
||||
void glfwDropCB(GLFWwindow* window, int count, const char **names) {
|
||||
goDropCB(window, count, (char**)names);
|
||||
}
|
||||
|
||||
void glfwSetJoystickCallbackCB() {
|
||||
glfwSetJoystickCallback(glfwJoystickCB);
|
||||
}
|
||||
|
||||
void glfwSetKeyCallbackCB(GLFWwindow *window) {
|
||||
glfwSetKeyCallback(window, glfwKeyCB);
|
||||
}
|
||||
|
||||
void glfwSetCharCallbackCB(GLFWwindow *window) {
|
||||
glfwSetCharCallback(window, glfwCharCB);
|
||||
}
|
||||
|
||||
void glfwSetCharModsCallbackCB(GLFWwindow *window) {
|
||||
glfwSetCharModsCallback(window, glfwCharModsCB);
|
||||
}
|
||||
|
||||
void glfwSetMouseButtonCallbackCB(GLFWwindow *window) {
|
||||
glfwSetMouseButtonCallback(window, glfwMouseButtonCB);
|
||||
}
|
||||
|
||||
void glfwSetCursorPosCallbackCB(GLFWwindow *window) {
|
||||
glfwSetCursorPosCallback(window, glfwCursorPosCB);
|
||||
}
|
||||
|
||||
void glfwSetCursorEnterCallbackCB(GLFWwindow *window) {
|
||||
glfwSetCursorEnterCallback(window, glfwCursorEnterCB);
|
||||
}
|
||||
|
||||
void glfwSetScrollCallbackCB(GLFWwindow *window) {
|
||||
glfwSetScrollCallback(window, glfwScrollCB);
|
||||
}
|
||||
|
||||
void glfwSetDropCallbackCB(GLFWwindow *window) {
|
||||
glfwSetDropCallback(window, glfwDropCB);
|
||||
}
|
||||
|
||||
float GetAxisAtIndex(float *axis, int i) {
|
||||
return axis[i];
|
||||
}
|
||||
|
||||
unsigned char GetButtonsAtIndex(unsigned char *buttons, int i) {
|
||||
return buttons[i];
|
||||
}
|
696
vendor/github.com/go-gl/glfw/v3.2/glfw/input.go
generated
vendored
Normal file
696
vendor/github.com/go-gl/glfw/v3.2/glfw/input.go
generated
vendored
Normal file
@@ -0,0 +1,696 @@
|
||||
package glfw
|
||||
|
||||
//#include "glfw/include/GLFW/glfw3.h"
|
||||
//void glfwSetJoystickCallbackCB();
|
||||
//void glfwSetKeyCallbackCB(GLFWwindow *window);
|
||||
//void glfwSetCharCallbackCB(GLFWwindow *window);
|
||||
//void glfwSetCharModsCallbackCB(GLFWwindow *window);
|
||||
//void glfwSetMouseButtonCallbackCB(GLFWwindow *window);
|
||||
//void glfwSetCursorPosCallbackCB(GLFWwindow *window);
|
||||
//void glfwSetCursorEnterCallbackCB(GLFWwindow *window);
|
||||
//void glfwSetScrollCallbackCB(GLFWwindow *window);
|
||||
//void glfwSetDropCallbackCB(GLFWwindow *window);
|
||||
//float GetAxisAtIndex(float *axis, int i);
|
||||
//unsigned char GetButtonsAtIndex(unsigned char *buttons, int i);
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/draw"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var fJoystickHolder func(joy, event int)
|
||||
|
||||
// Joystick corresponds to a joystick.
|
||||
type Joystick int
|
||||
|
||||
// Joystick IDs.
|
||||
const (
|
||||
Joystick1 Joystick = C.GLFW_JOYSTICK_1
|
||||
Joystick2 Joystick = C.GLFW_JOYSTICK_2
|
||||
Joystick3 Joystick = C.GLFW_JOYSTICK_3
|
||||
Joystick4 Joystick = C.GLFW_JOYSTICK_4
|
||||
Joystick5 Joystick = C.GLFW_JOYSTICK_5
|
||||
Joystick6 Joystick = C.GLFW_JOYSTICK_6
|
||||
Joystick7 Joystick = C.GLFW_JOYSTICK_7
|
||||
Joystick8 Joystick = C.GLFW_JOYSTICK_8
|
||||
Joystick9 Joystick = C.GLFW_JOYSTICK_9
|
||||
Joystick10 Joystick = C.GLFW_JOYSTICK_10
|
||||
Joystick11 Joystick = C.GLFW_JOYSTICK_11
|
||||
Joystick12 Joystick = C.GLFW_JOYSTICK_12
|
||||
Joystick13 Joystick = C.GLFW_JOYSTICK_13
|
||||
Joystick14 Joystick = C.GLFW_JOYSTICK_14
|
||||
Joystick15 Joystick = C.GLFW_JOYSTICK_15
|
||||
Joystick16 Joystick = C.GLFW_JOYSTICK_16
|
||||
JoystickLast Joystick = C.GLFW_JOYSTICK_LAST
|
||||
)
|
||||
|
||||
// Key corresponds to a keyboard key.
|
||||
type Key int
|
||||
|
||||
// These key codes are inspired by the USB HID Usage Tables v1.12 (p. 53-60),
|
||||
// but re-arranged to map to 7-bit ASCII for printable keys (function keys are
|
||||
// put in the 256+ range).
|
||||
const (
|
||||
KeyUnknown Key = C.GLFW_KEY_UNKNOWN
|
||||
KeySpace Key = C.GLFW_KEY_SPACE
|
||||
KeyApostrophe Key = C.GLFW_KEY_APOSTROPHE
|
||||
KeyComma Key = C.GLFW_KEY_COMMA
|
||||
KeyMinus Key = C.GLFW_KEY_MINUS
|
||||
KeyPeriod Key = C.GLFW_KEY_PERIOD
|
||||
KeySlash Key = C.GLFW_KEY_SLASH
|
||||
Key0 Key = C.GLFW_KEY_0
|
||||
Key1 Key = C.GLFW_KEY_1
|
||||
Key2 Key = C.GLFW_KEY_2
|
||||
Key3 Key = C.GLFW_KEY_3
|
||||
Key4 Key = C.GLFW_KEY_4
|
||||
Key5 Key = C.GLFW_KEY_5
|
||||
Key6 Key = C.GLFW_KEY_6
|
||||
Key7 Key = C.GLFW_KEY_7
|
||||
Key8 Key = C.GLFW_KEY_8
|
||||
Key9 Key = C.GLFW_KEY_9
|
||||
KeySemicolon Key = C.GLFW_KEY_SEMICOLON
|
||||
KeyEqual Key = C.GLFW_KEY_EQUAL
|
||||
KeyA Key = C.GLFW_KEY_A
|
||||
KeyB Key = C.GLFW_KEY_B
|
||||
KeyC Key = C.GLFW_KEY_C
|
||||
KeyD Key = C.GLFW_KEY_D
|
||||
KeyE Key = C.GLFW_KEY_E
|
||||
KeyF Key = C.GLFW_KEY_F
|
||||
KeyG Key = C.GLFW_KEY_G
|
||||
KeyH Key = C.GLFW_KEY_H
|
||||
KeyI Key = C.GLFW_KEY_I
|
||||
KeyJ Key = C.GLFW_KEY_J
|
||||
KeyK Key = C.GLFW_KEY_K
|
||||
KeyL Key = C.GLFW_KEY_L
|
||||
KeyM Key = C.GLFW_KEY_M
|
||||
KeyN Key = C.GLFW_KEY_N
|
||||
KeyO Key = C.GLFW_KEY_O
|
||||
KeyP Key = C.GLFW_KEY_P
|
||||
KeyQ Key = C.GLFW_KEY_Q
|
||||
KeyR Key = C.GLFW_KEY_R
|
||||
KeyS Key = C.GLFW_KEY_S
|
||||
KeyT Key = C.GLFW_KEY_T
|
||||
KeyU Key = C.GLFW_KEY_U
|
||||
KeyV Key = C.GLFW_KEY_V
|
||||
KeyW Key = C.GLFW_KEY_W
|
||||
KeyX Key = C.GLFW_KEY_X
|
||||
KeyY Key = C.GLFW_KEY_Y
|
||||
KeyZ Key = C.GLFW_KEY_Z
|
||||
KeyLeftBracket Key = C.GLFW_KEY_LEFT_BRACKET
|
||||
KeyBackslash Key = C.GLFW_KEY_BACKSLASH
|
||||
KeyRightBracket Key = C.GLFW_KEY_RIGHT_BRACKET
|
||||
KeyGraveAccent Key = C.GLFW_KEY_GRAVE_ACCENT
|
||||
KeyWorld1 Key = C.GLFW_KEY_WORLD_1
|
||||
KeyWorld2 Key = C.GLFW_KEY_WORLD_2
|
||||
KeyEscape Key = C.GLFW_KEY_ESCAPE
|
||||
KeyEnter Key = C.GLFW_KEY_ENTER
|
||||
KeyTab Key = C.GLFW_KEY_TAB
|
||||
KeyBackspace Key = C.GLFW_KEY_BACKSPACE
|
||||
KeyInsert Key = C.GLFW_KEY_INSERT
|
||||
KeyDelete Key = C.GLFW_KEY_DELETE
|
||||
KeyRight Key = C.GLFW_KEY_RIGHT
|
||||
KeyLeft Key = C.GLFW_KEY_LEFT
|
||||
KeyDown Key = C.GLFW_KEY_DOWN
|
||||
KeyUp Key = C.GLFW_KEY_UP
|
||||
KeyPageUp Key = C.GLFW_KEY_PAGE_UP
|
||||
KeyPageDown Key = C.GLFW_KEY_PAGE_DOWN
|
||||
KeyHome Key = C.GLFW_KEY_HOME
|
||||
KeyEnd Key = C.GLFW_KEY_END
|
||||
KeyCapsLock Key = C.GLFW_KEY_CAPS_LOCK
|
||||
KeyScrollLock Key = C.GLFW_KEY_SCROLL_LOCK
|
||||
KeyNumLock Key = C.GLFW_KEY_NUM_LOCK
|
||||
KeyPrintScreen Key = C.GLFW_KEY_PRINT_SCREEN
|
||||
KeyPause Key = C.GLFW_KEY_PAUSE
|
||||
KeyF1 Key = C.GLFW_KEY_F1
|
||||
KeyF2 Key = C.GLFW_KEY_F2
|
||||
KeyF3 Key = C.GLFW_KEY_F3
|
||||
KeyF4 Key = C.GLFW_KEY_F4
|
||||
KeyF5 Key = C.GLFW_KEY_F5
|
||||
KeyF6 Key = C.GLFW_KEY_F6
|
||||
KeyF7 Key = C.GLFW_KEY_F7
|
||||
KeyF8 Key = C.GLFW_KEY_F8
|
||||
KeyF9 Key = C.GLFW_KEY_F9
|
||||
KeyF10 Key = C.GLFW_KEY_F10
|
||||
KeyF11 Key = C.GLFW_KEY_F11
|
||||
KeyF12 Key = C.GLFW_KEY_F12
|
||||
KeyF13 Key = C.GLFW_KEY_F13
|
||||
KeyF14 Key = C.GLFW_KEY_F14
|
||||
KeyF15 Key = C.GLFW_KEY_F15
|
||||
KeyF16 Key = C.GLFW_KEY_F16
|
||||
KeyF17 Key = C.GLFW_KEY_F17
|
||||
KeyF18 Key = C.GLFW_KEY_F18
|
||||
KeyF19 Key = C.GLFW_KEY_F19
|
||||
KeyF20 Key = C.GLFW_KEY_F20
|
||||
KeyF21 Key = C.GLFW_KEY_F21
|
||||
KeyF22 Key = C.GLFW_KEY_F22
|
||||
KeyF23 Key = C.GLFW_KEY_F23
|
||||
KeyF24 Key = C.GLFW_KEY_F24
|
||||
KeyF25 Key = C.GLFW_KEY_F25
|
||||
KeyKP0 Key = C.GLFW_KEY_KP_0
|
||||
KeyKP1 Key = C.GLFW_KEY_KP_1
|
||||
KeyKP2 Key = C.GLFW_KEY_KP_2
|
||||
KeyKP3 Key = C.GLFW_KEY_KP_3
|
||||
KeyKP4 Key = C.GLFW_KEY_KP_4
|
||||
KeyKP5 Key = C.GLFW_KEY_KP_5
|
||||
KeyKP6 Key = C.GLFW_KEY_KP_6
|
||||
KeyKP7 Key = C.GLFW_KEY_KP_7
|
||||
KeyKP8 Key = C.GLFW_KEY_KP_8
|
||||
KeyKP9 Key = C.GLFW_KEY_KP_9
|
||||
KeyKPDecimal Key = C.GLFW_KEY_KP_DECIMAL
|
||||
KeyKPDivide Key = C.GLFW_KEY_KP_DIVIDE
|
||||
KeyKPMultiply Key = C.GLFW_KEY_KP_MULTIPLY
|
||||
KeyKPSubtract Key = C.GLFW_KEY_KP_SUBTRACT
|
||||
KeyKPAdd Key = C.GLFW_KEY_KP_ADD
|
||||
KeyKPEnter Key = C.GLFW_KEY_KP_ENTER
|
||||
KeyKPEqual Key = C.GLFW_KEY_KP_EQUAL
|
||||
KeyLeftShift Key = C.GLFW_KEY_LEFT_SHIFT
|
||||
KeyLeftControl Key = C.GLFW_KEY_LEFT_CONTROL
|
||||
KeyLeftAlt Key = C.GLFW_KEY_LEFT_ALT
|
||||
KeyLeftSuper Key = C.GLFW_KEY_LEFT_SUPER
|
||||
KeyRightShift Key = C.GLFW_KEY_RIGHT_SHIFT
|
||||
KeyRightControl Key = C.GLFW_KEY_RIGHT_CONTROL
|
||||
KeyRightAlt Key = C.GLFW_KEY_RIGHT_ALT
|
||||
KeyRightSuper Key = C.GLFW_KEY_RIGHT_SUPER
|
||||
KeyMenu Key = C.GLFW_KEY_MENU
|
||||
KeyLast Key = C.GLFW_KEY_LAST
|
||||
)
|
||||
|
||||
// ModifierKey corresponds to a modifier key.
|
||||
type ModifierKey int
|
||||
|
||||
// Modifier keys.
|
||||
const (
|
||||
ModShift ModifierKey = C.GLFW_MOD_SHIFT
|
||||
ModControl ModifierKey = C.GLFW_MOD_CONTROL
|
||||
ModAlt ModifierKey = C.GLFW_MOD_ALT
|
||||
ModSuper ModifierKey = C.GLFW_MOD_SUPER
|
||||
)
|
||||
|
||||
// MouseButton corresponds to a mouse button.
|
||||
type MouseButton int
|
||||
|
||||
// Mouse buttons.
|
||||
const (
|
||||
MouseButton1 MouseButton = C.GLFW_MOUSE_BUTTON_1
|
||||
MouseButton2 MouseButton = C.GLFW_MOUSE_BUTTON_2
|
||||
MouseButton3 MouseButton = C.GLFW_MOUSE_BUTTON_3
|
||||
MouseButton4 MouseButton = C.GLFW_MOUSE_BUTTON_4
|
||||
MouseButton5 MouseButton = C.GLFW_MOUSE_BUTTON_5
|
||||
MouseButton6 MouseButton = C.GLFW_MOUSE_BUTTON_6
|
||||
MouseButton7 MouseButton = C.GLFW_MOUSE_BUTTON_7
|
||||
MouseButton8 MouseButton = C.GLFW_MOUSE_BUTTON_8
|
||||
MouseButtonLast MouseButton = C.GLFW_MOUSE_BUTTON_LAST
|
||||
MouseButtonLeft MouseButton = C.GLFW_MOUSE_BUTTON_LEFT
|
||||
MouseButtonRight MouseButton = C.GLFW_MOUSE_BUTTON_RIGHT
|
||||
MouseButtonMiddle MouseButton = C.GLFW_MOUSE_BUTTON_MIDDLE
|
||||
)
|
||||
|
||||
// StandardCursor corresponds to a standard cursor icon.
|
||||
type StandardCursor int
|
||||
|
||||
// Standard cursors
|
||||
const (
|
||||
ArrowCursor StandardCursor = C.GLFW_ARROW_CURSOR
|
||||
IBeamCursor StandardCursor = C.GLFW_IBEAM_CURSOR
|
||||
CrosshairCursor StandardCursor = C.GLFW_CROSSHAIR_CURSOR
|
||||
HandCursor StandardCursor = C.GLFW_HAND_CURSOR
|
||||
HResizeCursor StandardCursor = C.GLFW_HRESIZE_CURSOR
|
||||
VResizeCursor StandardCursor = C.GLFW_VRESIZE_CURSOR
|
||||
)
|
||||
|
||||
// Action corresponds to a key or button action.
|
||||
type Action int
|
||||
|
||||
// Action types.
|
||||
const (
|
||||
Release Action = C.GLFW_RELEASE // The key or button was released.
|
||||
Press Action = C.GLFW_PRESS // The key or button was pressed.
|
||||
Repeat Action = C.GLFW_REPEAT // The key was held down until it repeated.
|
||||
)
|
||||
|
||||
// InputMode corresponds to an input mode.
|
||||
type InputMode int
|
||||
|
||||
// Input modes.
|
||||
const (
|
||||
CursorMode InputMode = C.GLFW_CURSOR // See Cursor mode values
|
||||
StickyKeysMode InputMode = C.GLFW_STICKY_KEYS // Value can be either 1 or 0
|
||||
StickyMouseButtonsMode InputMode = C.GLFW_STICKY_MOUSE_BUTTONS // Value can be either 1 or 0
|
||||
)
|
||||
|
||||
// Cursor mode values.
|
||||
const (
|
||||
CursorNormal int = C.GLFW_CURSOR_NORMAL
|
||||
CursorHidden int = C.GLFW_CURSOR_HIDDEN
|
||||
CursorDisabled int = C.GLFW_CURSOR_DISABLED
|
||||
)
|
||||
|
||||
// Cursor represents a cursor.
|
||||
type Cursor struct {
|
||||
data *C.GLFWcursor
|
||||
}
|
||||
|
||||
//export goJoystickCB
|
||||
func goJoystickCB(joy, event C.int) {
|
||||
fJoystickHolder(int(joy), int(event))
|
||||
}
|
||||
|
||||
//export goMouseButtonCB
|
||||
func goMouseButtonCB(window unsafe.Pointer, button, action, mods C.int) {
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
w.fMouseButtonHolder(w, MouseButton(button), Action(action), ModifierKey(mods))
|
||||
}
|
||||
|
||||
//export goCursorPosCB
|
||||
func goCursorPosCB(window unsafe.Pointer, xpos, ypos C.double) {
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
w.fCursorPosHolder(w, float64(xpos), float64(ypos))
|
||||
}
|
||||
|
||||
//export goCursorEnterCB
|
||||
func goCursorEnterCB(window unsafe.Pointer, entered C.int) {
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
hasEntered := glfwbool(entered)
|
||||
w.fCursorEnterHolder(w, hasEntered)
|
||||
}
|
||||
|
||||
//export goScrollCB
|
||||
func goScrollCB(window unsafe.Pointer, xoff, yoff C.double) {
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
w.fScrollHolder(w, float64(xoff), float64(yoff))
|
||||
}
|
||||
|
||||
//export goKeyCB
|
||||
func goKeyCB(window unsafe.Pointer, key, scancode, action, mods C.int) {
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
w.fKeyHolder(w, Key(key), int(scancode), Action(action), ModifierKey(mods))
|
||||
}
|
||||
|
||||
//export goCharCB
|
||||
func goCharCB(window unsafe.Pointer, character C.uint) {
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
w.fCharHolder(w, rune(character))
|
||||
}
|
||||
|
||||
//export goCharModsCB
|
||||
func goCharModsCB(window unsafe.Pointer, character C.uint, mods C.int) {
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
w.fCharModsHolder(w, rune(character), ModifierKey(mods))
|
||||
}
|
||||
|
||||
//export goDropCB
|
||||
func goDropCB(window unsafe.Pointer, count C.int, names **C.char) { // TODO: The types of name can be `**C.char` or `unsafe.Pointer`, use whichever is better.
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
namesSlice := make([]string, int(count)) // TODO: Make this better. This part is unfinished, hacky, probably not correct, and not idiomatic.
|
||||
for i := 0; i < int(count); i++ { // TODO: Make this better. It should be cleaned up and vetted.
|
||||
var x *C.char // TODO: Make this better.
|
||||
p := (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(names)) + uintptr(i)*unsafe.Sizeof(x))) // TODO: Make this better.
|
||||
namesSlice[i] = C.GoString(*p) // TODO: Make this better.
|
||||
}
|
||||
w.fDropHolder(w, namesSlice)
|
||||
}
|
||||
|
||||
// GetInputMode returns the value of an input option of the window.
|
||||
func (w *Window) GetInputMode(mode InputMode) int {
|
||||
ret := int(C.glfwGetInputMode(w.data, C.int(mode)))
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// SetInputMode sets an input option for the window.
|
||||
func (w *Window) SetInputMode(mode InputMode, value int) {
|
||||
C.glfwSetInputMode(w.data, C.int(mode), C.int(value))
|
||||
panicError()
|
||||
}
|
||||
|
||||
// GetKey returns the last reported state of a keyboard key. The returned state
|
||||
// is one of Press or Release. The higher-level state Repeat is only reported to
|
||||
// the key callback.
|
||||
//
|
||||
// If the StickyKeys input mode is enabled, this function returns Press the first
|
||||
// time you call this function after a key has been pressed, even if the key has
|
||||
// already been released.
|
||||
//
|
||||
// The key functions deal with physical keys, with key tokens named after their
|
||||
// use on the standard US keyboard layout. If you want to input text, use the
|
||||
// Unicode character callback instead.
|
||||
func (w *Window) GetKey(key Key) Action {
|
||||
ret := Action(C.glfwGetKey(w.data, C.int(key)))
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetKeyName returns the localized name of the specified printable key.
|
||||
//
|
||||
// If the key is glfw.KeyUnknown, the scancode is used, otherwise the scancode is ignored.
|
||||
func GetKeyName(key Key, scancode int) string {
|
||||
ret := C.glfwGetKeyName(C.int(key), C.int(scancode))
|
||||
panicError()
|
||||
return C.GoString(ret)
|
||||
}
|
||||
|
||||
// GetMouseButton returns the last state reported for the specified mouse button.
|
||||
//
|
||||
// If the StickyMouseButtons input mode is enabled, this function returns Press
|
||||
// the first time you call this function after a mouse button has been pressed,
|
||||
// even if the mouse button has already been released.
|
||||
func (w *Window) GetMouseButton(button MouseButton) Action {
|
||||
ret := Action(C.glfwGetMouseButton(w.data, C.int(button)))
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetCursorPos returns the last reported position of the cursor.
|
||||
//
|
||||
// If the cursor is disabled (with CursorDisabled) then the cursor position is
|
||||
// unbounded and limited only by the minimum and maximum values of a double.
|
||||
//
|
||||
// The coordinate can be converted to their integer equivalents with the floor
|
||||
// function. Casting directly to an integer type works for positive coordinates,
|
||||
// but fails for negative ones.
|
||||
func (w *Window) GetCursorPos() (x, y float64) {
|
||||
var xpos, ypos C.double
|
||||
C.glfwGetCursorPos(w.data, &xpos, &ypos)
|
||||
panicError()
|
||||
return float64(xpos), float64(ypos)
|
||||
}
|
||||
|
||||
// SetCursorPos sets the position of the cursor. The specified window must
|
||||
// be focused. If the window does not have focus when this function is called,
|
||||
// it fails silently.
|
||||
//
|
||||
// If the cursor is disabled (with CursorDisabled) then the cursor position is
|
||||
// unbounded and limited only by the minimum and maximum values of a double.
|
||||
func (w *Window) SetCursorPos(xpos, ypos float64) {
|
||||
C.glfwSetCursorPos(w.data, C.double(xpos), C.double(ypos))
|
||||
panicError()
|
||||
}
|
||||
|
||||
// CreateCursor creates a new custom cursor image that can be set for a window with SetCursor.
|
||||
// The cursor can be destroyed with Destroy. Any remaining cursors are destroyed by Terminate.
|
||||
//
|
||||
// The image is ideally provided in the form of *image.NRGBA.
|
||||
// The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
|
||||
// bits per channel with the red channel first. They are arranged canonically
|
||||
// as packed sequential rows, starting from the top-left corner. If the image
|
||||
// type is not *image.NRGBA, it will be converted to it.
|
||||
//
|
||||
// The cursor hotspot is specified in pixels, relative to the upper-left corner of the cursor image.
|
||||
// Like all other coordinate systems in GLFW, the X-axis points to the right and the Y-axis points down.
|
||||
func CreateCursor(img image.Image, xhot, yhot int) *Cursor {
|
||||
var imgC C.GLFWimage
|
||||
var pixels []uint8
|
||||
b := img.Bounds()
|
||||
|
||||
switch img := img.(type) {
|
||||
case *image.NRGBA:
|
||||
pixels = img.Pix
|
||||
default:
|
||||
m := image.NewNRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
|
||||
draw.Draw(m, m.Bounds(), img, b.Min, draw.Src)
|
||||
pixels = m.Pix
|
||||
}
|
||||
|
||||
pix, free := bytes(pixels)
|
||||
|
||||
imgC.width = C.int(b.Dx())
|
||||
imgC.height = C.int(b.Dy())
|
||||
imgC.pixels = (*C.uchar)(pix)
|
||||
|
||||
c := C.glfwCreateCursor(&imgC, C.int(xhot), C.int(yhot))
|
||||
|
||||
free()
|
||||
panicError()
|
||||
|
||||
return &Cursor{c}
|
||||
}
|
||||
|
||||
// CreateStandardCursor returns a cursor with a standard shape,
|
||||
// that can be set for a window with SetCursor.
|
||||
func CreateStandardCursor(shape StandardCursor) *Cursor {
|
||||
c := C.glfwCreateStandardCursor(C.int(shape))
|
||||
panicError()
|
||||
return &Cursor{c}
|
||||
}
|
||||
|
||||
// Destroy destroys a cursor previously created with CreateCursor.
|
||||
// Any remaining cursors will be destroyed by Terminate.
|
||||
func (c *Cursor) Destroy() {
|
||||
C.glfwDestroyCursor(c.data)
|
||||
panicError()
|
||||
}
|
||||
|
||||
// SetCursor sets the cursor image to be used when the cursor is over the client area
|
||||
// of the specified window. The set cursor will only be visible when the cursor mode of the
|
||||
// window is CursorNormal.
|
||||
//
|
||||
// On some platforms, the set cursor may not be visible unless the window also has input focus.
|
||||
func (w *Window) SetCursor(c *Cursor) {
|
||||
if c == nil {
|
||||
C.glfwSetCursor(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetCursor(w.data, c.data)
|
||||
}
|
||||
panicError()
|
||||
}
|
||||
|
||||
// JoystickCallback is the joystick configuration callback.
|
||||
type JoystickCallback func(joy, event int)
|
||||
|
||||
// SetJoystickCallback sets the joystick configuration callback, or removes the
|
||||
// currently set callback. This is called when a joystick is connected to or
|
||||
// disconnected from the system.
|
||||
func SetJoystickCallback(cbfun JoystickCallback) (previous JoystickCallback) {
|
||||
previous = fJoystickHolder
|
||||
fJoystickHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetJoystickCallback(nil)
|
||||
} else {
|
||||
C.glfwSetJoystickCallbackCB()
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// KeyCallback is the key callback.
|
||||
type KeyCallback func(w *Window, key Key, scancode int, action Action, mods ModifierKey)
|
||||
|
||||
// SetKeyCallback sets the key callback which is called when a key is pressed,
|
||||
// repeated or released.
|
||||
//
|
||||
// The key functions deal with physical keys, with layout independent key tokens
|
||||
// named after their values in the standard US keyboard layout. If you want to
|
||||
// input text, use the SetCharCallback instead.
|
||||
//
|
||||
// When a window loses focus, it will generate synthetic key release events for
|
||||
// all pressed keys. You can tell these events from user-generated events by the
|
||||
// fact that the synthetic ones are generated after the window has lost focus,
|
||||
// i.e. Focused will be false and the focus callback will have already been
|
||||
// called.
|
||||
func (w *Window) SetKeyCallback(cbfun KeyCallback) (previous KeyCallback) {
|
||||
previous = w.fKeyHolder
|
||||
w.fKeyHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetKeyCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetKeyCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// CharCallback is the character callback.
|
||||
type CharCallback func(w *Window, char rune)
|
||||
|
||||
// SetCharCallback sets the character callback which is called when a
|
||||
// Unicode character is input.
|
||||
//
|
||||
// The character callback is intended for Unicode text input. As it deals with
|
||||
// characters, it is keyboard layout dependent, whereas the
|
||||
// key callback is not. Characters do not map 1:1
|
||||
// to physical keys, as a key may produce zero, one or more characters. If you
|
||||
// want to know whether a specific physical key was pressed or released, see
|
||||
// the key callback instead.
|
||||
//
|
||||
// The character callback behaves as system text input normally does and will
|
||||
// not be called if modifier keys are held down that would prevent normal text
|
||||
// input on that platform, for example a Super (Command) key on OS X or Alt key
|
||||
// on Windows. There is a character with modifiers callback that receives these events.
|
||||
func (w *Window) SetCharCallback(cbfun CharCallback) (previous CharCallback) {
|
||||
previous = w.fCharHolder
|
||||
w.fCharHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetCharCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetCharCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// CharModsCallback is the character with modifiers callback.
|
||||
type CharModsCallback func(w *Window, char rune, mods ModifierKey)
|
||||
|
||||
// SetCharModsCallback sets the character with modifiers callback which is called when a
|
||||
// Unicode character is input regardless of what modifier keys are used.
|
||||
//
|
||||
// The character with modifiers callback is intended for implementing custom
|
||||
// Unicode character input. For regular Unicode text input, see the
|
||||
// character callback. Like the character callback, the character with modifiers callback
|
||||
// deals with characters and is keyboard layout dependent. Characters do not
|
||||
// map 1:1 to physical keys, as a key may produce zero, one or more characters.
|
||||
// If you want to know whether a specific physical key was pressed or released,
|
||||
// see the key callback instead.
|
||||
func (w *Window) SetCharModsCallback(cbfun CharModsCallback) (previous CharModsCallback) {
|
||||
previous = w.fCharModsHolder
|
||||
w.fCharModsHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetCharModsCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetCharModsCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// MouseButtonCallback is the mouse button callback.
|
||||
type MouseButtonCallback func(w *Window, button MouseButton, action Action, mod ModifierKey)
|
||||
|
||||
// SetMouseButtonCallback sets the mouse button callback which is called when a
|
||||
// mouse button is pressed or released.
|
||||
//
|
||||
// When a window loses focus, it will generate synthetic mouse button release
|
||||
// events for all pressed mouse buttons. You can tell these events from
|
||||
// user-generated events by the fact that the synthetic ones are generated after
|
||||
// the window has lost focus, i.e. Focused will be false and the focus
|
||||
// callback will have already been called.
|
||||
func (w *Window) SetMouseButtonCallback(cbfun MouseButtonCallback) (previous MouseButtonCallback) {
|
||||
previous = w.fMouseButtonHolder
|
||||
w.fMouseButtonHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetMouseButtonCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetMouseButtonCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// CursorPosCallback the cursor position callback.
|
||||
type CursorPosCallback func(w *Window, xpos float64, ypos float64)
|
||||
|
||||
// SetCursorPosCallback sets the cursor position callback which is called
|
||||
// when the cursor is moved. The callback is provided with the position relative
|
||||
// to the upper-left corner of the client area of the window.
|
||||
func (w *Window) SetCursorPosCallback(cbfun CursorPosCallback) (previous CursorPosCallback) {
|
||||
previous = w.fCursorPosHolder
|
||||
w.fCursorPosHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetCursorPosCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetCursorPosCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// CursorEnterCallback is the cursor boundary crossing callback.
|
||||
type CursorEnterCallback func(w *Window, entered bool)
|
||||
|
||||
// SetCursorEnterCallback the cursor boundary crossing callback which is called
|
||||
// when the cursor enters or leaves the client area of the window.
|
||||
func (w *Window) SetCursorEnterCallback(cbfun CursorEnterCallback) (previous CursorEnterCallback) {
|
||||
previous = w.fCursorEnterHolder
|
||||
w.fCursorEnterHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetCursorEnterCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetCursorEnterCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// ScrollCallback is the scroll callback.
|
||||
type ScrollCallback func(w *Window, xoff float64, yoff float64)
|
||||
|
||||
// SetScrollCallback sets the scroll callback which is called when a scrolling
|
||||
// device is used, such as a mouse wheel or scrolling area of a touchpad.
|
||||
func (w *Window) SetScrollCallback(cbfun ScrollCallback) (previous ScrollCallback) {
|
||||
previous = w.fScrollHolder
|
||||
w.fScrollHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetScrollCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetScrollCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// DropCallback is the drop callback.
|
||||
type DropCallback func(w *Window, names []string)
|
||||
|
||||
// SetDropCallback sets the drop callback which is called when an object
|
||||
// is dropped over the window.
|
||||
func (w *Window) SetDropCallback(cbfun DropCallback) (previous DropCallback) {
|
||||
previous = w.fDropHolder
|
||||
w.fDropHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetDropCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetDropCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// JoystickPresent reports whether the specified joystick is present.
|
||||
func JoystickPresent(joy Joystick) bool {
|
||||
ret := glfwbool(C.glfwJoystickPresent(C.int(joy)))
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetJoystickAxes returns a slice of axis values.
|
||||
func GetJoystickAxes(joy Joystick) []float32 {
|
||||
var length int
|
||||
|
||||
axis := C.glfwGetJoystickAxes(C.int(joy), (*C.int)(unsafe.Pointer(&length)))
|
||||
panicError()
|
||||
if axis == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
a := make([]float32, length)
|
||||
for i := 0; i < length; i++ {
|
||||
a[i] = float32(C.GetAxisAtIndex(axis, C.int(i)))
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// GetJoystickButtons returns a slice of button values.
|
||||
func GetJoystickButtons(joy Joystick) []byte {
|
||||
var length int
|
||||
|
||||
buttons := C.glfwGetJoystickButtons(C.int(joy), (*C.int)(unsafe.Pointer(&length)))
|
||||
panicError()
|
||||
if buttons == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b := make([]byte, length)
|
||||
for i := 0; i < length; i++ {
|
||||
b[i] = byte(C.GetButtonsAtIndex(buttons, C.int(i)))
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// GetJoystickName returns the name, encoded as UTF-8, of the specified joystick.
|
||||
func GetJoystickName(joy Joystick) string {
|
||||
jn := C.glfwGetJoystickName(C.int(joy))
|
||||
panicError()
|
||||
return C.GoString(jn)
|
||||
}
|
25
vendor/github.com/go-gl/glfw/v3.2/glfw/monitor.c
generated
vendored
Normal file
25
vendor/github.com/go-gl/glfw/v3.2/glfw/monitor.c
generated
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
#include "_cgo_export.h"
|
||||
|
||||
GLFWmonitor *GetMonitorAtIndex(GLFWmonitor **monitors, int index) {
|
||||
return monitors[index];
|
||||
}
|
||||
|
||||
GLFWvidmode GetVidmodeAtIndex(GLFWvidmode *vidmodes, int index) {
|
||||
return vidmodes[index];
|
||||
}
|
||||
|
||||
void glfwMonitorCB(GLFWmonitor* monitor, int event) {
|
||||
goMonitorCB(monitor, event);
|
||||
}
|
||||
|
||||
void glfwSetMonitorCallbackCB() {
|
||||
glfwSetMonitorCallback(glfwMonitorCB);
|
||||
}
|
||||
|
||||
unsigned int GetGammaAtIndex(unsigned short *color, int i) {
|
||||
return color[i];
|
||||
}
|
||||
|
||||
void SetGammaAtIndex(unsigned short *color, int i, unsigned short value) {
|
||||
color[i] = value;
|
||||
}
|
208
vendor/github.com/go-gl/glfw/v3.2/glfw/monitor.go
generated
vendored
Normal file
208
vendor/github.com/go-gl/glfw/v3.2/glfw/monitor.go
generated
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
package glfw
|
||||
|
||||
//#include "glfw/include/GLFW/glfw3.h"
|
||||
//GLFWmonitor* GetMonitorAtIndex(GLFWmonitor **monitors, int index);
|
||||
//GLFWvidmode GetVidmodeAtIndex(GLFWvidmode *vidmodes, int index);
|
||||
//void glfwSetMonitorCallbackCB();
|
||||
//unsigned int GetGammaAtIndex(unsigned short *color, int i);
|
||||
//void SetGammaAtIndex(unsigned short *color, int i, unsigned short value);
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Monitor represents a monitor.
|
||||
type Monitor struct {
|
||||
data *C.GLFWmonitor
|
||||
}
|
||||
|
||||
// MonitorEvent corresponds to a monitor configuration event.
|
||||
type MonitorEvent int
|
||||
|
||||
// GammaRamp describes the gamma ramp for a monitor.
|
||||
type GammaRamp struct {
|
||||
Red []uint16 // A slice of value describing the response of the red channel.
|
||||
Green []uint16 // A slice of value describing the response of the green channel.
|
||||
Blue []uint16 // A slice of value describing the response of the blue channel.
|
||||
}
|
||||
|
||||
// Monitor events.
|
||||
const (
|
||||
Connected MonitorEvent = C.GLFW_CONNECTED
|
||||
Disconnected MonitorEvent = C.GLFW_DISCONNECTED
|
||||
)
|
||||
|
||||
// VidMode describes a single video mode.
|
||||
type VidMode struct {
|
||||
Width int // The width, in pixels, of the video mode.
|
||||
Height int // The height, in pixels, of the video mode.
|
||||
RedBits int // The bit depth of the red channel of the video mode.
|
||||
GreenBits int // The bit depth of the green channel of the video mode.
|
||||
BlueBits int // The bit depth of the blue channel of the video mode.
|
||||
RefreshRate int // The refresh rate, in Hz, of the video mode.
|
||||
}
|
||||
|
||||
var fMonitorHolder func(monitor *Monitor, event MonitorEvent)
|
||||
|
||||
//export goMonitorCB
|
||||
func goMonitorCB(monitor unsafe.Pointer, event C.int) {
|
||||
fMonitorHolder(&Monitor{(*C.GLFWmonitor)(monitor)}, MonitorEvent(event))
|
||||
}
|
||||
|
||||
// GetMonitors returns a slice of handles for all currently connected monitors.
|
||||
func GetMonitors() []*Monitor {
|
||||
var length int
|
||||
|
||||
mC := C.glfwGetMonitors((*C.int)(unsafe.Pointer(&length)))
|
||||
panicError()
|
||||
if mC == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
m := make([]*Monitor, length)
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
m[i] = &Monitor{C.GetMonitorAtIndex(mC, C.int(i))}
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// GetPrimaryMonitor returns the primary monitor. This is usually the monitor
|
||||
// where elements like the Windows task bar or the OS X menu bar is located.
|
||||
func GetPrimaryMonitor() *Monitor {
|
||||
m := C.glfwGetPrimaryMonitor()
|
||||
panicError()
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
return &Monitor{m}
|
||||
}
|
||||
|
||||
// GetPos returns the position, in screen coordinates, of the upper-left
|
||||
// corner of the monitor.
|
||||
func (m *Monitor) GetPos() (x, y int) {
|
||||
var xpos, ypos C.int
|
||||
C.glfwGetMonitorPos(m.data, &xpos, &ypos)
|
||||
panicError()
|
||||
return int(xpos), int(ypos)
|
||||
}
|
||||
|
||||
// GetPhysicalSize returns the size, in millimetres, of the display area of the
|
||||
// monitor.
|
||||
//
|
||||
// Note: Some operating systems do not provide accurate information, either
|
||||
// because the monitor's EDID data is incorrect, or because the driver does not
|
||||
// report it accurately.
|
||||
func (m *Monitor) GetPhysicalSize() (width, height int) {
|
||||
var wi, h C.int
|
||||
C.glfwGetMonitorPhysicalSize(m.data, &wi, &h)
|
||||
panicError()
|
||||
return int(wi), int(h)
|
||||
}
|
||||
|
||||
// GetName returns a human-readable name of the monitor, encoded as UTF-8.
|
||||
func (m *Monitor) GetName() string {
|
||||
mn := C.glfwGetMonitorName(m.data)
|
||||
panicError()
|
||||
if mn == nil {
|
||||
return ""
|
||||
}
|
||||
return C.GoString(mn)
|
||||
}
|
||||
|
||||
// SetMonitorCallback sets the monitor configuration callback, or removes the
|
||||
// currently set callback. This is called when a monitor is connected to or
|
||||
// disconnected from the system.
|
||||
func SetMonitorCallback(cbfun func(monitor *Monitor, event MonitorEvent)) {
|
||||
if cbfun == nil {
|
||||
C.glfwSetMonitorCallback(nil)
|
||||
} else {
|
||||
fMonitorHolder = cbfun
|
||||
C.glfwSetMonitorCallbackCB()
|
||||
}
|
||||
panicError()
|
||||
}
|
||||
|
||||
// GetVideoModes returns an array of all video modes supported by the monitor.
|
||||
// The returned array is sorted in ascending order, first by color bit depth
|
||||
// (the sum of all channel depths) and then by resolution area (the product of
|
||||
// width and height).
|
||||
func (m *Monitor) GetVideoModes() []*VidMode {
|
||||
var length int
|
||||
|
||||
vC := C.glfwGetVideoModes(m.data, (*C.int)(unsafe.Pointer(&length)))
|
||||
panicError()
|
||||
if vC == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := make([]*VidMode, length)
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
t := C.GetVidmodeAtIndex(vC, C.int(i))
|
||||
v[i] = &VidMode{int(t.width), int(t.height), int(t.redBits), int(t.greenBits), int(t.blueBits), int(t.refreshRate)}
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
// GetVideoMode returns the current video mode of the monitor. If you
|
||||
// are using a full screen window, the return value will therefore depend on
|
||||
// whether it is focused.
|
||||
func (m *Monitor) GetVideoMode() *VidMode {
|
||||
t := C.glfwGetVideoMode(m.data)
|
||||
if t == nil {
|
||||
return nil
|
||||
}
|
||||
panicError()
|
||||
return &VidMode{int(t.width), int(t.height), int(t.redBits), int(t.greenBits), int(t.blueBits), int(t.refreshRate)}
|
||||
}
|
||||
|
||||
// SetGamma generates a 256-element gamma ramp from the specified exponent and then calls
|
||||
// SetGamma with it.
|
||||
func (m *Monitor) SetGamma(gamma float32) {
|
||||
C.glfwSetGamma(m.data, C.float(gamma))
|
||||
panicError()
|
||||
}
|
||||
|
||||
// GetGammaRamp retrieves the current gamma ramp of the monitor.
|
||||
func (m *Monitor) GetGammaRamp() *GammaRamp {
|
||||
var ramp GammaRamp
|
||||
|
||||
rampC := C.glfwGetGammaRamp(m.data)
|
||||
panicError()
|
||||
if rampC == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
length := int(rampC.size)
|
||||
ramp.Red = make([]uint16, length)
|
||||
ramp.Green = make([]uint16, length)
|
||||
ramp.Blue = make([]uint16, length)
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
ramp.Red[i] = uint16(C.GetGammaAtIndex(rampC.red, C.int(i)))
|
||||
ramp.Green[i] = uint16(C.GetGammaAtIndex(rampC.green, C.int(i)))
|
||||
ramp.Blue[i] = uint16(C.GetGammaAtIndex(rampC.blue, C.int(i)))
|
||||
}
|
||||
|
||||
return &ramp
|
||||
}
|
||||
|
||||
// SetGammaRamp sets the current gamma ramp for the monitor.
|
||||
func (m *Monitor) SetGammaRamp(ramp *GammaRamp) {
|
||||
var rampC C.GLFWgammaramp
|
||||
|
||||
length := len(ramp.Red)
|
||||
|
||||
for i := 0; i < length; i++ {
|
||||
C.SetGammaAtIndex(rampC.red, C.int(i), C.ushort(ramp.Red[i]))
|
||||
C.SetGammaAtIndex(rampC.green, C.int(i), C.ushort(ramp.Green[i]))
|
||||
C.SetGammaAtIndex(rampC.blue, C.int(i), C.ushort(ramp.Blue[i]))
|
||||
}
|
||||
|
||||
C.glfwSetGammaRamp(m.data, &rampC)
|
||||
panicError()
|
||||
}
|
39
vendor/github.com/go-gl/glfw/v3.2/glfw/native_darwin.go
generated
vendored
Normal file
39
vendor/github.com/go-gl/glfw/v3.2/glfw/native_darwin.go
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package glfw
|
||||
|
||||
/*
|
||||
#define GLFW_EXPOSE_NATIVE_COCOA
|
||||
#define GLFW_EXPOSE_NATIVE_NSGL
|
||||
#include "glfw/include/GLFW/glfw3.h"
|
||||
#include "glfw/include/GLFW/glfw3native.h"
|
||||
|
||||
// workaround wrappers needed due to a cgo and/or LLVM bug.
|
||||
// See: https://github.com/go-gl/glfw/issues/136
|
||||
void *workaround_glfwGetCocoaWindow(GLFWwindow *w) {
|
||||
return (void *)glfwGetCocoaWindow(w);
|
||||
}
|
||||
void *workaround_glfwGetNSGLContext(GLFWwindow *w) {
|
||||
return (void *)glfwGetNSGLContext(w);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// GetCocoaMonitor returns the CGDirectDisplayID of the monitor.
|
||||
func (m *Monitor) GetCocoaMonitor() uintptr {
|
||||
ret := uintptr(C.glfwGetCocoaMonitor(m.data))
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetCocoaWindow returns the NSWindow of the window.
|
||||
func (w *Window) GetCocoaWindow() uintptr {
|
||||
ret := uintptr(C.workaround_glfwGetCocoaWindow(w.data))
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetNSGLContext returns the NSOpenGLContext of the window.
|
||||
func (w *Window) GetNSGLContext() uintptr {
|
||||
ret := uintptr(C.workaround_glfwGetNSGLContext(w.data))
|
||||
panicError()
|
||||
return ret
|
||||
}
|
50
vendor/github.com/go-gl/glfw/v3.2/glfw/native_linbsd.go
generated
vendored
Normal file
50
vendor/github.com/go-gl/glfw/v3.2/glfw/native_linbsd.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
// +build linux freebsd
|
||||
|
||||
package glfw
|
||||
|
||||
//#define GLFW_EXPOSE_NATIVE_X11
|
||||
//#define GLFW_EXPOSE_NATIVE_GLX
|
||||
//#include "glfw/include/GLFW/glfw3.h"
|
||||
//#include "glfw/include/GLFW/glfw3native.h"
|
||||
import "C"
|
||||
|
||||
func GetX11Display() *C.Display {
|
||||
ret := C.glfwGetX11Display()
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetX11Adapter returns the RRCrtc of the monitor.
|
||||
func (m *Monitor) GetX11Adapter() C.RRCrtc {
|
||||
ret := C.glfwGetX11Adapter(m.data)
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetX11Monitor returns the RROutput of the monitor.
|
||||
func (m *Monitor) GetX11Monitor() C.RROutput {
|
||||
ret := C.glfwGetX11Monitor(m.data)
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetX11Window returns the Window of the window.
|
||||
func (w *Window) GetX11Window() C.Window {
|
||||
ret := C.glfwGetX11Window(w.data)
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetGLXContext returns the GLXContext of the window.
|
||||
func (w *Window) GetGLXContext() C.GLXContext {
|
||||
ret := C.glfwGetGLXContext(w.data)
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetGLXWindow returns the GLXWindow of the window.
|
||||
func (w *Window) GetGLXWindow() C.GLXWindow {
|
||||
ret := C.glfwGetGLXWindow(w.data)
|
||||
panicError()
|
||||
return ret
|
||||
}
|
35
vendor/github.com/go-gl/glfw/v3.2/glfw/native_windows.go
generated
vendored
Normal file
35
vendor/github.com/go-gl/glfw/v3.2/glfw/native_windows.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
package glfw
|
||||
|
||||
//#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
//#define GLFW_EXPOSE_NATIVE_WGL
|
||||
//#include "glfw/include/GLFW/glfw3.h"
|
||||
//#include "glfw/include/GLFW/glfw3native.h"
|
||||
import "C"
|
||||
|
||||
// GetWin32Adapter returns the adapter device name of the monitor.
|
||||
func (m *Monitor) GetWin32Adapter() string {
|
||||
ret := C.glfwGetWin32Adapter(m.data)
|
||||
panicError()
|
||||
return C.GoString(ret)
|
||||
}
|
||||
|
||||
// GetWin32Monitor returns the display device name of the monitor.
|
||||
func (m *Monitor) GetWin32Monitor() string {
|
||||
ret := C.glfwGetWin32Monitor(m.data)
|
||||
panicError()
|
||||
return C.GoString(ret)
|
||||
}
|
||||
|
||||
// GetWin32Window returns the HWND of the window.
|
||||
func (w *Window) GetWin32Window() C.HWND {
|
||||
ret := C.glfwGetWin32Window(w.data)
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetWGLContext returns the HGLRC of the window.
|
||||
func (w *Window) GetWGLContext() C.HGLRC {
|
||||
ret := C.glfwGetWGLContext(w.data)
|
||||
panicError()
|
||||
return ret
|
||||
}
|
41
vendor/github.com/go-gl/glfw/v3.2/glfw/time.go
generated
vendored
Normal file
41
vendor/github.com/go-gl/glfw/v3.2/glfw/time.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
package glfw
|
||||
|
||||
//#include "glfw/include/GLFW/glfw3.h"
|
||||
import "C"
|
||||
|
||||
// GetTime returns the value of the GLFW timer. Unless the timer has been set
|
||||
// using SetTime, the timer measures time elapsed since GLFW was initialized.
|
||||
//
|
||||
// The resolution of the timer is system dependent, but is usually on the order
|
||||
// of a few micro- or nanoseconds. It uses the highest-resolution monotonic time
|
||||
// source on each supported platform.
|
||||
func GetTime() float64 {
|
||||
ret := float64(C.glfwGetTime())
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// SetTime sets the value of the GLFW timer. It then continues to count up from
|
||||
// that value.
|
||||
//
|
||||
// The resolution of the timer is system dependent, but is usually on the order
|
||||
// of a few micro- or nanoseconds. It uses the highest-resolution monotonic time
|
||||
// source on each supported platform.
|
||||
func SetTime(time float64) {
|
||||
C.glfwSetTime(C.double(time))
|
||||
panicError()
|
||||
}
|
||||
|
||||
// GetTimerFrequency returns frequency of the timer, in Hz, or zero if an error occurred.
|
||||
func GetTimerFrequency() uint64 {
|
||||
ret := uint64(C.glfwGetTimerFrequency())
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// GetTimerValue returns the current value of the raw timer, measured in 1 / frequency seconds.
|
||||
func GetTimerValue() uint64 {
|
||||
ret := uint64(C.glfwGetTimerValue())
|
||||
panicError()
|
||||
return ret
|
||||
}
|
37
vendor/github.com/go-gl/glfw/v3.2/glfw/util.go
generated
vendored
Normal file
37
vendor/github.com/go-gl/glfw/v3.2/glfw/util.go
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
package glfw
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include "glfw/include/GLFW/glfw3.h"
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func glfwbool(b C.int) bool {
|
||||
if b == C.GL_TRUE {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func bytes(origin []byte) (pointer *uint8, free func()) {
|
||||
n := len(origin)
|
||||
|
||||
if n == 0 {
|
||||
return nil, func() {}
|
||||
}
|
||||
|
||||
data := C.malloc(C.size_t(n))
|
||||
|
||||
dataSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
|
||||
Data: uintptr(data),
|
||||
Len: n,
|
||||
Cap: n,
|
||||
}))
|
||||
|
||||
copy(dataSlice, origin)
|
||||
|
||||
return &dataSlice[0], func() { C.free(data) }
|
||||
}
|
14
vendor/github.com/go-gl/glfw/v3.2/glfw/vulkan.go
generated
vendored
Normal file
14
vendor/github.com/go-gl/glfw/v3.2/glfw/vulkan.go
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
package glfw
|
||||
|
||||
//#include "glfw/include/GLFW/glfw3.h"
|
||||
import "C"
|
||||
|
||||
// VulkanSupported reports whether the Vulkan loader has been found. This check is performed by Init.
|
||||
//
|
||||
// The availability of a Vulkan loader does not by itself guarantee that window surface creation or
|
||||
// even device creation is possible. Call GetRequiredInstanceExtensions to check whether the
|
||||
// extensions necessary for Vulkan surface creation are available and GetPhysicalDevicePresentationSupport
|
||||
// to check whether a queue family of a physical device supports image presentation.
|
||||
func VulkanSupported() bool {
|
||||
return glfwbool(C.glfwVulkanSupported())
|
||||
}
|
57
vendor/github.com/go-gl/glfw/v3.2/glfw/window.c
generated
vendored
Normal file
57
vendor/github.com/go-gl/glfw/v3.2/glfw/window.c
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "_cgo_export.h"
|
||||
|
||||
void glfwWindowPosCB(GLFWwindow* window, int xpos, int ypos) {
|
||||
goWindowPosCB(window, xpos, ypos);
|
||||
}
|
||||
|
||||
void glfwWindowSizeCB(GLFWwindow* window, int width, int height) {
|
||||
goWindowSizeCB(window, width, height);
|
||||
}
|
||||
|
||||
void glfwFramebufferSizeCB(GLFWwindow* window, int width, int height) {
|
||||
goFramebufferSizeCB(window, width, height);
|
||||
}
|
||||
|
||||
void glfwWindowCloseCB(GLFWwindow* window) {
|
||||
goWindowCloseCB(window);
|
||||
}
|
||||
|
||||
void glfwWindowRefreshCB(GLFWwindow* window) {
|
||||
goWindowRefreshCB(window);
|
||||
}
|
||||
|
||||
void glfwWindowFocusCB(GLFWwindow* window, int focused) {
|
||||
goWindowFocusCB(window, focused);
|
||||
}
|
||||
|
||||
void glfwWindowIconifyCB(GLFWwindow* window, int iconified) {
|
||||
goWindowIconifyCB(window, iconified);
|
||||
}
|
||||
|
||||
void glfwSetWindowPosCallbackCB(GLFWwindow* window) {
|
||||
glfwSetWindowPosCallback(window, glfwWindowPosCB);
|
||||
}
|
||||
|
||||
void glfwSetWindowSizeCallbackCB(GLFWwindow* window) {
|
||||
glfwSetWindowSizeCallback(window, glfwWindowSizeCB);
|
||||
}
|
||||
|
||||
void glfwSetFramebufferSizeCallbackCB(GLFWwindow* window) {
|
||||
glfwSetFramebufferSizeCallback(window, glfwFramebufferSizeCB);
|
||||
}
|
||||
|
||||
void glfwSetWindowCloseCallbackCB(GLFWwindow* window) {
|
||||
glfwSetWindowCloseCallback(window, glfwWindowCloseCB);
|
||||
}
|
||||
|
||||
void glfwSetWindowRefreshCallbackCB(GLFWwindow* window) {
|
||||
glfwSetWindowRefreshCallback(window, glfwWindowRefreshCB);
|
||||
}
|
||||
|
||||
void glfwSetWindowFocusCallbackCB(GLFWwindow* window) {
|
||||
glfwSetWindowFocusCallback(window, glfwWindowFocusCB);
|
||||
}
|
||||
|
||||
void glfwSetWindowIconifyCallbackCB(GLFWwindow* window) {
|
||||
glfwSetWindowIconifyCallback(window, glfwWindowIconifyCB);
|
||||
}
|
830
vendor/github.com/go-gl/glfw/v3.2/glfw/window.go
generated
vendored
Normal file
830
vendor/github.com/go-gl/glfw/v3.2/glfw/window.go
generated
vendored
Normal file
@@ -0,0 +1,830 @@
|
||||
package glfw
|
||||
|
||||
//#include <stdlib.h>
|
||||
//#include "glfw/include/GLFW/glfw3.h"
|
||||
//void glfwSetWindowPosCallbackCB(GLFWwindow *window);
|
||||
//void glfwSetWindowSizeCallbackCB(GLFWwindow *window);
|
||||
//void glfwSetFramebufferSizeCallbackCB(GLFWwindow *window);
|
||||
//void glfwSetWindowCloseCallbackCB(GLFWwindow *window);
|
||||
//void glfwSetWindowRefreshCallbackCB(GLFWwindow *window);
|
||||
//void glfwSetWindowFocusCallbackCB(GLFWwindow *window);
|
||||
//void glfwSetWindowIconifyCallbackCB(GLFWwindow *window);
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/draw"
|
||||
"sync"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Internal window list stuff
|
||||
type windowList struct {
|
||||
l sync.Mutex
|
||||
m map[*C.GLFWwindow]*Window
|
||||
}
|
||||
|
||||
var windows = windowList{m: map[*C.GLFWwindow]*Window{}}
|
||||
|
||||
func (w *windowList) put(wnd *Window) {
|
||||
w.l.Lock()
|
||||
defer w.l.Unlock()
|
||||
w.m[wnd.data] = wnd
|
||||
}
|
||||
|
||||
func (w *windowList) remove(wnd *C.GLFWwindow) {
|
||||
w.l.Lock()
|
||||
defer w.l.Unlock()
|
||||
delete(w.m, wnd)
|
||||
}
|
||||
|
||||
func (w *windowList) get(wnd *C.GLFWwindow) *Window {
|
||||
w.l.Lock()
|
||||
defer w.l.Unlock()
|
||||
return w.m[wnd]
|
||||
}
|
||||
|
||||
// Hint corresponds to hints that can be set before creating a window.
|
||||
//
|
||||
// Hint also corresponds to the attributes of the window that can be get after
|
||||
// its creation.
|
||||
type Hint int
|
||||
|
||||
// Window related hints.
|
||||
const (
|
||||
Focused Hint = C.GLFW_FOCUSED // Specifies whether the window will be given input focus when created. This hint is ignored for full screen and initially hidden windows.
|
||||
Iconified Hint = C.GLFW_ICONIFIED // Specifies whether the window will be minimized.
|
||||
Maximized Hint = C.GLFW_MAXIMIZED // Specifies whether the window is maximized.
|
||||
Visible Hint = C.GLFW_VISIBLE // Specifies whether the window will be initially visible.
|
||||
Resizable Hint = C.GLFW_RESIZABLE // Specifies whether the window will be resizable by the user.
|
||||
Decorated Hint = C.GLFW_DECORATED // Specifies whether the window will have window decorations such as a border, a close widget, etc.
|
||||
Floating Hint = C.GLFW_FLOATING // Specifies whether the window will be always-on-top.
|
||||
AutoIconify Hint = C.GLFW_AUTO_ICONIFY // Specifies whether fullscreen windows automatically iconify (and restore the previous video mode) on focus loss.
|
||||
)
|
||||
|
||||
// Context related hints.
|
||||
const (
|
||||
ClientAPI Hint = C.GLFW_CLIENT_API // Specifies which client API to create the context for. Hard constraint.
|
||||
ContextVersionMajor Hint = C.GLFW_CONTEXT_VERSION_MAJOR // Specifies the client API version that the created context must be compatible with.
|
||||
ContextVersionMinor Hint = C.GLFW_CONTEXT_VERSION_MINOR // Specifies the client API version that the created context must be compatible with.
|
||||
ContextRobustness Hint = C.GLFW_CONTEXT_ROBUSTNESS // Specifies the robustness strategy to be used by the context.
|
||||
ContextReleaseBehavior Hint = C.GLFW_CONTEXT_RELEASE_BEHAVIOR // Specifies the release behavior to be used by the context.
|
||||
OpenGLForwardCompatible Hint = C.GLFW_OPENGL_FORWARD_COMPAT // Specifies whether the OpenGL context should be forward-compatible. Hard constraint.
|
||||
OpenGLDebugContext Hint = C.GLFW_OPENGL_DEBUG_CONTEXT // Specifies whether to create a debug OpenGL context, which may have additional error and performance issue reporting functionality. If OpenGL ES is requested, this hint is ignored.
|
||||
OpenGLProfile Hint = C.GLFW_OPENGL_PROFILE // Specifies which OpenGL profile to create the context for. Hard constraint.
|
||||
ContextCreationAPI Hint = C.GLFW_CONTEXT_CREATION_API // Specifies which context creation API to use to create the context.
|
||||
)
|
||||
|
||||
// Framebuffer related hints.
|
||||
const (
|
||||
ContextRevision Hint = C.GLFW_CONTEXT_REVISION
|
||||
RedBits Hint = C.GLFW_RED_BITS // Specifies the desired bit depth of the default framebuffer.
|
||||
GreenBits Hint = C.GLFW_GREEN_BITS // Specifies the desired bit depth of the default framebuffer.
|
||||
BlueBits Hint = C.GLFW_BLUE_BITS // Specifies the desired bit depth of the default framebuffer.
|
||||
AlphaBits Hint = C.GLFW_ALPHA_BITS // Specifies the desired bit depth of the default framebuffer.
|
||||
DepthBits Hint = C.GLFW_DEPTH_BITS // Specifies the desired bit depth of the default framebuffer.
|
||||
StencilBits Hint = C.GLFW_STENCIL_BITS // Specifies the desired bit depth of the default framebuffer.
|
||||
AccumRedBits Hint = C.GLFW_ACCUM_RED_BITS // Specifies the desired bit depth of the accumulation buffer.
|
||||
AccumGreenBits Hint = C.GLFW_ACCUM_GREEN_BITS // Specifies the desired bit depth of the accumulation buffer.
|
||||
AccumBlueBits Hint = C.GLFW_ACCUM_BLUE_BITS // Specifies the desired bit depth of the accumulation buffer.
|
||||
AccumAlphaBits Hint = C.GLFW_ACCUM_ALPHA_BITS // Specifies the desired bit depth of the accumulation buffer.
|
||||
AuxBuffers Hint = C.GLFW_AUX_BUFFERS // Specifies the desired number of auxiliary buffers.
|
||||
Stereo Hint = C.GLFW_STEREO // Specifies whether to use stereoscopic rendering. Hard constraint.
|
||||
Samples Hint = C.GLFW_SAMPLES // Specifies the desired number of samples to use for multisampling. Zero disables multisampling.
|
||||
SRGBCapable Hint = C.GLFW_SRGB_CAPABLE // Specifies whether the framebuffer should be sRGB capable.
|
||||
RefreshRate Hint = C.GLFW_REFRESH_RATE // Specifies the desired refresh rate for full screen windows. If set to zero, the highest available refresh rate will be used. This hint is ignored for windowed mode windows.
|
||||
DoubleBuffer Hint = C.GLFW_DOUBLEBUFFER // Specifies whether the framebuffer should be double buffered. You nearly always want to use double buffering. This is a hard constraint.
|
||||
)
|
||||
|
||||
// Values for the ClientAPI hint.
|
||||
const (
|
||||
OpenGLAPI int = C.GLFW_OPENGL_API
|
||||
OpenGLESAPI int = C.GLFW_OPENGL_ES_API
|
||||
NoAPI int = C.GLFW_NO_API
|
||||
)
|
||||
|
||||
// Values for ContextCreationAPI hint.
|
||||
const (
|
||||
NativeContextAPI int = C.GLFW_NATIVE_CONTEXT_API
|
||||
EGLContextAPI int = C.GLFW_EGL_CONTEXT_API
|
||||
)
|
||||
|
||||
// Values for the ContextRobustness hint.
|
||||
const (
|
||||
NoRobustness int = C.GLFW_NO_ROBUSTNESS
|
||||
NoResetNotification int = C.GLFW_NO_RESET_NOTIFICATION
|
||||
LoseContextOnReset int = C.GLFW_LOSE_CONTEXT_ON_RESET
|
||||
)
|
||||
|
||||
// Values for ContextReleaseBehavior hint.
|
||||
const (
|
||||
AnyReleaseBehavior int = C.GLFW_ANY_RELEASE_BEHAVIOR
|
||||
ReleaseBehaviorFlush int = C.GLFW_RELEASE_BEHAVIOR_FLUSH
|
||||
ReleaseBehaviorNone int = C.GLFW_RELEASE_BEHAVIOR_NONE
|
||||
)
|
||||
|
||||
// Values for the OpenGLProfile hint.
|
||||
const (
|
||||
OpenGLAnyProfile int = C.GLFW_OPENGL_ANY_PROFILE
|
||||
OpenGLCoreProfile int = C.GLFW_OPENGL_CORE_PROFILE
|
||||
OpenGLCompatProfile int = C.GLFW_OPENGL_COMPAT_PROFILE
|
||||
)
|
||||
|
||||
// Other values.
|
||||
const (
|
||||
True int = C.GL_TRUE
|
||||
False int = C.GL_FALSE
|
||||
DontCare int = C.GLFW_DONT_CARE
|
||||
)
|
||||
|
||||
// Window represents a window.
|
||||
type Window struct {
|
||||
data *C.GLFWwindow
|
||||
|
||||
// Window.
|
||||
fPosHolder func(w *Window, xpos int, ypos int)
|
||||
fSizeHolder func(w *Window, width int, height int)
|
||||
fFramebufferSizeHolder func(w *Window, width int, height int)
|
||||
fCloseHolder func(w *Window)
|
||||
fRefreshHolder func(w *Window)
|
||||
fFocusHolder func(w *Window, focused bool)
|
||||
fIconifyHolder func(w *Window, iconified bool)
|
||||
|
||||
// Input.
|
||||
fMouseButtonHolder func(w *Window, button MouseButton, action Action, mod ModifierKey)
|
||||
fCursorPosHolder func(w *Window, xpos float64, ypos float64)
|
||||
fCursorEnterHolder func(w *Window, entered bool)
|
||||
fScrollHolder func(w *Window, xoff float64, yoff float64)
|
||||
fKeyHolder func(w *Window, key Key, scancode int, action Action, mods ModifierKey)
|
||||
fCharHolder func(w *Window, char rune)
|
||||
fCharModsHolder func(w *Window, char rune, mods ModifierKey)
|
||||
fDropHolder func(w *Window, names []string)
|
||||
}
|
||||
|
||||
// GLFWWindow returns a *C.GLFWwindow reference (i.e. the GLFW window itself). This can be used for
|
||||
// passing the GLFW window handle to external C libraries.
|
||||
func (w *Window) GLFWWindow() uintptr {
|
||||
return uintptr(unsafe.Pointer(w.data))
|
||||
}
|
||||
|
||||
//export goWindowPosCB
|
||||
func goWindowPosCB(window unsafe.Pointer, xpos, ypos C.int) {
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
w.fPosHolder(w, int(xpos), int(ypos))
|
||||
}
|
||||
|
||||
//export goWindowSizeCB
|
||||
func goWindowSizeCB(window unsafe.Pointer, width, height C.int) {
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
w.fSizeHolder(w, int(width), int(height))
|
||||
}
|
||||
|
||||
//export goFramebufferSizeCB
|
||||
func goFramebufferSizeCB(window unsafe.Pointer, width, height C.int) {
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
w.fFramebufferSizeHolder(w, int(width), int(height))
|
||||
}
|
||||
|
||||
//export goWindowCloseCB
|
||||
func goWindowCloseCB(window unsafe.Pointer) {
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
w.fCloseHolder(w)
|
||||
}
|
||||
|
||||
//export goWindowRefreshCB
|
||||
func goWindowRefreshCB(window unsafe.Pointer) {
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
w.fRefreshHolder(w)
|
||||
}
|
||||
|
||||
//export goWindowFocusCB
|
||||
func goWindowFocusCB(window unsafe.Pointer, focused C.int) {
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
isFocused := glfwbool(focused)
|
||||
w.fFocusHolder(w, isFocused)
|
||||
}
|
||||
|
||||
//export goWindowIconifyCB
|
||||
func goWindowIconifyCB(window unsafe.Pointer, iconified C.int) {
|
||||
isIconified := glfwbool(iconified)
|
||||
w := windows.get((*C.GLFWwindow)(window))
|
||||
w.fIconifyHolder(w, isIconified)
|
||||
}
|
||||
|
||||
// DefaultWindowHints resets all window hints to their default values.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func DefaultWindowHints() {
|
||||
C.glfwDefaultWindowHints()
|
||||
panicError()
|
||||
}
|
||||
|
||||
// WindowHint sets hints for the next call to CreateWindow. The hints,
|
||||
// once set, retain their values until changed by a call to WindowHint or
|
||||
// DefaultWindowHints, or until the library is terminated with Terminate.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func WindowHint(target Hint, hint int) {
|
||||
C.glfwWindowHint(C.int(target), C.int(hint))
|
||||
panicError()
|
||||
}
|
||||
|
||||
// CreateWindow creates a window and its associated context. Most of the options
|
||||
// controlling how the window and its context should be created are specified
|
||||
// through Hint.
|
||||
//
|
||||
// Successful creation does not change which context is current. Before you can
|
||||
// use the newly created context, you need to make it current using
|
||||
// MakeContextCurrent.
|
||||
//
|
||||
// Note that the created window and context may differ from what you requested,
|
||||
// as not all parameters and hints are hard constraints. This includes the size
|
||||
// of the window, especially for full screen windows. To retrieve the actual
|
||||
// attributes of the created window and context, use queries like
|
||||
// GetWindowAttrib and GetWindowSize.
|
||||
//
|
||||
// To create the window at a specific position, make it initially invisible using
|
||||
// the Visible window hint, set its position and then show it.
|
||||
//
|
||||
// If a fullscreen window is active, the screensaver is prohibited from starting.
|
||||
//
|
||||
// Windows: If the executable has an icon resource named GLFW_ICON, it will be
|
||||
// set as the icon for the window. If no such icon is present, the IDI_WINLOGO
|
||||
// icon will be used instead.
|
||||
//
|
||||
// Mac OS X: The GLFW window has no icon, as it is not a document window, but the
|
||||
// dock icon will be the same as the application bundle's icon. Also, the first
|
||||
// time a window is opened the menu bar is populated with common commands like
|
||||
// Hide, Quit and About. The (minimal) about dialog uses information from the
|
||||
// application's bundle. For more information on bundles, see the Bundle
|
||||
// Programming Guide provided by Apple.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func CreateWindow(width, height int, title string, monitor *Monitor, share *Window) (*Window, error) {
|
||||
var (
|
||||
m *C.GLFWmonitor
|
||||
s *C.GLFWwindow
|
||||
)
|
||||
|
||||
t := C.CString(title)
|
||||
defer C.free(unsafe.Pointer(t))
|
||||
|
||||
if monitor != nil {
|
||||
m = monitor.data
|
||||
}
|
||||
|
||||
if share != nil {
|
||||
s = share.data
|
||||
}
|
||||
|
||||
w := C.glfwCreateWindow(C.int(width), C.int(height), t, m, s)
|
||||
if w == nil {
|
||||
return nil, acceptError(APIUnavailable, VersionUnavailable)
|
||||
}
|
||||
|
||||
wnd := &Window{data: w}
|
||||
windows.put(wnd)
|
||||
return wnd, nil
|
||||
}
|
||||
|
||||
// Destroy destroys the specified window and its context. On calling this
|
||||
// function, no further callbacks will be called for that window.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func (w *Window) Destroy() {
|
||||
windows.remove(w.data)
|
||||
C.glfwDestroyWindow(w.data)
|
||||
panicError()
|
||||
}
|
||||
|
||||
// ShouldClose reports the value of the close flag of the specified window.
|
||||
func (w *Window) ShouldClose() bool {
|
||||
ret := glfwbool(C.glfwWindowShouldClose(w.data))
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// SetShouldClose sets the value of the close flag of the window. This can be
|
||||
// used to override the user's attempt to close the window, or to signal that it
|
||||
// should be closed.
|
||||
func (w *Window) SetShouldClose(value bool) {
|
||||
if !value {
|
||||
C.glfwSetWindowShouldClose(w.data, C.GL_FALSE)
|
||||
} else {
|
||||
C.glfwSetWindowShouldClose(w.data, C.GL_TRUE)
|
||||
}
|
||||
panicError()
|
||||
}
|
||||
|
||||
// SetTitle sets the window title, encoded as UTF-8, of the window.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func (w *Window) SetTitle(title string) {
|
||||
t := C.CString(title)
|
||||
defer C.free(unsafe.Pointer(t))
|
||||
C.glfwSetWindowTitle(w.data, t)
|
||||
panicError()
|
||||
}
|
||||
|
||||
// SetIcon sets the icon of the specified window. If passed an array of candidate images,
|
||||
// those of or closest to the sizes desired by the system are selected. If no images are
|
||||
// specified, the window reverts to its default icon.
|
||||
//
|
||||
// The image is ideally provided in the form of *image.NRGBA.
|
||||
// The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
|
||||
// bits per channel with the red channel first. They are arranged canonically
|
||||
// as packed sequential rows, starting from the top-left corner. If the image
|
||||
// type is not *image.NRGBA, it will be converted to it.
|
||||
//
|
||||
// The desired image sizes varies depending on platform and system settings. The selected
|
||||
// images will be rescaled as needed. Good sizes include 16x16, 32x32 and 48x48.
|
||||
func (w *Window) SetIcon(images []image.Image) {
|
||||
count := len(images)
|
||||
cimages := make([]C.GLFWimage, count)
|
||||
freePixels := make([]func(), count)
|
||||
|
||||
for i, img := range images {
|
||||
var pixels []uint8
|
||||
b := img.Bounds()
|
||||
|
||||
switch img := img.(type) {
|
||||
case *image.NRGBA:
|
||||
pixels = img.Pix
|
||||
default:
|
||||
m := image.NewNRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
|
||||
draw.Draw(m, m.Bounds(), img, b.Min, draw.Src)
|
||||
pixels = m.Pix
|
||||
}
|
||||
|
||||
pix, free := bytes(pixels)
|
||||
freePixels[i] = free
|
||||
|
||||
cimages[i].width = C.int(b.Dx())
|
||||
cimages[i].height = C.int(b.Dy())
|
||||
cimages[i].pixels = (*C.uchar)(pix)
|
||||
}
|
||||
|
||||
var p *C.GLFWimage
|
||||
if count > 0 {
|
||||
p = &cimages[0]
|
||||
}
|
||||
C.glfwSetWindowIcon(w.data, C.int(count), p)
|
||||
|
||||
for _, v := range freePixels {
|
||||
v()
|
||||
}
|
||||
|
||||
panicError()
|
||||
}
|
||||
|
||||
// GetPos returns the position, in screen coordinates, of the upper-left
|
||||
// corner of the client area of the window.
|
||||
func (w *Window) GetPos() (x, y int) {
|
||||
var xpos, ypos C.int
|
||||
C.glfwGetWindowPos(w.data, &xpos, &ypos)
|
||||
panicError()
|
||||
return int(xpos), int(ypos)
|
||||
}
|
||||
|
||||
// SetPos sets the position, in screen coordinates, of the upper-left corner
|
||||
// of the client area of the window.
|
||||
//
|
||||
// If it is a full screen window, this function does nothing.
|
||||
//
|
||||
// If you wish to set an initial window position you should create a hidden
|
||||
// window (using Hint and Visible), set its position and then show it.
|
||||
//
|
||||
// It is very rarely a good idea to move an already visible window, as it will
|
||||
// confuse and annoy the user.
|
||||
//
|
||||
// The window manager may put limits on what positions are allowed.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func (w *Window) SetPos(xpos, ypos int) {
|
||||
C.glfwSetWindowPos(w.data, C.int(xpos), C.int(ypos))
|
||||
panicError()
|
||||
}
|
||||
|
||||
// GetSize returns the size, in screen coordinates, of the client area of the
|
||||
// specified window.
|
||||
func (w *Window) GetSize() (width, height int) {
|
||||
var wi, h C.int
|
||||
C.glfwGetWindowSize(w.data, &wi, &h)
|
||||
panicError()
|
||||
return int(wi), int(h)
|
||||
}
|
||||
|
||||
// SetSize sets the size, in screen coordinates, of the client area of the
|
||||
// window.
|
||||
//
|
||||
// For full screen windows, this function selects and switches to the resolution
|
||||
// closest to the specified size, without affecting the window's context. As the
|
||||
// context is unaffected, the bit depths of the framebuffer remain unchanged.
|
||||
//
|
||||
// The window manager may put limits on what window sizes are allowed.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func (w *Window) SetSize(width, height int) {
|
||||
C.glfwSetWindowSize(w.data, C.int(width), C.int(height))
|
||||
panicError()
|
||||
}
|
||||
|
||||
// SetSizeLimits sets the size limits of the client area of the specified window.
|
||||
// If the window is full screen or not resizable, this function does nothing.
|
||||
//
|
||||
// The size limits are applied immediately and may cause the window to be resized.
|
||||
func (w *Window) SetSizeLimits(minw, minh, maxw, maxh int) {
|
||||
C.glfwSetWindowSizeLimits(w.data, C.int(minw), C.int(minh), C.int(maxw), C.int(maxh))
|
||||
panicError()
|
||||
}
|
||||
|
||||
// SetAspectRatio sets the required aspect ratio of the client area of the specified window.
|
||||
// If the window is full screen or not resizable, this function does nothing.
|
||||
//
|
||||
// The aspect ratio is specified as a numerator and a denominator and both values must be greater
|
||||
// than zero. For example, the common 16:9 aspect ratio is specified as 16 and 9, respectively.
|
||||
//
|
||||
// If the numerator and denominator is set to glfw.DontCare then the aspect ratio limit is disabled.
|
||||
//
|
||||
// The aspect ratio is applied immediately and may cause the window to be resized.
|
||||
func (w *Window) SetAspectRatio(numer, denom int) {
|
||||
C.glfwSetWindowAspectRatio(w.data, C.int(numer), C.int(denom))
|
||||
panicError()
|
||||
}
|
||||
|
||||
// GetFramebufferSize retrieves the size, in pixels, of the framebuffer of the
|
||||
// specified window.
|
||||
func (w *Window) GetFramebufferSize() (width, height int) {
|
||||
var wi, h C.int
|
||||
C.glfwGetFramebufferSize(w.data, &wi, &h)
|
||||
panicError()
|
||||
return int(wi), int(h)
|
||||
}
|
||||
|
||||
// GetFrameSize retrieves the size, in screen coordinates, of each edge of the frame
|
||||
// of the specified window. This size includes the title bar, if the window has one.
|
||||
// The size of the frame may vary depending on the window-related hints used to create it.
|
||||
//
|
||||
// Because this function retrieves the size of each window frame edge and not the offset
|
||||
// along a particular coordinate axis, the retrieved values will always be zero or positive.
|
||||
func (w *Window) GetFrameSize() (left, top, right, bottom int) {
|
||||
var l, t, r, b C.int
|
||||
C.glfwGetWindowFrameSize(w.data, &l, &t, &r, &b)
|
||||
panicError()
|
||||
return int(l), int(t), int(r), int(b)
|
||||
}
|
||||
|
||||
// Focus brings the specified window to front and sets input focus.
|
||||
// The window should already be visible and not iconified.
|
||||
//
|
||||
// By default, both windowed and full screen mode windows are focused when initially created.
|
||||
// Set the glfw.Focused to disable this behavior.
|
||||
//
|
||||
// Do not use this function to steal focus from other applications unless you are certain that
|
||||
// is what the user wants. Focus stealing can be extremely disruptive.
|
||||
func (w *Window) Focus() error {
|
||||
C.glfwFocusWindow(w.data)
|
||||
return acceptError(APIUnavailable)
|
||||
}
|
||||
|
||||
// Iconify iconifies/minimizes the window, if it was previously restored. If it
|
||||
// is a full screen window, the original monitor resolution is restored until the
|
||||
// window is restored. If the window is already iconified, this function does
|
||||
// nothing.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func (w *Window) Iconify() error {
|
||||
C.glfwIconifyWindow(w.data)
|
||||
return acceptError(APIUnavailable)
|
||||
}
|
||||
|
||||
// Maximize maximizes the specified window if it was previously not maximized.
|
||||
// If the window is already maximized, this function does nothing.
|
||||
//
|
||||
// If the specified window is a full screen window, this function does nothing.
|
||||
func (w *Window) Maximize() error {
|
||||
C.glfwMaximizeWindow(w.data)
|
||||
return acceptError(APIUnavailable)
|
||||
}
|
||||
|
||||
// Restore restores the window, if it was previously iconified/minimized. If it
|
||||
// is a full screen window, the resolution chosen for the window is restored on
|
||||
// the selected monitor. If the window is already restored, this function does
|
||||
// nothing.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func (w *Window) Restore() error {
|
||||
C.glfwRestoreWindow(w.data)
|
||||
return acceptError(APIUnavailable)
|
||||
}
|
||||
|
||||
// Show makes the window visible, if it was previously hidden. If the window is
|
||||
// already visible or is in full screen mode, this function does nothing.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func (w *Window) Show() {
|
||||
C.glfwShowWindow(w.data)
|
||||
panicError()
|
||||
}
|
||||
|
||||
// Hide hides the window, if it was previously visible. If the window is already
|
||||
// hidden or is in full screen mode, this function does nothing.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func (w *Window) Hide() {
|
||||
C.glfwHideWindow(w.data)
|
||||
panicError()
|
||||
}
|
||||
|
||||
// GetMonitor returns the handle of the monitor that the window is in
|
||||
// fullscreen on.
|
||||
//
|
||||
// Returns nil if the window is in windowed mode.
|
||||
func (w *Window) GetMonitor() *Monitor {
|
||||
m := C.glfwGetWindowMonitor(w.data)
|
||||
panicError()
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
return &Monitor{m}
|
||||
}
|
||||
|
||||
// SetMonitor sets the monitor that the window uses for full screen mode or,
|
||||
// if the monitor is NULL, makes it windowed mode.
|
||||
//
|
||||
// When setting a monitor, this function updates the width, height and refresh
|
||||
// rate of the desired video mode and switches to the video mode closest to it.
|
||||
// The window position is ignored when setting a monitor.
|
||||
//
|
||||
// When the monitor is NULL, the position, width and height are used to place
|
||||
// the window client area. The refresh rate is ignored when no monitor is specified.
|
||||
// If you only wish to update the resolution of a full screen window or the size of
|
||||
// a windowed mode window, see window.SetSize.
|
||||
//
|
||||
// When a window transitions from full screen to windowed mode, this function
|
||||
// restores any previous window settings such as whether it is decorated, floating,
|
||||
// resizable, has size or aspect ratio limits, etc..
|
||||
func (w *Window) SetMonitor(monitor *Monitor, xpos, ypos, width, height, refreshRate int) {
|
||||
var m *C.GLFWmonitor
|
||||
if monitor == nil {
|
||||
m = nil
|
||||
} else {
|
||||
m = monitor.data
|
||||
}
|
||||
C.glfwSetWindowMonitor(w.data, m, C.int(xpos), C.int(ypos), C.int(width), C.int(height), C.int(refreshRate))
|
||||
panicError()
|
||||
}
|
||||
|
||||
// GetAttrib returns an attribute of the window. There are many attributes,
|
||||
// some related to the window and others to its context.
|
||||
func (w *Window) GetAttrib(attrib Hint) int {
|
||||
ret := int(C.glfwGetWindowAttrib(w.data, C.int(attrib)))
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// SetUserPointer sets the user-defined pointer of the window. The current value
|
||||
// is retained until the window is destroyed. The initial value is nil.
|
||||
func (w *Window) SetUserPointer(pointer unsafe.Pointer) {
|
||||
C.glfwSetWindowUserPointer(w.data, pointer)
|
||||
panicError()
|
||||
}
|
||||
|
||||
// GetUserPointer returns the current value of the user-defined pointer of the
|
||||
// window. The initial value is nil.
|
||||
func (w *Window) GetUserPointer() unsafe.Pointer {
|
||||
ret := C.glfwGetWindowUserPointer(w.data)
|
||||
panicError()
|
||||
return ret
|
||||
}
|
||||
|
||||
// PosCallback is the window position callback.
|
||||
type PosCallback func(w *Window, xpos int, ypos int)
|
||||
|
||||
// SetPosCallback sets the position callback of the window, which is called
|
||||
// when the window is moved. The callback is provided with the screen position
|
||||
// of the upper-left corner of the client area of the window.
|
||||
func (w *Window) SetPosCallback(cbfun PosCallback) (previous PosCallback) {
|
||||
previous = w.fPosHolder
|
||||
w.fPosHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetWindowPosCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetWindowPosCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// SizeCallback is the window size callback.
|
||||
type SizeCallback func(w *Window, width int, height int)
|
||||
|
||||
// SetSizeCallback sets the size callback of the window, which is called when
|
||||
// the window is resized. The callback is provided with the size, in screen
|
||||
// coordinates, of the client area of the window.
|
||||
func (w *Window) SetSizeCallback(cbfun SizeCallback) (previous SizeCallback) {
|
||||
previous = w.fSizeHolder
|
||||
w.fSizeHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetWindowSizeCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetWindowSizeCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// FramebufferSizeCallback is the framebuffer size callback.
|
||||
type FramebufferSizeCallback func(w *Window, width int, height int)
|
||||
|
||||
// SetFramebufferSizeCallback sets the framebuffer resize callback of the specified
|
||||
// window, which is called when the framebuffer of the specified window is resized.
|
||||
func (w *Window) SetFramebufferSizeCallback(cbfun FramebufferSizeCallback) (previous FramebufferSizeCallback) {
|
||||
previous = w.fFramebufferSizeHolder
|
||||
w.fFramebufferSizeHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetFramebufferSizeCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetFramebufferSizeCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// CloseCallback is the window close callback.
|
||||
type CloseCallback func(w *Window)
|
||||
|
||||
// SetCloseCallback sets the close callback of the window, which is called when
|
||||
// the user attempts to close the window, for example by clicking the close
|
||||
// widget in the title bar.
|
||||
//
|
||||
// The close flag is set before this callback is called, but you can modify it at
|
||||
// any time with SetShouldClose.
|
||||
//
|
||||
// Mac OS X: Selecting Quit from the application menu will trigger the close
|
||||
// callback for all windows.
|
||||
func (w *Window) SetCloseCallback(cbfun CloseCallback) (previous CloseCallback) {
|
||||
previous = w.fCloseHolder
|
||||
w.fCloseHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetWindowCloseCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetWindowCloseCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// RefreshCallback is the window refresh callback.
|
||||
type RefreshCallback func(w *Window)
|
||||
|
||||
// SetRefreshCallback sets the refresh callback of the window, which
|
||||
// is called when the client area of the window needs to be redrawn, for example
|
||||
// if the window has been exposed after having been covered by another window.
|
||||
//
|
||||
// On compositing window systems such as Aero, Compiz or Aqua, where the window
|
||||
// contents are saved off-screen, this callback may be called only very
|
||||
// infrequently or never at all.
|
||||
func (w *Window) SetRefreshCallback(cbfun RefreshCallback) (previous RefreshCallback) {
|
||||
previous = w.fRefreshHolder
|
||||
w.fRefreshHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetWindowRefreshCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetWindowRefreshCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// FocusCallback is the window focus callback.
|
||||
type FocusCallback func(w *Window, focused bool)
|
||||
|
||||
// SetFocusCallback sets the focus callback of the window, which is called when
|
||||
// the window gains or loses focus.
|
||||
//
|
||||
// After the focus callback is called for a window that lost focus, synthetic key
|
||||
// and mouse button release events will be generated for all such that had been
|
||||
// pressed. For more information, see SetKeyCallback and SetMouseButtonCallback.
|
||||
func (w *Window) SetFocusCallback(cbfun FocusCallback) (previous FocusCallback) {
|
||||
previous = w.fFocusHolder
|
||||
w.fFocusHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetWindowFocusCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetWindowFocusCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// IconifyCallback is the window iconification callback.
|
||||
type IconifyCallback func(w *Window, iconified bool)
|
||||
|
||||
// SetIconifyCallback sets the iconification callback of the window, which is
|
||||
// called when the window is iconified or restored.
|
||||
func (w *Window) SetIconifyCallback(cbfun IconifyCallback) (previous IconifyCallback) {
|
||||
previous = w.fIconifyHolder
|
||||
w.fIconifyHolder = cbfun
|
||||
if cbfun == nil {
|
||||
C.glfwSetWindowIconifyCallback(w.data, nil)
|
||||
} else {
|
||||
C.glfwSetWindowIconifyCallbackCB(w.data)
|
||||
}
|
||||
panicError()
|
||||
return previous
|
||||
}
|
||||
|
||||
// SetClipboardString sets the system clipboard to the specified UTF-8 encoded
|
||||
// string.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func (w *Window) SetClipboardString(str string) {
|
||||
cp := C.CString(str)
|
||||
defer C.free(unsafe.Pointer(cp))
|
||||
C.glfwSetClipboardString(w.data, cp)
|
||||
panicError()
|
||||
}
|
||||
|
||||
// GetClipboardString returns the contents of the system clipboard, if it
|
||||
// contains or is convertible to a UTF-8 encoded string.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func (w *Window) GetClipboardString() (string, error) {
|
||||
cs := C.glfwGetClipboardString(w.data)
|
||||
if cs == nil {
|
||||
return "", acceptError(FormatUnavailable)
|
||||
}
|
||||
return C.GoString(cs), nil
|
||||
}
|
||||
|
||||
// PollEvents processes only those events that have already been received and
|
||||
// then returns immediately. Processing events will cause the window and input
|
||||
// callbacks associated with those events to be called.
|
||||
//
|
||||
// This function is not required for joystick input to work.
|
||||
//
|
||||
// This function may not be called from a callback.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func PollEvents() {
|
||||
C.glfwPollEvents()
|
||||
panicError()
|
||||
}
|
||||
|
||||
// WaitEvents puts the calling thread to sleep until at least one event has been
|
||||
// received. Once one or more events have been recevied, it behaves as if
|
||||
// PollEvents was called, i.e. the events are processed and the function then
|
||||
// returns immediately. Processing events will cause the window and input
|
||||
// callbacks associated with those events to be called.
|
||||
//
|
||||
// Since not all events are associated with callbacks, this function may return
|
||||
// without a callback having been called even if you are monitoring all
|
||||
// callbacks.
|
||||
//
|
||||
// This function may not be called from a callback.
|
||||
//
|
||||
// This function may only be called from the main thread.
|
||||
func WaitEvents() {
|
||||
C.glfwWaitEvents()
|
||||
panicError()
|
||||
}
|
||||
|
||||
// WaitEventsTimeout puts the calling thread to sleep until at least one event is available in the
|
||||
// event queue, or until the specified timeout is reached. If one or more events are available,
|
||||
// it behaves exactly like PollEvents, i.e. the events in the queue are processed and the function
|
||||
// then returns immediately. Processing events will cause the window and input callbacks associated
|
||||
// with those events to be called.
|
||||
//
|
||||
// The timeout value must be a positive finite number.
|
||||
//
|
||||
// Since not all events are associated with callbacks, this function may return without a callback
|
||||
// having been called even if you are monitoring all callbacks.
|
||||
//
|
||||
// On some platforms, a window move, resize or menu operation will cause event processing to block.
|
||||
// This is due to how event processing is designed on those platforms. You can use the window
|
||||
// refresh callback to redraw the contents of your window when necessary during such operations.
|
||||
//
|
||||
// On some platforms, certain callbacks may be called outside of a call to one of the event
|
||||
// processing functions.
|
||||
//
|
||||
// If no windows exist, this function returns immediately. For synchronization of threads in
|
||||
// applications that do not create windows, use native Go primitives.
|
||||
//
|
||||
// Event processing is not required for joystick input to work.
|
||||
func WaitEventsTimeout(timeout float64) {
|
||||
C.glfwWaitEventsTimeout(C.double(timeout))
|
||||
panicError()
|
||||
}
|
||||
|
||||
// PostEmptyEvent posts an empty event from the current thread to the main
|
||||
// thread event queue, causing WaitEvents to return.
|
||||
//
|
||||
// If no windows exist, this function returns immediately. For synchronization of threads in
|
||||
// applications that do not create windows, use native Go primitives.
|
||||
//
|
||||
// This function may be called from secondary threads.
|
||||
func PostEmptyEvent() {
|
||||
C.glfwPostEmptyEvent()
|
||||
panicError()
|
||||
}
|
14
vendor/github.com/go-gl/mathgl/AUTHORS
generated
vendored
Normal file
14
vendor/github.com/go-gl/mathgl/AUTHORS
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# This is the official list of go-gl/mathgl authors for copyright purposes.
|
||||
# This file is distinct from the CONTRIBUTORS files.
|
||||
# See the latter for an explanation.
|
||||
|
||||
# Names should be added to this file as
|
||||
# Name or Organization <email address>
|
||||
# The email address is not required for organizations.
|
||||
|
||||
# Please keep the list sorted.
|
||||
|
||||
Alex Vasi <eee@someuser.com>
|
||||
Dmitri Shuralyov <shurcooL@gmail.com>
|
||||
GlenKelley <???>
|
||||
Zoe Juozapaitis <jragonmiris@gmail.com>
|
21
vendor/github.com/go-gl/mathgl/CONTRIBUTORS
generated
vendored
Normal file
21
vendor/github.com/go-gl/mathgl/CONTRIBUTORS
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# This is the official list of people who can contribute
|
||||
# (and typically have contributed) code to the mathgl
|
||||
# repository.
|
||||
#
|
||||
# The AUTHORS file lists the copyright holders; this file
|
||||
# lists people. For example, Google employees would be listed here
|
||||
# but not in AUTHORS, because Google would hold the copyright.
|
||||
#
|
||||
# When adding J Random Contributor's name to this file,
|
||||
# either J's name or J's organization's name should be
|
||||
# added to the AUTHORS file.
|
||||
#
|
||||
# Names should be added to this file like so:
|
||||
# Name <email address>
|
||||
#
|
||||
# Please keep the list sorted.
|
||||
|
||||
Alex Vasi <eee@someuser.com>
|
||||
Dmitri Shuralyov <shurcooL@gmail.com>
|
||||
GlenKelley <???>
|
||||
Zoe Juozapaitis <jragonmiris@gmail.com>
|
23
vendor/github.com/go-gl/mathgl/LICENSE
generated
vendored
Normal file
23
vendor/github.com/go-gl/mathgl/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
Copyright ©2013 The go-gl Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the gonum project nor the names of its authors and
|
||||
contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
276
vendor/github.com/go-gl/mathgl/mgl32/codegen.go
generated
vendored
Normal file
276
vendor/github.com/go-gl/mathgl/mgl32/codegen.go
generated
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
// Copyright 2014 The go-gl/mathgl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// codegen generates go code from templates. Intended to be
|
||||
// used with go generate; Also makes mgl64 from mgl32.
|
||||
// See the invocation in mgl32/util.go for details.
|
||||
// To use it, just run "go generate github.com/go-gl/mathgl/mgl32"
|
||||
// (or "go generate" in mgl32 directory).
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
Comment string
|
||||
TemplateName string
|
||||
}
|
||||
|
||||
type MatrixIter struct {
|
||||
M int // row
|
||||
N int // column
|
||||
index int
|
||||
}
|
||||
|
||||
var mgl64RewriteRules = []string{
|
||||
"mgl32 -> mgl64",
|
||||
"float32 -> float64",
|
||||
"f32 -> f64",
|
||||
"a.Float32 -> a.Float64",
|
||||
"math.MaxFloat32 -> math.MaxFloat64",
|
||||
"math.SmallestNonzeroFloat32 -> math.SmallestNonzeroFloat64",
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = func() {
|
||||
fmt.Println("Usage: codegen -template file.tmpl -output file.go")
|
||||
fmt.Println("Usage: codegen -mgl64 [-dir ../mgl64]")
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
tmplPath := flag.String("template", "file.tmpl", "template path")
|
||||
oPath := flag.String("output", "file.go", "output path")
|
||||
mgl64 := flag.Bool("mgl64", false, "make mgl64")
|
||||
mgl64Path := flag.String("dir", "../mgl64", "path to mgl64 location")
|
||||
|
||||
flag.Parse()
|
||||
if flag.NArg() > 0 || flag.NFlag() == 0 {
|
||||
flag.Usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
if *mgl64 {
|
||||
genMgl64(*mgl64Path)
|
||||
return
|
||||
}
|
||||
|
||||
tmpl := template.New("").Delims("<<", ">>").Funcs(template.FuncMap{
|
||||
"typename": typenameHelper,
|
||||
"elementname": elementNameHelper,
|
||||
"iter": iterHelper,
|
||||
"matiter": matrixIterHelper,
|
||||
"enum": enumHelper,
|
||||
"sep": separatorHelper,
|
||||
"repeat": repeatHelper,
|
||||
"add": addHelper,
|
||||
"mul": mulHelper,
|
||||
})
|
||||
tmpl = template.Must(tmpl.ParseFiles(*tmplPath))
|
||||
tmplName := filepath.Base(*tmplPath)
|
||||
|
||||
oFile, err := os.Create(*oPath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
context := Context{
|
||||
Comment: "This file is generated by codegen.go; DO NOT EDIT",
|
||||
TemplateName: tmplName,
|
||||
}
|
||||
if err = tmpl.ExecuteTemplate(oFile, tmplName, context); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
oFile.Close()
|
||||
|
||||
if err = rungofmt(*oPath, false, nil); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func genMgl64(destPath string) {
|
||||
HandleFile := func(source string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dest := filepath.Join(destPath, source)
|
||||
|
||||
if info.IsDir() {
|
||||
return os.MkdirAll(dest, info.Mode())
|
||||
}
|
||||
if !strings.HasSuffix(source, ".go") || info.Name() == "codegen.go" {
|
||||
return nil
|
||||
}
|
||||
if !info.Mode().IsRegular() {
|
||||
fmt.Println("Ignored, not a regular file:", source)
|
||||
return nil
|
||||
}
|
||||
|
||||
in, err := ioutil.ReadFile(source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC,
|
||||
info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
comment := fmt.Sprintf(
|
||||
"// This file is generated from mgl32/%s; DO NOT EDIT\n\n",
|
||||
source)
|
||||
if _, err = out.WriteString(comment); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r := strings.NewReplacer("//go:generate ", "//#go:generate ") // We don't want go generate directives in mgl64 package.
|
||||
|
||||
if _, err = r.WriteString(out, string(in)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return rungofmt(dest, true, mgl64RewriteRules)
|
||||
}
|
||||
|
||||
if err := filepath.Walk(".", HandleFile); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func rungofmt(path string, fiximports bool, rewriteRules []string) error {
|
||||
args := []string{"-w", path}
|
||||
output, err := exec.Command("gofmt", args...).CombinedOutput()
|
||||
|
||||
for i := 0; err == nil && i < len(rewriteRules); i++ {
|
||||
args = []string{"-w", "-r", rewriteRules[i], path}
|
||||
output, err = exec.Command("gofmt", args...).CombinedOutput()
|
||||
}
|
||||
|
||||
if fiximports && err == nil {
|
||||
args = []string{"-w", path}
|
||||
output, err = exec.Command("goimports", args...).CombinedOutput()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Println("Error executing gofmt", strings.Join(args, " "))
|
||||
os.Stdout.Write(output)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func typenameHelper(m, n int) string {
|
||||
if m == 1 {
|
||||
return fmt.Sprintf("Vec%d", n)
|
||||
}
|
||||
if n == 1 {
|
||||
return fmt.Sprintf("Vec%d", m)
|
||||
}
|
||||
if m == n {
|
||||
return fmt.Sprintf("Mat%d", m)
|
||||
}
|
||||
return fmt.Sprintf("Mat%dx%d", m, n)
|
||||
}
|
||||
|
||||
func elementNameHelper(m int) string {
|
||||
switch m {
|
||||
case 0:
|
||||
return "X"
|
||||
case 1:
|
||||
return "Y"
|
||||
case 2:
|
||||
return "Z"
|
||||
case 3:
|
||||
return "W"
|
||||
default:
|
||||
panic("Can't generate element name")
|
||||
}
|
||||
}
|
||||
|
||||
func iterHelper(start, end int) []int {
|
||||
iter := make([]int, end-start)
|
||||
for i := start; i < end; i++ {
|
||||
iter[i] = i
|
||||
}
|
||||
return iter
|
||||
}
|
||||
|
||||
func matrixIterHelper(rows, cols int) []MatrixIter {
|
||||
res := make([]MatrixIter, 0, rows*cols)
|
||||
|
||||
for n := 0; n < cols; n++ {
|
||||
for m := 0; m < rows; m++ {
|
||||
res = append(res, MatrixIter{
|
||||
M: m,
|
||||
N: n,
|
||||
index: n*rows + m,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// Template function that returns slice from its arguments. Indended to be used
|
||||
// in range loops.
|
||||
func enumHelper(args ...int) []int {
|
||||
return args
|
||||
}
|
||||
|
||||
// Template function to insert commas and '+' in range loops.
|
||||
func separatorHelper(sep string, iterCond int) string {
|
||||
if iterCond > 0 {
|
||||
return sep
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Template function to repeat string 'count' times. Inserting 'sep' between
|
||||
// repetitions. Also changes all occurrences of '%d' to repetition number.
|
||||
// For example, repeatHelper(3, "col%d", ",") will output "col0, col1, col2"
|
||||
func repeatHelper(count int, text string, sep string) string {
|
||||
var res bytes.Buffer
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
if i > 0 {
|
||||
res.WriteString(sep)
|
||||
}
|
||||
res.WriteString(strings.Replace(text, "%d", fmt.Sprintf("%d", i), -1))
|
||||
}
|
||||
|
||||
return res.String()
|
||||
}
|
||||
|
||||
func addHelper(args ...int) int {
|
||||
res := 0
|
||||
for _, a := range args {
|
||||
res += a
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func mulHelper(args ...int) int {
|
||||
res := 1
|
||||
for _, a := range args {
|
||||
res *= a
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (i MatrixIter) String() string {
|
||||
return fmt.Sprintf("%d", i.index)
|
||||
}
|
94
vendor/github.com/go-gl/mathgl/mgl32/conv.go
generated
vendored
Normal file
94
vendor/github.com/go-gl/mathgl/mgl32/conv.go
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
// Copyright 2014 The go-gl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mgl32
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// Converts 3-dimensional cartesian coordinates (x,y,z) to spherical
|
||||
// coordinates with radius r, inclination theta, and azimuth phi.
|
||||
//
|
||||
// All angles are in radians.
|
||||
func CartesianToSpherical(coord Vec3) (r, theta, phi float32) {
|
||||
r = coord.Len()
|
||||
theta = float32(math.Acos(float64(coord[2] / r)))
|
||||
phi = float32(math.Atan2(float64(coord[1]), float64(coord[0])))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Converts 3-dimensional cartesian coordinates (x,y,z) to cylindrical
|
||||
// coordinates with radial distance r, azimuth phi, and height z.
|
||||
//
|
||||
// All angles are in radians.
|
||||
func CartesianToCylindical(coord Vec3) (rho, phi, z float32) {
|
||||
rho = float32(math.Hypot(float64(coord[0]), float64(coord[1])))
|
||||
|
||||
phi = float32(math.Atan2(float64(coord[1]), float64(coord[0])))
|
||||
|
||||
z = coord[2]
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Converts spherical coordinates with radius r, inclination theta,
|
||||
// and azimuth phi to cartesian coordinates (x,y,z).
|
||||
//
|
||||
// Angles are in radians.
|
||||
func SphericalToCartesian(r, theta, phi float32) Vec3 {
|
||||
st, ct := math.Sincos(float64(theta))
|
||||
sp, cp := math.Sincos(float64(phi))
|
||||
|
||||
return Vec3{r * float32(st*cp), r * float32(st*sp), r * float32(ct)}
|
||||
}
|
||||
|
||||
// Converts spherical coordinates with radius r, inclination theta,
|
||||
// and azimuth phi to cylindrical coordinates with radial distance r,
|
||||
// azimuth phi, and height z.
|
||||
//
|
||||
// Angles are in radians
|
||||
func SphericalToCylindrical(r, theta, phi float32) (rho, phi2, z float32) {
|
||||
s, c := math.Sincos(float64(theta))
|
||||
|
||||
rho = r * float32(s)
|
||||
z = r * float32(c)
|
||||
phi2 = phi
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Converts cylindrical coordinates with radial distance r,
|
||||
// azimuth phi, and height z to spherical coordinates with radius r,
|
||||
// inclination theta, and azimuth phi.
|
||||
//
|
||||
// Angles are in radians
|
||||
func CylindircalToSpherical(rho, phi, z float32) (r, theta, phi2 float32) {
|
||||
r = float32(math.Hypot(float64(rho), float64(z)))
|
||||
phi2 = phi
|
||||
theta = float32(math.Atan2(float64(rho), float64(z)))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Converts cylindrical coordinates with radial distance r,
|
||||
// azimuth phi, and height z to cartesian coordinates (x,y,z)
|
||||
//
|
||||
// Angles are in radians.
|
||||
func CylindricalToCartesian(rho, phi, z float32) Vec3 {
|
||||
s, c := math.Sincos(float64(phi))
|
||||
|
||||
return Vec3{rho * float32(c), rho * float32(s), z}
|
||||
}
|
||||
|
||||
// Converts degrees to radians
|
||||
func DegToRad(angle float32) float32 {
|
||||
return angle * float32(math.Pi) / 180
|
||||
}
|
||||
|
||||
// Converts radians to degrees
|
||||
func RadToDeg(angle float32) float32 {
|
||||
return angle * 180 / float32(math.Pi)
|
||||
}
|
22
vendor/github.com/go-gl/mathgl/mgl32/doc.go
generated
vendored
Normal file
22
vendor/github.com/go-gl/mathgl/mgl32/doc.go
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2014 The go-gl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
Package mgl[32|64] (an abbreviation of mathgl since the packages were split between 32 and 64-bit versions)
|
||||
is a pure Go math package specialized for 3D math, with inspiration from GLM. It provides statically-sized vectors and matrices with
|
||||
compile-time generated calculations for most basic math operations. It also provides several basic graphics utilities such as bezier curves and surfaces,
|
||||
generation of basic primitives like circles, easy creation of common matrices such as perspective or rotation, and common operations like converting
|
||||
to/from screen/OpenGL coordinates or Projecting/Unprojecting from an MVP matrix. Quaternions are also supported.
|
||||
|
||||
The basic vectors and matrices are written with code generation, so looking directly at the source will probably be a bit confusing. I recommend looking at the Godoc
|
||||
instead, as all basic functions are documented.
|
||||
|
||||
This package is written in Column Major Order to make it easier with OpenGL. This means for uniform blocks you can use the default ordering, and when you call
|
||||
pass-in functions you can leave the "transpose" argument as false.
|
||||
|
||||
The package now contains variable sized vectors and matrices. Using these is discouraged. They exist for corner cases where you need "small" matrices that are still
|
||||
bigger than 4x4. An example may be a Jacobean used for inverse kinematics. Things like computer vision or general linear algebra are best left to packages
|
||||
more directly suited for that task -- OpenCV, BLAS, LAPACK, numpy, gonum (if you want to stay in Go), and so on.
|
||||
*/
|
||||
package mgl32
|
494
vendor/github.com/go-gl/mathgl/mgl32/matmn.go
generated
vendored
Normal file
494
vendor/github.com/go-gl/mathgl/mgl32/matmn.go
generated
vendored
Normal file
@@ -0,0 +1,494 @@
|
||||
// Copyright 2014 The go-gl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mgl32
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// An arbitrary mxn matrix backed by a slice of floats.
|
||||
//
|
||||
// This is emphatically not recommended for hardcore n-dimensional
|
||||
// linear algebra. For that purpose I recommend github.com/gonum/matrix or
|
||||
// well-tested C libraries such as BLAS or LAPACK.
|
||||
//
|
||||
// This is meant to complement future algorithms that may require matrices larger than
|
||||
// 4x4, but still relatively small (e.g. Jacobeans for inverse kinematics).
|
||||
//
|
||||
// It makes use of the same memory sync.Pool set that VecN does, with the same sizing rules.
|
||||
//
|
||||
// MatMN will always check if the receiver is nil on any method. Meaning MathMN(nil).Add(dst,m2)
|
||||
// should always work. Except for the Reshape function, the semantics of this is to "propogate" nils
|
||||
// forward, so if an invalid operation occurs in a long chain of matrix operations, the overall result will be nil.
|
||||
type MatMxN struct {
|
||||
m, n int
|
||||
dat []float32
|
||||
}
|
||||
|
||||
// Creates a matrix backed by a new slice of size m*n
|
||||
func NewMatrix(m, n int) (mat *MatMxN) {
|
||||
if shouldPool {
|
||||
return &MatMxN{m: m, n: n, dat: grabFromPool(m * n)}
|
||||
} else {
|
||||
return &MatMxN{m: m, n: n, dat: make([]float32, m*n)}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a matrix with data specified by the data in src
|
||||
//
|
||||
// For instance, to create a 3x3 MatMN from a Mat3
|
||||
//
|
||||
// m1 := mgl32.Rotate3DX(3.14159)
|
||||
// mat := mgl32.NewBackedMatrix(m1[:],3,3)
|
||||
//
|
||||
// will create an MN matrix matching the data in the original
|
||||
// rotation matrix. This matrix is NOT backed by the initial slice;
|
||||
// it's a copy of the data
|
||||
//
|
||||
// If m*n > cap(src), this function will panic.
|
||||
func NewMatrixFromData(src []float32, m, n int) *MatMxN {
|
||||
var internal []float32
|
||||
if shouldPool {
|
||||
internal = grabFromPool(m * n)
|
||||
} else {
|
||||
internal = make([]float32, m*n)
|
||||
}
|
||||
copy(internal, src[:m*n])
|
||||
|
||||
return &MatMxN{m: m, n: n, dat: internal}
|
||||
}
|
||||
|
||||
// Copies src into dst. This Reshapes dst
|
||||
// to the same size as src.
|
||||
//
|
||||
// If dst or src is nil, this is a no-op
|
||||
func CopyMatMN(dst, src *MatMxN) {
|
||||
if dst == nil || src == nil {
|
||||
return
|
||||
}
|
||||
dst.Reshape(src.m, src.n)
|
||||
copy(dst.dat, src.dat)
|
||||
}
|
||||
|
||||
// Stores the NxN identity matrix in dst, reallocating as necessary.
|
||||
func IdentN(dst *MatMxN, n int) *MatMxN {
|
||||
dst = dst.Reshape(n, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
for j := 0; j < n; j++ {
|
||||
if i == j {
|
||||
dst.Set(i, j, 1)
|
||||
} else {
|
||||
dst.Set(i, j, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Creates an NxN diagonal matrix seeded by the diagonal vector
|
||||
// diag. Meaning: for all entries, where i==j, dst.At(i,j) = diag[i]. Otherwise
|
||||
// dst.At(i,j) = 0
|
||||
//
|
||||
// This reshapes dst to the correct size, returning/grabbing from the memory pool as necessary.
|
||||
func DiagN(dst *MatMxN, diag *VecN) *MatMxN {
|
||||
dst = dst.Reshape(len(diag.vec), len(diag.vec))
|
||||
n := len(diag.vec)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
for j := 0; j < n; j++ {
|
||||
if i == j {
|
||||
dst.Set(i, j, diag.vec[i])
|
||||
} else {
|
||||
dst.Set(i, j, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Reshapes the matrix to m by n and zeroes out all
|
||||
// elements.
|
||||
func (mat *MatMxN) Zero(m, n int) {
|
||||
if mat == nil {
|
||||
return
|
||||
}
|
||||
|
||||
mat.Reshape(m, n)
|
||||
for i := range mat.dat {
|
||||
mat.dat[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the underlying matrix slice to the memory pool
|
||||
func (mat *MatMxN) destroy() {
|
||||
if mat == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if shouldPool && mat.dat != nil {
|
||||
returnToPool(mat.dat)
|
||||
}
|
||||
mat.m, mat.n = 0, 0
|
||||
mat.dat = nil
|
||||
}
|
||||
|
||||
// Reshapes the matrix to the desired dimensions.
|
||||
// If the overall size of the new matrix (m*n) is bigger
|
||||
// than the current size, the underlying slice will
|
||||
// be grown, sending the current slice to the memory pool
|
||||
// and grabbing a bigger one if necessary
|
||||
//
|
||||
// If the caller is a nil pointer, the return value will be a new
|
||||
// matrix, as if NewMatrix(m,n) had been called. Otherwise it's
|
||||
// simply the caller.
|
||||
func (mat *MatMxN) Reshape(m, n int) *MatMxN {
|
||||
if mat == nil {
|
||||
return NewMatrix(m, n)
|
||||
}
|
||||
|
||||
if m*n <= cap(mat.dat) {
|
||||
if mat.dat != nil {
|
||||
mat.dat = mat.dat[:m*n]
|
||||
} else {
|
||||
mat.dat = []float32{}
|
||||
}
|
||||
mat.m, mat.n = m, n
|
||||
return mat
|
||||
}
|
||||
|
||||
if shouldPool && mat.dat != nil {
|
||||
returnToPool(mat.dat)
|
||||
}
|
||||
(*mat) = (*NewMatrix(m, n))
|
||||
|
||||
return mat
|
||||
}
|
||||
|
||||
// Infers an MxN matrix from a constant matrix from this package. For instance,
|
||||
// a Mat2x3 inferred with this function will work just like NewMatrixFromData(m[:],2,3)
|
||||
// where m is the Mat2x3. This uses a type switch.
|
||||
//
|
||||
// I personally recommend using NewMatrixFromData, because it avoids a potentially costly type switch.
|
||||
// However, this is also more robust and less error prone if you change the size of your matrix somewhere.
|
||||
//
|
||||
// If the value passed in is not recognized, it returns an InferMatrixError.
|
||||
func (mat *MatMxN) InferMatrix(m interface{}) (*MatMxN, error) {
|
||||
switch raw := m.(type) {
|
||||
case Mat2:
|
||||
return NewMatrixFromData(raw[:], 2, 2), nil
|
||||
case Mat2x3:
|
||||
return NewMatrixFromData(raw[:], 2, 3), nil
|
||||
case Mat2x4:
|
||||
return NewMatrixFromData(raw[:], 2, 4), nil
|
||||
case Mat3:
|
||||
return NewMatrixFromData(raw[:], 3, 3), nil
|
||||
case Mat3x2:
|
||||
return NewMatrixFromData(raw[:], 3, 2), nil
|
||||
case Mat3x4:
|
||||
return NewMatrixFromData(raw[:], 3, 4), nil
|
||||
case Mat4:
|
||||
return NewMatrixFromData(raw[:], 4, 4), nil
|
||||
case Mat4x2:
|
||||
return NewMatrixFromData(raw[:], 4, 2), nil
|
||||
case Mat4x3:
|
||||
return NewMatrixFromData(raw[:], 4, 3), nil
|
||||
default:
|
||||
return nil, InferMatrixError{}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the trace of a square matrix (sum of all diagonal elements). If the matrix
|
||||
// is nil, or not square, the result will be NaN.
|
||||
func (mat *MatMxN) Trace() float32 {
|
||||
if mat == nil || mat.m != mat.n {
|
||||
return float32(math.NaN())
|
||||
}
|
||||
|
||||
var out float32
|
||||
for i := 0; i < mat.m; i++ {
|
||||
out += mat.At(i, i)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// Takes the transpose of mat and puts it in dst.
|
||||
//
|
||||
// If dst is not of the correct dimensions, it will be Reshaped,
|
||||
// if dst and mat are the same, a temporary matrix of the correct size will
|
||||
// be allocated; these resources will be released via the memory pool.
|
||||
//
|
||||
// This should be improved in the future.
|
||||
func (mat *MatMxN) Transpose(dst *MatMxN) (t *MatMxN) {
|
||||
if mat == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if dst == mat {
|
||||
dst = NewMatrix(mat.n, mat.m)
|
||||
|
||||
// Copy data to correct matrix,
|
||||
// delete temporary buffer,
|
||||
// and set the return value to the
|
||||
// correct one
|
||||
defer func() {
|
||||
copy(mat.dat, dst.dat)
|
||||
|
||||
mat.m, mat.n = mat.n, mat.m
|
||||
|
||||
dst.destroy()
|
||||
t = mat
|
||||
}()
|
||||
|
||||
return mat
|
||||
} else {
|
||||
dst = dst.Reshape(mat.n, mat.m)
|
||||
}
|
||||
|
||||
for r := 0; r < mat.m; r++ {
|
||||
for c := 0; c < mat.n; c++ {
|
||||
dst.dat[r*dst.m+c] = mat.dat[c*mat.m+r]
|
||||
}
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Returns the raw slice backing this matrix
|
||||
func (mat *MatMxN) Raw() []float32 {
|
||||
if mat == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return mat.dat
|
||||
}
|
||||
|
||||
// Returns the number of rows in this matrix
|
||||
func (mat *MatMxN) NumRows() int {
|
||||
return mat.m
|
||||
}
|
||||
|
||||
// Returns the number of columns in this matrix
|
||||
func (mat *MatMxN) NumCols() int {
|
||||
return mat.n
|
||||
}
|
||||
|
||||
// Returns the number of rows and columns in this matrix
|
||||
// as a single operation
|
||||
func (mat *MatMxN) NumRowCols() (rows, cols int) {
|
||||
return mat.m, mat.n
|
||||
}
|
||||
|
||||
// Returns the element at the given row and column.
|
||||
// This is garbage in/garbage out and does no bounds
|
||||
// checking. If the computation happens to lead to an invalid
|
||||
// element, it will be returned; or it may panic.
|
||||
func (mat *MatMxN) At(row, col int) float32 {
|
||||
return mat.dat[col*mat.m+row]
|
||||
}
|
||||
|
||||
// Sets the element at the given row and column.
|
||||
// This is garbage in/garbage out and does no bounds
|
||||
// checking. If the computation happens to lead to an invalid
|
||||
// element, it will be set; or it may panic.
|
||||
func (mat *MatMxN) Set(row, col int, val float32) {
|
||||
mat.dat[col*mat.m+row] = val
|
||||
}
|
||||
|
||||
func (mat *MatMxN) Add(dst *MatMxN, addend *MatMxN) *MatMxN {
|
||||
if mat == nil || addend == nil || mat.m != addend.m || mat.n != addend.n {
|
||||
return nil
|
||||
}
|
||||
|
||||
dst = dst.Reshape(mat.m, mat.n)
|
||||
|
||||
// No need to care about rows and columns
|
||||
// since it's element-wise anyway
|
||||
for i, el := range mat.dat {
|
||||
dst.dat[i] = el + addend.dat[i]
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
func (mat *MatMxN) Sub(dst *MatMxN, subtrahend *MatMxN) *MatMxN {
|
||||
if mat == nil || subtrahend == nil || mat.m != subtrahend.m || mat.n != subtrahend.n {
|
||||
return nil
|
||||
}
|
||||
|
||||
dst = dst.Reshape(mat.m, mat.n)
|
||||
|
||||
// No need to care about rows and columns
|
||||
// since it's element-wise anyway
|
||||
for i, el := range mat.dat {
|
||||
dst.dat[i] = el - subtrahend.dat[i]
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Performs matrix multiplication on MxN matrix mat and NxO matrix mul, storing the result in dst.
|
||||
// This returns dst, or nil if the operation is not able to be performed.
|
||||
//
|
||||
// If mat == dst, or mul == dst a temporary matrix will be used.
|
||||
//
|
||||
// This uses the naive algorithm (though on smaller matrices,
|
||||
// this can actually be faster; about len(mat)+len(mul) < ~100)
|
||||
func (mat *MatMxN) MulMxN(dst *MatMxN, mul *MatMxN) *MatMxN {
|
||||
if mat == nil || mul == nil || mat.n != mul.m {
|
||||
return nil
|
||||
}
|
||||
|
||||
if dst == mul {
|
||||
mul = NewMatrix(mul.m, mul.n)
|
||||
copy(mul.dat, dst.dat)
|
||||
|
||||
// If mat==dst==mul, we need to change
|
||||
// mat too or we have a bug
|
||||
if mat == dst {
|
||||
mat = mul
|
||||
}
|
||||
|
||||
defer mul.destroy()
|
||||
} else if dst == mat {
|
||||
mat = NewMatrix(mat.m, mat.n)
|
||||
copy(mat.dat, dst.dat)
|
||||
|
||||
defer mat.destroy()
|
||||
}
|
||||
|
||||
dst = dst.Reshape(mat.m, mul.n)
|
||||
for r1 := 0; r1 < mat.m; r1++ {
|
||||
for c2 := 0; c2 < mul.n; c2++ {
|
||||
|
||||
dst.dat[c2*mat.m+r1] = 0
|
||||
for i := 0; i < mat.n; i++ {
|
||||
dst.dat[c2*mat.m+r1] += mat.dat[i*mat.m+r1] * mul.dat[c2*mul.m+i]
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Performs a scalar multiplication between mat and some constant c,
|
||||
// storing the result in dst. Mat and dst can be equal. If dst is not the
|
||||
// correct size, a Reshape will occur.
|
||||
func (mat *MatMxN) Mul(dst *MatMxN, c float32) *MatMxN {
|
||||
if mat == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
dst = dst.Reshape(mat.m, mat.n)
|
||||
|
||||
for i, el := range mat.dat {
|
||||
dst.dat[i] = el * c
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Multiplies the matrix by a vector of size n. If mat or v is
|
||||
// nil, this returns nil. If the number of columns in mat does not match
|
||||
// the Size of v, this also returns nil.
|
||||
//
|
||||
// Dst will be resized if it's not big enough. If dst == v; a temporary
|
||||
// vector will be allocated and returned via the realloc callback when complete.
|
||||
func (mat *MatMxN) MulNx1(dst, v *VecN) *VecN {
|
||||
if mat == nil || v == nil || mat.n != len(v.vec) {
|
||||
return nil
|
||||
}
|
||||
if dst == v {
|
||||
v = NewVecN(len(v.vec))
|
||||
copy(v.vec, dst.vec)
|
||||
|
||||
defer v.destroy()
|
||||
}
|
||||
|
||||
dst = dst.Resize(mat.m)
|
||||
|
||||
for r := 0; r < mat.m; r++ {
|
||||
dst.vec[r] = 0
|
||||
|
||||
for c := 0; c < mat.n; c++ {
|
||||
dst.vec[r] += mat.At(r, c) * v.vec[c]
|
||||
}
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
func (mat *MatMxN) ApproxEqual(m2 *MatMxN) bool {
|
||||
if mat == m2 {
|
||||
return true
|
||||
}
|
||||
if mat.m != m2.m || mat.n != m2.n {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, el := range mat.dat {
|
||||
if !FloatEqual(el, m2.dat[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (mat *MatMxN) ApproxEqualThreshold(m2 *MatMxN, epsilon float32) bool {
|
||||
if mat == m2 {
|
||||
return true
|
||||
}
|
||||
if mat.m != m2.m || mat.n != m2.n {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, el := range mat.dat {
|
||||
if !FloatEqualThreshold(el, m2.dat[i], epsilon) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (mat *MatMxN) ApproxEqualFunc(m2 *MatMxN, comp func(float32, float32) bool) bool {
|
||||
if mat == m2 {
|
||||
return true
|
||||
}
|
||||
if mat.m != m2.m || mat.n != m2.n {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, el := range mat.dat {
|
||||
if !comp(el, m2.dat[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
type InferMatrixError struct{}
|
||||
|
||||
func (me InferMatrixError) Error() string {
|
||||
return "could not infer matrix. Make sure you're using a constant matrix such as Mat3 from within the same package (meaning: mgl32.MatMxN can't handle a mgl64.Mat2x3)."
|
||||
}
|
||||
|
||||
type RectangularMatrixError struct{}
|
||||
|
||||
func (mse RectangularMatrixError) Error() string {
|
||||
return "the matrix was the wrong shape, needed a square matrix."
|
||||
}
|
||||
|
||||
type NilMatrixError struct{}
|
||||
|
||||
func (me NilMatrixError) Error() string {
|
||||
return "the matrix is nil"
|
||||
}
|
2341
vendor/github.com/go-gl/mathgl/mgl32/matrix.go
generated
vendored
Normal file
2341
vendor/github.com/go-gl/mathgl/mgl32/matrix.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
370
vendor/github.com/go-gl/mathgl/mgl32/matrix.tmpl
generated
vendored
Normal file
370
vendor/github.com/go-gl/mathgl/mgl32/matrix.tmpl
generated
vendored
Normal file
@@ -0,0 +1,370 @@
|
||||
// Copyright 2014 The go-gl/mathgl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// <<.Comment>>
|
||||
// Edit <<.TemplateName>> and run "go generate" to make changes.
|
||||
|
||||
package mgl32
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"golang.org/x/image/math/f32"
|
||||
"text/tabwriter"
|
||||
)
|
||||
|
||||
type Mat2 [4]float32
|
||||
type Mat2x3 [6]float32
|
||||
type Mat2x4 [8]float32
|
||||
type Mat3x2 [6]float32
|
||||
type Mat3 f32.Mat3
|
||||
type Mat3x4 [12]float32
|
||||
type Mat4x2 [8]float32
|
||||
type Mat4x3 [12]float32
|
||||
type Mat4 f32.Mat4
|
||||
|
||||
func (m Mat2) Mat3() Mat3 {
|
||||
col0, col1 := m.Cols()
|
||||
return Mat3FromCols(
|
||||
col0.Vec3(0),
|
||||
col1.Vec3(0),
|
||||
Vec3{0, 0, 1},
|
||||
)
|
||||
}
|
||||
|
||||
func (m Mat2) Mat4() Mat4 {
|
||||
col0, col1 := m.Cols()
|
||||
return Mat4FromCols(
|
||||
col0.Vec4(0, 0),
|
||||
col1.Vec4(0, 0),
|
||||
Vec4{0, 0, 1, 0},
|
||||
Vec4{0, 0, 0, 1},
|
||||
)
|
||||
}
|
||||
|
||||
func (m Mat3) Mat2() Mat2 {
|
||||
col0, col1, _ := m.Cols()
|
||||
return Mat2FromCols(
|
||||
col0.Vec2(),
|
||||
col1.Vec2(),
|
||||
)
|
||||
}
|
||||
|
||||
func (m Mat3) Mat4() Mat4 {
|
||||
col0, col1, col2 := m.Cols()
|
||||
return Mat4FromCols(
|
||||
col0.Vec4(0),
|
||||
col1.Vec4(0),
|
||||
col2.Vec4(0),
|
||||
Vec4{0, 0, 0, 1},
|
||||
)
|
||||
}
|
||||
|
||||
func (m Mat4) Mat2() Mat2 {
|
||||
col0, col1, _, _ := m.Cols()
|
||||
return Mat2FromCols(
|
||||
col0.Vec2(),
|
||||
col1.Vec2(),
|
||||
)
|
||||
}
|
||||
|
||||
func (m Mat4) Mat3() Mat3 {
|
||||
col0, col1, col2, _ := m.Cols()
|
||||
return Mat3FromCols(
|
||||
col0.Vec3(),
|
||||
col1.Vec3(),
|
||||
col2.Vec3(),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
<</* Common functions for all matrices */>>
|
||||
<<range $m := enum 2 3 4>><<range $n := enum 2 3 4>>
|
||||
<<$type := typename $m $n>>
|
||||
|
||||
// Sets a Column within the Matrix, so it mutates the calling matrix.
|
||||
func (m *<<$type>>) SetCol(col int, v <<typename $m 1>>) {
|
||||
<<range $i := iter 0 $m>><<sep "," $i>>m[col*<<$m>>+<<$i>>]<<end>> = <<repeat $m "v[%d]" ",">>
|
||||
}
|
||||
|
||||
// Sets a Row within the Matrix, so it mutates the calling matrix.
|
||||
func (m *<<$type>>) SetRow(row int, v <<typename $n 1>>) {
|
||||
<<range $i := iter 0 $n>><<sep "," $i>>m[row+<<mul $m $i>>]<<end>> = <<repeat $n "v[%d]" ",">>
|
||||
}
|
||||
|
||||
<<if eq $m $n>>
|
||||
// Diag is a basic operation on a square matrix that simply
|
||||
// returns main diagonal (meaning all elements such that row==col).
|
||||
func (m <<$type>>) Diag() <<typename $m 1>> {
|
||||
return <<typename $m 1>>{<<range $i := iter 0 $m>>m[<<mul $i $m | add $i>>],<<end>>}
|
||||
}
|
||||
<<end>>
|
||||
|
||||
<<if eq $m $n>>
|
||||
// Ident<<$m>> returns the <<$m>>x<<$n>> identity matrix.
|
||||
// The identity matrix is a square matrix with the value 1 on its
|
||||
// diagonals. The characteristic property of the identity matrix is that
|
||||
// any matrix multiplied by it is itself. (MI = M; IN = N)
|
||||
func Ident<<$m>>() <<$type>> {
|
||||
return <<$type>>{<<range $i := matiter $m $n>><<if eq $i.M $i.N>>1<<else>>0<<end>>,<<end>>}
|
||||
}
|
||||
<<end>>
|
||||
|
||||
<<if eq $m $n>>
|
||||
// Diag<<$m>> creates a diagonal matrix from the entries of the input vector.
|
||||
// That is, for each pointer for row==col, vector[row] is the entry. Otherwise it's 0.
|
||||
//
|
||||
// Another way to think about it is that the identity is this function where the every vector element is 1.
|
||||
func Diag<<$m>>(v <<typename $m 1>>) <<$type>> {
|
||||
var m <<$type>>
|
||||
<<range $i := iter 0 $m>><<sep "," $i>>m[<<mul $i $m | add $i>>]<<end>> = <<repeat $m "v[%d]" ",">>
|
||||
return m
|
||||
}
|
||||
<<end>>
|
||||
|
||||
// <<$type>>FromRows builds a new matrix from row vectors.
|
||||
// The resulting matrix will still be in column major order, but this can be
|
||||
// good for hand-building matrices.
|
||||
|
||||
func <<$type>>FromRows(<<range $i := iter 0 $m>><<sep "," $i>>row<<$i>><<end>> <<typename $n 1>>) <<$type>> {
|
||||
return <<$type>>{<<range $i := matiter $m $n>>row<<$i.M>>[<<$i.N>>],<<end>>}
|
||||
}
|
||||
|
||||
// <<$type>>FromCols builds a new matrix from column vectors.
|
||||
func <<$type>>FromCols(<<repeat $n "col%d" ",">> <<typename $m 1>>) <<$type>> {
|
||||
return <<$type>>{<<range $i := matiter $m $n>>col<<$i.N>>[<<$i.M>>], <<end>>}
|
||||
}
|
||||
|
||||
// Add performs an element-wise addition of two matrices, this is
|
||||
// equivalent to iterating over every element of m1 and adding the corresponding value of m2.
|
||||
func (m1 <<$type>>) Add(m2 <<$type>>) <<$type>> {
|
||||
return <<$type>>{<< range $i := matiter $m $n>>m1[<<$i>>] + m2[<<$i>>], <<end>>}
|
||||
}
|
||||
|
||||
// Sub performs an element-wise subtraction of two matrices, this is
|
||||
// equivalent to iterating over every element of m1 and subtracting the corresponding value of m2.
|
||||
func (m1 <<$type>>) Sub(m2 <<$type>>) <<$type>> {
|
||||
return <<$type>>{<< range $i := matiter $m $n>>m1[<<$i>>] - m2[<<$i>>], <<end>>}
|
||||
}
|
||||
|
||||
// Mul performs a scalar multiplcation of the matrix. This is equivalent to iterating
|
||||
// over every element of the matrix and multiply it by c.
|
||||
func (m1 <<$type>>) Mul(c float32) <<$type>> {
|
||||
return <<$type>>{<< range $i := matiter $m $n>>m1[<<$i>>] * c, <<end>>}
|
||||
}
|
||||
|
||||
<<range $o := enum 1 2 3 4>>
|
||||
// Mul<<$n>><<if ne $n $o>>x<<$o>><<end>> performs a "matrix product" between this matrix
|
||||
// and another of the given dimension. For any two matrices of dimensionality
|
||||
// MxN and NxO, the result will be MxO. For instance, Mat4 multiplied using
|
||||
// Mul4x2 will result in a Mat4x2.
|
||||
func (m1 <<$type>>) Mul<<$n>><<if ne $n $o>>x<<$o>><<end>>(m2 <<typename $n $o>>) <<typename $m $o>> {
|
||||
return <<typename $m $o>>{<<range $i := matiter $m $o>>
|
||||
<<range $k := iter 0 $n>><<sep "+" $k>>m1[<<mul $k $m | add $i.M>>]*m2[<<mul $i.N $n| add $k>>]<<end>>,<<end>>
|
||||
}
|
||||
}
|
||||
<<end>>
|
||||
|
||||
// Transpose produces the transpose of this matrix. For any MxN matrix
|
||||
// the transpose is an NxM matrix with the rows swapped with the columns. For instance
|
||||
// the transpose of the Mat3x2 is a Mat2x3 like so:
|
||||
//
|
||||
// [[a b]] [[a c e]]
|
||||
// [[c d]] = [[b d f]]
|
||||
// [[e f]]
|
||||
func (m1 <<$type>>) Transpose() <<typename $n $m>> {
|
||||
return <<typename $n $m>>{<<range $i := matiter $n $m>>m1[<<mul $m $i.M | add $i.N>>], <<end>>}
|
||||
}
|
||||
|
||||
<<if eq $m $n>>
|
||||
// The determinant of a matrix is a measure of a square matrix's
|
||||
// singularity and invertability, among other things. In this library, the
|
||||
// determinant is hard coded based on pre-computed cofactor expansion, and uses
|
||||
// no loops. Of course, the addition and multiplication must still be done.
|
||||
func (m <<$type>>) Det() float32 {
|
||||
<<if eq $m 2 ->>
|
||||
return m[0]*m[3] - m[1]*m[2]
|
||||
<<else if eq $m 3 ->>
|
||||
return m[0]*m[4]*m[8] + m[3]*m[7]*m[2] + m[6]*m[1]*m[5] - m[6]*m[4]*m[2] - m[3]*m[1]*m[8] - m[0]*m[7]*m[5]
|
||||
<<else if eq $m 4 ->>
|
||||
return m[0]*m[5]*m[10]*m[15] - m[0]*m[5]*m[11]*m[14] - m[0]*m[6]*m[9]*m[15] + m[0]*m[6]*m[11]*m[13] + m[0]*m[7]*m[9]*m[14] - m[0]*m[7]*m[10]*m[13] - m[1]*m[4]*m[10]*m[15] + m[1]*m[4]*m[11]*m[14] + m[1]*m[6]*m[8]*m[15] - m[1]*m[6]*m[11]*m[12] - m[1]*m[7]*m[8]*m[14] + m[1]*m[7]*m[10]*m[12] + m[2]*m[4]*m[9]*m[15] - m[2]*m[4]*m[11]*m[13] - m[2]*m[5]*m[8]*m[15] + m[2]*m[5]*m[11]*m[12] + m[2]*m[7]*m[8]*m[13] - m[2]*m[7]*m[9]*m[12] - m[3]*m[4]*m[9]*m[14] + m[3]*m[4]*m[10]*m[13] + m[3]*m[5]*m[8]*m[14] - m[3]*m[5]*m[10]*m[12] - m[3]*m[6]*m[8]*m[13] + m[3]*m[6]*m[9]*m[12]
|
||||
<<end ->>
|
||||
}
|
||||
<<end>>
|
||||
|
||||
<<if eq $m $n>>
|
||||
// Inv computes the inverse of a square matrix. An inverse is a square matrix such that when multiplied by the
|
||||
// original, yields the identity.
|
||||
//
|
||||
// M_inv * M = M * M_inv = I
|
||||
//
|
||||
// In this library, the math is precomputed, and uses no loops, though the multiplications, additions, determinant calculation, and scaling
|
||||
// are still done. This can still be (relatively) expensive for a 4x4.
|
||||
//
|
||||
// This function checks the determinant to see if the matrix is invertible.
|
||||
// If the determinant is 0.0, this function returns the zero matrix. However, due to floating point errors, it is
|
||||
// entirely plausible to get a false positive or negative.
|
||||
// In the future, an alternate function may be written which takes in a pre-computed determinant.
|
||||
func (m <<$type>>) Inv() <<$type>> {
|
||||
det := m.Det()
|
||||
if FloatEqual(det, float32(0.0)) {
|
||||
return <<$type>>{}
|
||||
}
|
||||
<<if eq $m 2>>
|
||||
retMat := Mat2{m[3], -m[1], -m[2], m[0]}
|
||||
<<else if eq $m 3>>
|
||||
retMat := Mat3{
|
||||
m[4]*m[8] - m[5]*m[7],
|
||||
m[2]*m[7] - m[1]*m[8],
|
||||
m[1]*m[5] - m[2]*m[4],
|
||||
m[5]*m[6] - m[3]*m[8],
|
||||
m[0]*m[8] - m[2]*m[6],
|
||||
m[2]*m[3] - m[0]*m[5],
|
||||
m[3]*m[7] - m[4]*m[6],
|
||||
m[1]*m[6] - m[0]*m[7],
|
||||
m[0]*m[4] - m[1]*m[3],
|
||||
}
|
||||
<<else if eq $m 4>>
|
||||
retMat := Mat4{
|
||||
-m[7]*m[10]*m[13] + m[6]*m[11]*m[13] + m[7]*m[9]*m[14] - m[5]*m[11]*m[14] - m[6]*m[9]*m[15] + m[5]*m[10]*m[15],
|
||||
m[3]*m[10]*m[13] - m[2]*m[11]*m[13] - m[3]*m[9]*m[14] + m[1]*m[11]*m[14] + m[2]*m[9]*m[15] - m[1]*m[10]*m[15],
|
||||
-m[3]*m[6]*m[13] + m[2]*m[7]*m[13] + m[3]*m[5]*m[14] - m[1]*m[7]*m[14] - m[2]*m[5]*m[15] + m[1]*m[6]*m[15],
|
||||
m[3]*m[6]*m[9] - m[2]*m[7]*m[9] - m[3]*m[5]*m[10] + m[1]*m[7]*m[10] + m[2]*m[5]*m[11] - m[1]*m[6]*m[11],
|
||||
m[7]*m[10]*m[12] - m[6]*m[11]*m[12] - m[7]*m[8]*m[14] + m[4]*m[11]*m[14] + m[6]*m[8]*m[15] - m[4]*m[10]*m[15],
|
||||
-m[3]*m[10]*m[12] + m[2]*m[11]*m[12] + m[3]*m[8]*m[14] - m[0]*m[11]*m[14] - m[2]*m[8]*m[15] + m[0]*m[10]*m[15],
|
||||
m[3]*m[6]*m[12] - m[2]*m[7]*m[12] - m[3]*m[4]*m[14] + m[0]*m[7]*m[14] + m[2]*m[4]*m[15] - m[0]*m[6]*m[15],
|
||||
-m[3]*m[6]*m[8] + m[2]*m[7]*m[8] + m[3]*m[4]*m[10] - m[0]*m[7]*m[10] - m[2]*m[4]*m[11] + m[0]*m[6]*m[11],
|
||||
-m[7]*m[9]*m[12] + m[5]*m[11]*m[12] + m[7]*m[8]*m[13] - m[4]*m[11]*m[13] - m[5]*m[8]*m[15] + m[4]*m[9]*m[15],
|
||||
m[3]*m[9]*m[12] - m[1]*m[11]*m[12] - m[3]*m[8]*m[13] + m[0]*m[11]*m[13] + m[1]*m[8]*m[15] - m[0]*m[9]*m[15],
|
||||
-m[3]*m[5]*m[12] + m[1]*m[7]*m[12] + m[3]*m[4]*m[13] - m[0]*m[7]*m[13] - m[1]*m[4]*m[15] + m[0]*m[5]*m[15],
|
||||
m[3]*m[5]*m[8] - m[1]*m[7]*m[8] - m[3]*m[4]*m[9] + m[0]*m[7]*m[9] + m[1]*m[4]*m[11] - m[0]*m[5]*m[11],
|
||||
m[6]*m[9]*m[12] - m[5]*m[10]*m[12] - m[6]*m[8]*m[13] + m[4]*m[10]*m[13] + m[5]*m[8]*m[14] - m[4]*m[9]*m[14],
|
||||
-m[2]*m[9]*m[12] + m[1]*m[10]*m[12] + m[2]*m[8]*m[13] - m[0]*m[10]*m[13] - m[1]*m[8]*m[14] + m[0]*m[9]*m[14],
|
||||
m[2]*m[5]*m[12] - m[1]*m[6]*m[12] - m[2]*m[4]*m[13] + m[0]*m[6]*m[13] + m[1]*m[4]*m[14] - m[0]*m[5]*m[14],
|
||||
-m[2]*m[5]*m[8] + m[1]*m[6]*m[8] + m[2]*m[4]*m[9] - m[0]*m[6]*m[9] - m[1]*m[4]*m[10] + m[0]*m[5]*m[10],
|
||||
}
|
||||
<<end>>
|
||||
return retMat.Mul(1 / det)
|
||||
}
|
||||
<<end>>
|
||||
|
||||
// ApproxEqual performs an element-wise approximate equality test between two matrices,
|
||||
// as if FloatEqual had been used.
|
||||
func (m1 <<$type>>) ApproxEqual(m2 <<$type>>) bool {
|
||||
for i := range m1 {
|
||||
if !FloatEqual(m1[i], m2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ApproxEqualThreshold performs an element-wise approximate equality test between two matrices
|
||||
// with a given epsilon threshold, as if FloatEqualThreshold had been used.
|
||||
func (m1 <<$type>>) ApproxEqualThreshold(m2 <<$type>>, threshold float32) bool {
|
||||
for i := range m1 {
|
||||
if !FloatEqualThreshold(m1[i], m2[i], threshold) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ApproxEqualFunc performs an element-wise approximate equality test between two matrices
|
||||
// with a given equality functions, intended to be used with FloatEqualFunc; although and comparison
|
||||
// function may be used in practice.
|
||||
func (m1 <<$type>>) ApproxFuncEqual(m2 <<$type>>, eq func(float32, float32) bool) bool {
|
||||
for i := range m1 {
|
||||
if !eq(m1[i], m2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// At returns the matrix element at the given row and column.
|
||||
// This is equivalent to mat[col * numRow + row] where numRow is constant
|
||||
// (E.G. for a Mat3x2 it's equal to 3)
|
||||
//
|
||||
// This method is garbage-in garbage-out. For instance, on a Mat4 asking for
|
||||
// At(5,0) will work just like At(1,1). Or it may panic if it's out of bounds.
|
||||
func (m <<$type>>) At(row, col int) float32 {
|
||||
return m[col*<<$m>>+row]
|
||||
}
|
||||
|
||||
// Set sets the corresponding matrix element at the given row and column.
|
||||
// This has a pointer receiver because it mutates the matrix.
|
||||
//
|
||||
// This method is garbage-in garbage-out. For instance, on a Mat4 asking for
|
||||
// Set(5,0,val) will work just like Set(1,1,val). Or it may panic if it's out of bounds.
|
||||
func (m *<<$type>>) Set(row, col int, value float32) {
|
||||
m[col*<<$m>>+row] = value
|
||||
}
|
||||
|
||||
// Index returns the index of the given row and column, to be used with direct
|
||||
// access. E.G. Index(0,0) = 0.
|
||||
//
|
||||
// This is a garbage-in garbage-out method. For instance, on a Mat4 asking for the index of
|
||||
// (5,0) will work the same as asking for (1,1). Or it may give you a value that will cause
|
||||
// a panic if you try to access the array with it if it's truly out of bounds.
|
||||
func (m <<$type>>) Index(row, col int) int {
|
||||
return col*<<$m>> + row
|
||||
}
|
||||
|
||||
// Row returns a vector representing the corresponding row (starting at row 0).
|
||||
// This package makes no distinction between row and column vectors, so it
|
||||
// will be a normal VecM for a MxN matrix.
|
||||
func (m <<$type>>) Row(row int) <<typename $n 1>> {
|
||||
return <<typename $n 1>>{<<range $i := iter 0 $n>>m[row+<<mul $m $i>>],<<end>>}
|
||||
}
|
||||
|
||||
// Rows decomposes a matrix into its corresponding row vectors.
|
||||
// This is equivalent to calling mat.Row for each row.
|
||||
func (m <<$type>>) Rows() (<<repeat $m "row%d" ",">> <<typename $n 1>>) {
|
||||
return <<repeat $m "m.Row(%d)" ",">>
|
||||
}
|
||||
|
||||
// Col returns a vector representing the corresponding column (starting at col 0).
|
||||
// This package makes no distinction between row and column vectors, so it
|
||||
// will be a normal VecN for a MxN matrix.
|
||||
func (m <<$type>>) Col(col int) <<typename $m 1>> {
|
||||
return <<typename $m 1>>{<<range $i := iter 0 $m>>m[col*<<$m>>+<<$i>>],<<end>>}
|
||||
}
|
||||
|
||||
// Cols decomposes a matrix into its corresponding column vectors.
|
||||
// This is equivalent to calling mat.Col for each column.
|
||||
func (m <<$type>>) Cols() (<<repeat $n "col%d" ",">> <<typename $m 1>>) {
|
||||
return <<repeat $n "m.Col(%d)" ",">>
|
||||
}
|
||||
|
||||
<<if eq $m $n>>
|
||||
// Trace is a basic operation on a square matrix that simply
|
||||
// sums up all elements on the main diagonal (meaning all elements such that row==col).
|
||||
func (m <<$type>>) Trace() float32 {
|
||||
return <<range $i := iter 0 $m>><<sep "+" $i>> m[<<mul $i $m | add $i>>]<<end>>
|
||||
}
|
||||
<<end>>
|
||||
|
||||
// Abs returns the element-wise absolute value of this matrix
|
||||
func (m <<$type>>) Abs() <<$type>> {
|
||||
return <<$type>>{<<repeat (mul $m $n) "Abs(m[%d])" ",">>}
|
||||
}
|
||||
|
||||
// Pretty prints the matrix
|
||||
func (m <<$type>>) String() string {
|
||||
buf := new(bytes.Buffer)
|
||||
w := tabwriter.NewWriter(buf, 4, 4, 1, ' ', tabwriter.AlignRight)
|
||||
for i := 0; i < <<$m>>; i++ {
|
||||
for _, col := range m.Row(i) {
|
||||
fmt.Fprintf(w, "%f\t", col)
|
||||
}
|
||||
|
||||
fmt.Fprintln(w, "")
|
||||
}
|
||||
w.Flush()
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
<<end>><<end>> <</* range $m range $n */>>
|
121
vendor/github.com/go-gl/mathgl/mgl32/mempool.go
generated
vendored
Normal file
121
vendor/github.com/go-gl/mathgl/mgl32/mempool.go
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
// Copyright 2014 The go-gl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mgl32
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
slicePools []*sync.Pool
|
||||
listLock sync.RWMutex
|
||||
)
|
||||
|
||||
var shouldPool = true
|
||||
|
||||
func DisableMemoryPooling() {
|
||||
shouldPool = false
|
||||
}
|
||||
|
||||
// Returns the given memory pool. If the pool doesn't exist, it will
|
||||
// create all pools up to element i. The number "i" corresponds to "p"
|
||||
// in most other comments. That is, it's Ceil(log_2(whatever)). So i=0
|
||||
// means you'll get the pool for slices of size 1, i=1 for size 2, i=2 for size 4,
|
||||
// and so on.
|
||||
//
|
||||
// This is concurrency safe and uses an RWMutex to protect the list expansion.
|
||||
func getPool(i int) *sync.Pool {
|
||||
listLock.RLock()
|
||||
if i >= len(slicePools) {
|
||||
|
||||
// Promote to a write lock because we now
|
||||
// need to mutate the pool
|
||||
listLock.RUnlock()
|
||||
listLock.Lock()
|
||||
defer listLock.Unlock()
|
||||
|
||||
for n := i - len(slicePools); n >= 0; n-- {
|
||||
newFunc := genPoolNew(1 << uint(len(slicePools)))
|
||||
slicePools = append(slicePools, &sync.Pool{New: newFunc})
|
||||
}
|
||||
} else {
|
||||
defer listLock.RUnlock()
|
||||
}
|
||||
|
||||
return slicePools[i]
|
||||
}
|
||||
|
||||
func genPoolNew(i int) func() interface{} {
|
||||
return func() interface{} {
|
||||
return make([]float32, 0, i)
|
||||
}
|
||||
}
|
||||
|
||||
// Grabs a slice from the memory pool, such that its cap
|
||||
// is 2^p where p is Ceil(log_2(size)). It will be downsliced
|
||||
// such that the len is size.
|
||||
func grabFromPool(size int) []float32 {
|
||||
pool, exact := binLog(size)
|
||||
|
||||
// Tried to grab something of size
|
||||
// zero or less
|
||||
if pool == -1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If the log is not exact, we
|
||||
// need to "overallocate" so we have
|
||||
// log+1
|
||||
if !exact {
|
||||
pool++
|
||||
}
|
||||
|
||||
slice := getPool(pool).Get().([]float32)
|
||||
slice = slice[:size]
|
||||
return slice
|
||||
}
|
||||
|
||||
// Returns a slice to the appropriate pool. If the slice does not have a cap that's precisely
|
||||
// a power of 2, this will panic.
|
||||
func returnToPool(slice []float32) {
|
||||
if cap(slice) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
pool, exact := binLog(cap(slice))
|
||||
|
||||
if !exact {
|
||||
panic("attempt to pool slice with non-exact cap. If you're a user, please file an issue with github.com/go-gl/mathgl about this bug. This should never happen.")
|
||||
}
|
||||
|
||||
getPool(pool).Put(slice)
|
||||
}
|
||||
|
||||
// This returns the integer base 2 log of the value
|
||||
// and whether the log is exact or rounded down.
|
||||
//
|
||||
// This is only for positive integers.
|
||||
//
|
||||
// There are faster ways to do this, I'm open to suggestions. Most rely on knowing system endianness
|
||||
// which Go makes hard to do. I'm hesistant to use float conversions and the math package because of off-by-one errors.
|
||||
func binLog(val int) (int, bool) {
|
||||
if val <= 0 {
|
||||
return -1, false
|
||||
}
|
||||
|
||||
exact := true
|
||||
l := 0
|
||||
for ; val > 1; val = val >> 1 {
|
||||
// If the current lsb is 1 and the number
|
||||
// is not equal to 1, this is not an exact
|
||||
// log, but rather a rounding of it
|
||||
if val&1 != 0 {
|
||||
exact = false
|
||||
}
|
||||
l++
|
||||
}
|
||||
|
||||
return l, exact
|
||||
}
|
98
vendor/github.com/go-gl/mathgl/mgl32/project.go
generated
vendored
Normal file
98
vendor/github.com/go-gl/mathgl/mgl32/project.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright 2014 The go-gl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mgl32
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
)
|
||||
|
||||
func Ortho(left, right, bottom, top, near, far float32) Mat4 {
|
||||
rml, tmb, fmn := (right - left), (top - bottom), (far - near)
|
||||
|
||||
return Mat4{float32(2. / rml), 0, 0, 0, 0, float32(2. / tmb), 0, 0, 0, 0, float32(-2. / fmn), 0, float32(-(right + left) / rml), float32(-(top + bottom) / tmb), float32(-(far + near) / fmn), 1}
|
||||
}
|
||||
|
||||
// Equivalent to Ortho with the near and far planes being -1 and 1, respectively
|
||||
func Ortho2D(left, right, bottom, top float32) Mat4 {
|
||||
return Ortho(left, right, bottom, top, -1, 1)
|
||||
}
|
||||
|
||||
func Perspective(fovy, aspect, near, far float32) Mat4 {
|
||||
// fovy = (fovy * math.Pi) / 180.0 // convert from degrees to radians
|
||||
nmf, f := near-far, float32(1./math.Tan(float64(fovy)/2.0))
|
||||
|
||||
return Mat4{float32(f / aspect), 0, 0, 0, 0, float32(f), 0, 0, 0, 0, float32((near + far) / nmf), -1, 0, 0, float32((2. * far * near) / nmf), 0}
|
||||
}
|
||||
|
||||
func Frustum(left, right, bottom, top, near, far float32) Mat4 {
|
||||
rml, tmb, fmn := (right - left), (top - bottom), (far - near)
|
||||
A, B, C, D := (right+left)/rml, (top+bottom)/tmb, -(far+near)/fmn, -(2*far*near)/fmn
|
||||
|
||||
return Mat4{float32((2. * near) / rml), 0, 0, 0, 0, float32((2. * near) / tmb), 0, 0, float32(A), float32(B), float32(C), -1, 0, 0, float32(D), 0}
|
||||
}
|
||||
|
||||
func LookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ float32) Mat4 {
|
||||
return LookAtV(Vec3{eyeX, eyeY, eyeZ}, Vec3{centerX, centerY, centerZ}, Vec3{upX, upY, upZ})
|
||||
}
|
||||
|
||||
// LookAtV generates a transform matrix from world space into the specific eye space
|
||||
func LookAtV(eye, center, up Vec3) Mat4 {
|
||||
f := center.Sub(eye).Normalize()
|
||||
s := f.Cross(up.Normalize()).Normalize()
|
||||
u := s.Cross(f)
|
||||
|
||||
M := Mat4{
|
||||
s[0], u[0], -f[0], 0,
|
||||
s[1], u[1], -f[1], 0,
|
||||
s[2], u[2], -f[2], 0,
|
||||
0, 0, 0, 1,
|
||||
}
|
||||
|
||||
return M.Mul4(Translate3D(float32(-eye[0]), float32(-eye[1]), float32(-eye[2])))
|
||||
}
|
||||
|
||||
// Transform a set of coordinates from object space (in obj) to window coordinates (with depth)
|
||||
//
|
||||
// Window coordinates are continuous, not discrete (well, as continuous as an IEEE Floating Point can be), so you won't get exact pixel locations
|
||||
// without rounding or similar
|
||||
func Project(obj Vec3, modelview, projection Mat4, initialX, initialY, width, height int) (win Vec3) {
|
||||
obj4 := obj.Vec4(1)
|
||||
|
||||
vpp := projection.Mul4(modelview).Mul4x1(obj4)
|
||||
vpp = vpp.Mul(1 / vpp.W())
|
||||
win[0] = float32(initialX) + (float32(width)*(vpp[0]+1))/2
|
||||
win[1] = float32(initialY) + (float32(height)*(vpp[1]+1))/2
|
||||
win[2] = (vpp[2] + 1) / 2
|
||||
|
||||
return win
|
||||
}
|
||||
|
||||
// Transform a set of window coordinates to object space. If your MVP (projection.Mul(modelview) matrix is not invertible, this will return an error
|
||||
//
|
||||
// Note that the projection may not be perfect if you use strict pixel locations rather than the exact values given by Projectf.
|
||||
// (It's still unlikely to be perfect due to precision errors, but it will be closer)
|
||||
func UnProject(win Vec3, modelview, projection Mat4, initialX, initialY, width, height int) (obj Vec3, err error) {
|
||||
inv := projection.Mul4(modelview).Inv()
|
||||
var blank Mat4
|
||||
if inv == blank {
|
||||
return Vec3{}, errors.New("Could not find matrix inverse (projection times modelview is probably non-singular)")
|
||||
}
|
||||
|
||||
obj4 := inv.Mul4x1(Vec4{
|
||||
(2 * (win[0] - float32(initialX)) / float32(width)) - 1,
|
||||
(2 * (win[1] - float32(initialY)) / float32(height)) - 1,
|
||||
2*win[2] - 1,
|
||||
1.0,
|
||||
})
|
||||
obj = obj4.Vec3()
|
||||
|
||||
//if obj4[3] > MinValue {}
|
||||
obj[0] /= obj4[3]
|
||||
obj[1] /= obj4[3]
|
||||
obj[2] /= obj4[3]
|
||||
|
||||
return obj, nil
|
||||
}
|
458
vendor/github.com/go-gl/mathgl/mgl32/quat.go
generated
vendored
Normal file
458
vendor/github.com/go-gl/mathgl/mgl32/quat.go
generated
vendored
Normal file
@@ -0,0 +1,458 @@
|
||||
// Copyright 2014 The go-gl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mgl32
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// A rotation order is the order in which
|
||||
// rotations will be transformed for the purposes of AnglesToQuat
|
||||
type RotationOrder int
|
||||
|
||||
const (
|
||||
XYX RotationOrder = iota
|
||||
XYZ
|
||||
XZX
|
||||
XZY
|
||||
YXY
|
||||
YXZ
|
||||
YZY
|
||||
YZX
|
||||
ZYZ
|
||||
ZYX
|
||||
ZXZ
|
||||
ZXY
|
||||
)
|
||||
|
||||
// A Quaternion is an extension of the imaginary numbers; there's all sorts of
|
||||
// interesting theory behind it. In 3D graphics we mostly use it as a cheap way of
|
||||
// representing rotation since quaternions are cheaper to multiply by, and easier to
|
||||
// interpolate than matrices.
|
||||
//
|
||||
// A Quaternion has two parts: W, the so-called scalar component,
|
||||
// and "V", the vector component. The vector component is considered to
|
||||
// be the part in 3D space, while W (loosely interpreted) is its 4D coordinate.
|
||||
type Quat struct {
|
||||
W float32
|
||||
V Vec3
|
||||
}
|
||||
|
||||
// The quaternion identity: W=1; V=(0,0,0).
|
||||
//
|
||||
// As with all identities, multiplying any quaternion by this will yield the same
|
||||
// quaternion you started with.
|
||||
func QuatIdent() Quat {
|
||||
return Quat{1., Vec3{0, 0, 0}}
|
||||
}
|
||||
|
||||
// Creates an angle from an axis and an angle relative to that axis.
|
||||
//
|
||||
// This is cheaper than HomogRotate3D.
|
||||
func QuatRotate(angle float32, axis Vec3) Quat {
|
||||
// angle = (float32(math.Pi) * angle) / 180.0
|
||||
|
||||
c, s := float32(math.Cos(float64(angle/2))), float32(math.Sin(float64(angle/2)))
|
||||
|
||||
return Quat{c, axis.Mul(s)}
|
||||
}
|
||||
|
||||
// A convenient alias for q.V[0]
|
||||
func (q Quat) X() float32 {
|
||||
return q.V[0]
|
||||
}
|
||||
|
||||
// A convenient alias for q.V[1]
|
||||
func (q Quat) Y() float32 {
|
||||
return q.V[1]
|
||||
}
|
||||
|
||||
// A convenient alias for q.V[2]
|
||||
func (q Quat) Z() float32 {
|
||||
return q.V[2]
|
||||
}
|
||||
|
||||
// Adds two quaternions. It's no more complicated than
|
||||
// adding their W and V components.
|
||||
func (q1 Quat) Add(q2 Quat) Quat {
|
||||
return Quat{q1.W + q2.W, q1.V.Add(q2.V)}
|
||||
}
|
||||
|
||||
// Subtracts two quaternions. It's no more complicated than
|
||||
// subtracting their W and V components.
|
||||
func (q1 Quat) Sub(q2 Quat) Quat {
|
||||
return Quat{q1.W - q2.W, q1.V.Sub(q2.V)}
|
||||
}
|
||||
|
||||
// Multiplies two quaternions. This can be seen as a rotation. Note that
|
||||
// Multiplication is NOT commutative, meaning q1.Mul(q2) does not necessarily
|
||||
// equal q2.Mul(q1).
|
||||
func (q1 Quat) Mul(q2 Quat) Quat {
|
||||
return Quat{q1.W*q2.W - q1.V.Dot(q2.V), q1.V.Cross(q2.V).Add(q2.V.Mul(q1.W)).Add(q1.V.Mul(q2.W))}
|
||||
}
|
||||
|
||||
// Scales every element of the quaternion by some constant factor.
|
||||
func (q1 Quat) Scale(c float32) Quat {
|
||||
return Quat{q1.W * c, Vec3{q1.V[0] * c, q1.V[1] * c, q1.V[2] * c}}
|
||||
}
|
||||
|
||||
// Returns the conjugate of a quaternion. Equivalent to
|
||||
// Quat{q1.W, q1.V.Mul(-1)}
|
||||
func (q1 Quat) Conjugate() Quat {
|
||||
return Quat{q1.W, q1.V.Mul(-1)}
|
||||
}
|
||||
|
||||
// Returns the Length of the quaternion, also known as its Norm. This is the same thing as
|
||||
// the Len of a Vec4
|
||||
func (q1 Quat) Len() float32 {
|
||||
return float32(math.Sqrt(float64(q1.W*q1.W + q1.V[0]*q1.V[0] + q1.V[1]*q1.V[1] + q1.V[2]*q1.V[2])))
|
||||
}
|
||||
|
||||
// Norm() is an alias for Len() since both are very common terms.
|
||||
func (q1 Quat) Norm() float32 {
|
||||
return q1.Len()
|
||||
}
|
||||
|
||||
// Normalizes the quaternion, returning its versor (unit quaternion).
|
||||
//
|
||||
// This is the same as normalizing it as a Vec4.
|
||||
func (q1 Quat) Normalize() Quat {
|
||||
length := q1.Len()
|
||||
|
||||
if FloatEqual(1, length) {
|
||||
return q1
|
||||
}
|
||||
if length == 0 {
|
||||
return QuatIdent()
|
||||
}
|
||||
if length == InfPos {
|
||||
length = MaxValue
|
||||
}
|
||||
|
||||
return Quat{q1.W * 1 / length, q1.V.Mul(1 / length)}
|
||||
}
|
||||
|
||||
// The inverse of a quaternion. The inverse is equivalent
|
||||
// to the conjugate divided by the square of the length.
|
||||
//
|
||||
// This method computes the square norm by directly adding the sum
|
||||
// of the squares of all terms instead of actually squaring q1.Len(),
|
||||
// both for performance and precision.
|
||||
func (q1 Quat) Inverse() Quat {
|
||||
return q1.Conjugate().Scale(1 / q1.Dot(q1))
|
||||
}
|
||||
|
||||
// Rotates a vector by the rotation this quaternion represents.
|
||||
// This will result in a 3D vector. Strictly speaking, this is
|
||||
// equivalent to q1.v.q* where the "."" is quaternion multiplication and v is interpreted
|
||||
// as a quaternion with W 0 and V v. In code:
|
||||
// q1.Mul(Quat{0,v}).Mul(q1.Conjugate()), and
|
||||
// then retrieving the imaginary (vector) part.
|
||||
//
|
||||
// In practice, we hand-compute this in the general case and simplify
|
||||
// to save a few operations.
|
||||
func (q1 Quat) Rotate(v Vec3) Vec3 {
|
||||
cross := q1.V.Cross(v)
|
||||
// v + 2q_w * (q_v x v) + 2q_v x (q_v x v)
|
||||
return v.Add(cross.Mul(2 * q1.W)).Add(q1.V.Mul(2).Cross(cross))
|
||||
}
|
||||
|
||||
// Returns the homogeneous 3D rotation matrix corresponding to the quaternion.
|
||||
func (q1 Quat) Mat4() Mat4 {
|
||||
w, x, y, z := q1.W, q1.V[0], q1.V[1], q1.V[2]
|
||||
return Mat4{
|
||||
1 - 2*y*y - 2*z*z, 2*x*y + 2*w*z, 2*x*z - 2*w*y, 0,
|
||||
2*x*y - 2*w*z, 1 - 2*x*x - 2*z*z, 2*y*z + 2*w*x, 0,
|
||||
2*x*z + 2*w*y, 2*y*z - 2*w*x, 1 - 2*x*x - 2*y*y, 0,
|
||||
0, 0, 0, 1,
|
||||
}
|
||||
}
|
||||
|
||||
// The dot product between two quaternions, equivalent to if this was a Vec4
|
||||
func (q1 Quat) Dot(q2 Quat) float32 {
|
||||
return q1.W*q2.W + q1.V[0]*q2.V[0] + q1.V[1]*q2.V[1] + q1.V[2]*q2.V[2]
|
||||
}
|
||||
|
||||
// Returns whether the quaternions are approximately equal, as if
|
||||
// FloatEqual was called on each matching element
|
||||
func (q1 Quat) ApproxEqual(q2 Quat) bool {
|
||||
return FloatEqual(q1.W, q2.W) && q1.V.ApproxEqual(q2.V)
|
||||
}
|
||||
|
||||
// Returns whether the quaternions are approximately equal with a given tolerence, as if
|
||||
// FloatEqualThreshold was called on each matching element with the given epsilon
|
||||
func (q1 Quat) ApproxEqualThreshold(q2 Quat, epsilon float32) bool {
|
||||
return FloatEqualThreshold(q1.W, q2.W, epsilon) && q1.V.ApproxEqualThreshold(q2.V, epsilon)
|
||||
}
|
||||
|
||||
// Returns whether the quaternions are approximately equal using the given comparison function, as if
|
||||
// the function had been called on each individual element
|
||||
func (q1 Quat) ApproxEqualFunc(q2 Quat, f func(float32, float32) bool) bool {
|
||||
return f(q1.W, q2.W) && q1.V.ApproxFuncEqual(q2.V, f)
|
||||
}
|
||||
|
||||
// Returns whether the quaternions represents the same orientation
|
||||
//
|
||||
// Different values can represent the same orientation (q == -q) because quaternions avoid singularities
|
||||
// and discontinuities involved with rotation in 3 dimensions by adding extra dimensions
|
||||
func (q1 Quat) OrientationEqual(q2 Quat) bool {
|
||||
return q1.OrientationEqualThreshold(q2, Epsilon)
|
||||
}
|
||||
|
||||
// Returns whether the quaternions represents the same orientation with a given tolerence
|
||||
func (q1 Quat) OrientationEqualThreshold(q2 Quat, epsilon float32) bool {
|
||||
return Abs(q1.Normalize().Dot(q2.Normalize())) > 1-epsilon
|
||||
}
|
||||
|
||||
// Slerp is *S*pherical *L*inear Int*erp*olation, a method of interpolating
|
||||
// between two quaternions. This always takes the straightest path on the sphere between
|
||||
// the two quaternions, and maintains constant velocity.
|
||||
//
|
||||
// However, it's expensive and QuatSlerp(q1,q2) is not the same as QuatSlerp(q2,q1)
|
||||
func QuatSlerp(q1, q2 Quat, amount float32) Quat {
|
||||
q1, q2 = q1.Normalize(), q2.Normalize()
|
||||
dot := q1.Dot(q2)
|
||||
|
||||
// If the inputs are too close for comfort, linearly interpolate and normalize the result.
|
||||
if dot > 0.9995 {
|
||||
return QuatNlerp(q1, q2, amount)
|
||||
}
|
||||
|
||||
// This is here for precision errors, I'm perfectly aware that *technically* the dot is bound [-1,1], but since Acos will freak out if it's not (even if it's just a liiiiitle bit over due to normal error) we need to clamp it
|
||||
dot = Clamp(dot, -1, 1)
|
||||
|
||||
theta := float32(math.Acos(float64(dot))) * amount
|
||||
c, s := float32(math.Cos(float64(theta))), float32(math.Sin(float64(theta)))
|
||||
rel := q2.Sub(q1.Scale(dot)).Normalize()
|
||||
|
||||
return q1.Scale(c).Add(rel.Scale(s))
|
||||
}
|
||||
|
||||
// *L*inear Int*erp*olation between two Quaternions, cheap and simple.
|
||||
//
|
||||
// Not excessively useful, but uses can be found.
|
||||
func QuatLerp(q1, q2 Quat, amount float32) Quat {
|
||||
return q1.Add(q2.Sub(q1).Scale(amount))
|
||||
}
|
||||
|
||||
// *Normalized* *L*inear Int*erp*olation between two Quaternions. Cheaper than Slerp
|
||||
// and usually just as good. This is literally Lerp with Normalize() called on it.
|
||||
//
|
||||
// Unlike Slerp, constant velocity isn't maintained, but it's much faster and
|
||||
// Nlerp(q1,q2) and Nlerp(q2,q1) return the same path. You should probably
|
||||
// use this more often unless you're suffering from choppiness due to the
|
||||
// non-constant velocity problem.
|
||||
func QuatNlerp(q1, q2 Quat, amount float32) Quat {
|
||||
return QuatLerp(q1, q2, amount).Normalize()
|
||||
}
|
||||
|
||||
// Performs a rotation in the specified order. If the order is not
|
||||
// a valid RotationOrder, this function will panic
|
||||
//
|
||||
// The rotation "order" is more of an axis descriptor. For instance XZX would
|
||||
// tell the function to interpret angle1 as a rotation about the X axis, angle2 about
|
||||
// the Z axis, and angle3 about the X axis again.
|
||||
//
|
||||
// Based off the code for the Matlab function "angle2quat", though this implementation
|
||||
// only supports 3 single angles as opposed to multiple angles.
|
||||
func AnglesToQuat(angle1, angle2, angle3 float32, order RotationOrder) Quat {
|
||||
var s [3]float64
|
||||
var c [3]float64
|
||||
|
||||
s[0], c[0] = math.Sincos(float64(angle1 / 2))
|
||||
s[1], c[1] = math.Sincos(float64(angle2 / 2))
|
||||
s[2], c[2] = math.Sincos(float64(angle3 / 2))
|
||||
|
||||
ret := Quat{}
|
||||
switch order {
|
||||
case ZYX:
|
||||
ret.W = float32(c[0]*c[1]*c[2] + s[0]*s[1]*s[2])
|
||||
ret.V = Vec3{float32(c[0]*c[1]*s[2] - s[0]*s[1]*c[2]),
|
||||
float32(c[0]*s[1]*c[2] + s[0]*c[1]*s[2]),
|
||||
float32(s[0]*c[1]*c[2] - c[0]*s[1]*s[2]),
|
||||
}
|
||||
case ZYZ:
|
||||
ret.W = float32(c[0]*c[1]*c[2] - s[0]*c[1]*s[2])
|
||||
ret.V = Vec3{float32(c[0]*s[1]*s[2] - s[0]*s[1]*c[2]),
|
||||
float32(c[0]*s[1]*c[2] + s[0]*s[1]*s[2]),
|
||||
float32(s[0]*c[1]*c[2] + c[0]*c[1]*s[2]),
|
||||
}
|
||||
case ZXY:
|
||||
ret.W = float32(c[0]*c[1]*c[2] - s[0]*s[1]*s[2])
|
||||
ret.V = Vec3{float32(c[0]*s[1]*c[2] - s[0]*c[1]*s[2]),
|
||||
float32(c[0]*c[1]*s[2] + s[0]*s[1]*c[2]),
|
||||
float32(c[0]*s[1]*s[2] + s[0]*c[1]*c[2]),
|
||||
}
|
||||
case ZXZ:
|
||||
ret.W = float32(c[0]*c[1]*c[2] - s[0]*c[1]*s[2])
|
||||
ret.V = Vec3{float32(c[0]*s[1]*c[2] + s[0]*s[1]*s[2]),
|
||||
float32(s[0]*s[1]*c[2] - c[0]*s[1]*s[2]),
|
||||
float32(c[0]*c[1]*s[2] + s[0]*c[1]*c[2]),
|
||||
}
|
||||
case YXZ:
|
||||
ret.W = float32(c[0]*c[1]*c[2] + s[0]*s[1]*s[2])
|
||||
ret.V = Vec3{float32(c[0]*s[1]*c[2] + s[0]*c[1]*s[2]),
|
||||
float32(s[0]*c[1]*c[2] - c[0]*s[1]*s[2]),
|
||||
float32(c[0]*c[1]*s[2] - s[0]*s[1]*c[2]),
|
||||
}
|
||||
case YXY:
|
||||
ret.W = float32(c[0]*c[1]*c[2] - s[0]*c[1]*s[2])
|
||||
ret.V = Vec3{float32(c[0]*s[1]*c[2] + s[0]*s[1]*s[2]),
|
||||
float32(s[0]*c[1]*c[2] + c[0]*c[1]*s[2]),
|
||||
float32(c[0]*s[1]*s[2] - s[0]*s[1]*c[2]),
|
||||
}
|
||||
case YZX:
|
||||
ret.W = float32(c[0]*c[1]*c[2] - s[0]*s[1]*s[2])
|
||||
ret.V = Vec3{float32(c[0]*c[1]*s[2] + s[0]*s[1]*c[2]),
|
||||
float32(c[0]*s[1]*s[2] + s[0]*c[1]*c[2]),
|
||||
float32(c[0]*s[1]*c[2] - s[0]*c[1]*s[2]),
|
||||
}
|
||||
case YZY:
|
||||
ret.W = float32(c[0]*c[1]*c[2] - s[0]*c[1]*s[2])
|
||||
ret.V = Vec3{float32(s[0]*s[1]*c[2] - c[0]*s[1]*s[2]),
|
||||
float32(c[0]*c[1]*s[2] + s[0]*c[1]*c[2]),
|
||||
float32(c[0]*s[1]*c[2] + s[0]*s[1]*s[2]),
|
||||
}
|
||||
case XYZ:
|
||||
ret.W = float32(c[0]*c[1]*c[2] - s[0]*s[1]*s[2])
|
||||
ret.V = Vec3{float32(c[0]*s[1]*s[2] + s[0]*c[1]*c[2]),
|
||||
float32(c[0]*s[1]*c[2] - s[0]*c[1]*s[2]),
|
||||
float32(c[0]*c[1]*s[2] + s[0]*s[1]*c[2]),
|
||||
}
|
||||
case XYX:
|
||||
ret.W = float32(c[0]*c[1]*c[2] - s[0]*c[1]*s[2])
|
||||
ret.V = Vec3{float32(c[0]*c[1]*s[2] + s[0]*c[1]*c[2]),
|
||||
float32(c[0]*s[1]*c[2] + s[0]*s[1]*s[2]),
|
||||
float32(s[0]*s[1]*c[2] - c[0]*s[1]*s[2]),
|
||||
}
|
||||
case XZY:
|
||||
ret.W = float32(c[0]*c[1]*c[2] + s[0]*s[1]*s[2])
|
||||
ret.V = Vec3{float32(s[0]*c[1]*c[2] - c[0]*s[1]*s[2]),
|
||||
float32(c[0]*c[1]*s[2] - s[0]*s[1]*c[2]),
|
||||
float32(c[0]*s[1]*c[2] + s[0]*c[1]*s[2]),
|
||||
}
|
||||
case XZX:
|
||||
ret.W = float32(c[0]*c[1]*c[2] - s[0]*c[1]*s[2])
|
||||
ret.V = Vec3{float32(c[0]*c[1]*s[2] + s[0]*c[1]*c[2]),
|
||||
float32(c[0]*s[1]*s[2] - s[0]*s[1]*c[2]),
|
||||
float32(c[0]*s[1]*c[2] + s[0]*s[1]*s[2]),
|
||||
}
|
||||
default:
|
||||
panic("Unsupported rotation order")
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Mat4ToQuat converts a pure rotation matrix into a quaternion
|
||||
func Mat4ToQuat(m Mat4) Quat {
|
||||
// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
|
||||
|
||||
if tr := m[0] + m[5] + m[10]; tr > 0 {
|
||||
s := float32(0.5 / math.Sqrt(float64(tr+1.0)))
|
||||
return Quat{
|
||||
0.25 / s,
|
||||
Vec3{
|
||||
(m[6] - m[9]) * s,
|
||||
(m[8] - m[2]) * s,
|
||||
(m[1] - m[4]) * s,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (m[0] > m[5]) && (m[0] > m[10]) {
|
||||
s := float32(2.0 * math.Sqrt(float64(1.0+m[0]-m[5]-m[10])))
|
||||
return Quat{
|
||||
(m[6] - m[9]) / s,
|
||||
Vec3{
|
||||
0.25 * s,
|
||||
(m[4] + m[1]) / s,
|
||||
(m[8] + m[2]) / s,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if m[5] > m[10] {
|
||||
s := float32(2.0 * math.Sqrt(float64(1.0+m[5]-m[0]-m[10])))
|
||||
return Quat{
|
||||
(m[8] - m[2]) / s,
|
||||
Vec3{
|
||||
(m[4] + m[1]) / s,
|
||||
0.25 * s,
|
||||
(m[9] + m[6]) / s,
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
s := float32(2.0 * math.Sqrt(float64(1.0+m[10]-m[0]-m[5])))
|
||||
return Quat{
|
||||
(m[1] - m[4]) / s,
|
||||
Vec3{
|
||||
(m[8] + m[2]) / s,
|
||||
(m[9] + m[6]) / s,
|
||||
0.25 * s,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// QuatLookAtV creates a rotation from an eye vector to a center vector
|
||||
//
|
||||
// It assumes the front of the rotated object at Z- and up at Y+
|
||||
func QuatLookAtV(eye, center, up Vec3) Quat {
|
||||
// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#I_need_an_equivalent_of_gluLookAt__How_do_I_orient_an_object_towards_a_point__
|
||||
// https://bitbucket.org/sinbad/ogre/src/d2ef494c4a2f5d6e2f0f17d3bfb9fd936d5423bb/OgreMain/src/OgreCamera.cpp?at=default#cl-161
|
||||
|
||||
direction := center.Sub(eye).Normalize()
|
||||
|
||||
// Find the rotation between the front of the object (that we assume towards Z-,
|
||||
// but this depends on your model) and the desired direction
|
||||
rotDir := QuatBetweenVectors(Vec3{0, 0, -1}, direction)
|
||||
|
||||
// Recompute up so that it's perpendicular to the direction
|
||||
// You can skip that part if you really want to force up
|
||||
//right := direction.Cross(up)
|
||||
//up = right.Cross(direction)
|
||||
|
||||
// Because of the 1rst rotation, the up is probably completely screwed up.
|
||||
// Find the rotation between the "up" of the rotated object, and the desired up
|
||||
upCur := rotDir.Rotate(Vec3{0, 1, 0})
|
||||
rotUp := QuatBetweenVectors(upCur, up)
|
||||
|
||||
rotTarget := rotUp.Mul(rotDir) // remember, in reverse order.
|
||||
return rotTarget.Inverse() // camera rotation should be inversed!
|
||||
}
|
||||
|
||||
// QuatBetweenVectors calculates the rotation between two vectors
|
||||
func QuatBetweenVectors(start, dest Vec3) Quat {
|
||||
// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-17-quaternions/#I_need_an_equivalent_of_gluLookAt__How_do_I_orient_an_object_towards_a_point__
|
||||
// https://github.com/g-truc/glm/blob/0.9.5/glm/gtx/quaternion.inl#L225
|
||||
// https://bitbucket.org/sinbad/ogre/src/d2ef494c4a2f5d6e2f0f17d3bfb9fd936d5423bb/OgreMain/include/OgreVector3.h?at=default#cl-654
|
||||
|
||||
start = start.Normalize()
|
||||
dest = dest.Normalize()
|
||||
epsilon := float32(0.001)
|
||||
|
||||
cosTheta := start.Dot(dest)
|
||||
if cosTheta < -1.0+epsilon {
|
||||
// special case when vectors in opposite directions:
|
||||
// there is no "ideal" rotation axis
|
||||
// So guess one; any will do as long as it's perpendicular to start
|
||||
axis := Vec3{1, 0, 0}.Cross(start)
|
||||
if axis.Dot(axis) < epsilon {
|
||||
// bad luck, they were parallel, try again!
|
||||
axis = Vec3{0, 1, 0}.Cross(start)
|
||||
}
|
||||
|
||||
return QuatRotate(math.Pi, axis.Normalize())
|
||||
}
|
||||
|
||||
axis := start.Cross(dest)
|
||||
s := float32(math.Sqrt(float64(1.0+cosTheta) * 2.0))
|
||||
|
||||
return Quat{
|
||||
s * 0.5,
|
||||
axis.Mul(1.0 / s),
|
||||
}
|
||||
}
|
306
vendor/github.com/go-gl/mathgl/mgl32/shapes.go
generated
vendored
Normal file
306
vendor/github.com/go-gl/mathgl/mgl32/shapes.go
generated
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
// Copyright 2014 The go-gl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mgl32
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
)
|
||||
|
||||
// Generates a circle centered at (0,0) with a given radius.
|
||||
// The radii are assumed to be in GL's coordinate sizing.
|
||||
//
|
||||
// Technically this draws an ellipse with two axes that match with the X and Y axes, the reason it has a radiusX and radiusY is because GL's coordinate system
|
||||
// is proportional to screen width and screen height. So if you have a non-square viewport, a single radius will appear
|
||||
// to "squash" the circle in one direction (usually the Y direction), so the X and Y radius allow for a circle to be made.
|
||||
// A good way to get the correct radii is with mathgl.ScreenToGLCoords(radius, radius, screenWidth, screenHeight) which will get you the correct
|
||||
// proportional GL coords.
|
||||
//
|
||||
// The numSlices argument specifies how many triangles you want your circle divided into, setting this
|
||||
// number to too low a value may cause problem (and too high will cause it to take a lot of memory and time to compute
|
||||
// without much gain in resolution).
|
||||
//
|
||||
// This uses discrete triangles, not a triangle fan
|
||||
func Circle(radiusX, radiusY float32, numSlices int) []Vec2 {
|
||||
twoPi := float32(2.0 * math.Pi)
|
||||
|
||||
circlePoints := make([]Vec2, 0, numSlices*3)
|
||||
center := Vec2{0.0, 0.0}
|
||||
previous := Vec2{radiusX, 0.0}
|
||||
|
||||
for theta := twoPi / float32(numSlices); !FloatEqual(theta, twoPi); theta = Clamp(theta+twoPi/float32(numSlices), 0.0, twoPi) {
|
||||
sin, cos := math.Sincos(float64(theta))
|
||||
curr := Vec2{float32(cos) * radiusX, float32(sin) * radiusY}
|
||||
|
||||
circlePoints = append(circlePoints, center, previous, curr)
|
||||
previous = curr
|
||||
}
|
||||
|
||||
// Now add the final point at theta=2pi
|
||||
circlePoints = append(circlePoints, center, previous, Vec2{radiusX, 0.0})
|
||||
return circlePoints
|
||||
}
|
||||
|
||||
// Generates a 2-triangle rectangle for use with GL_TRIANGLES. The width and height should use GL's proportions (that is, where a width of 1.0
|
||||
// is equivalent to half of the width of the render target); however, the y-coordinates grow downwards, not upwards. That is, it
|
||||
// assumes you want the origin of the rectangle with the top-left corner at (0.0,0.0).
|
||||
//
|
||||
// Keep in mind that GL's coordinate system is proportional, so width=height will not result in a square unless your viewport is square.
|
||||
// If you want to maintain proportionality regardless of screen size, use the results of w,h := ScreenToGLCoordsf(absoluteWidth, absoluteHeight, screenWidth, screenHeight);
|
||||
// w,h=w+1,h-1 in the call to this function. (The w+1,h-1 step maps the coordinates to start at 0.0 rather than -1.0)
|
||||
func Rect(width, height float32) []Vec2 {
|
||||
return []Vec2{
|
||||
{0.0, 0.0},
|
||||
{0.0, -height},
|
||||
{width, -height},
|
||||
|
||||
{0.0, 0.0},
|
||||
{width, -height},
|
||||
{width, 0.0},
|
||||
}
|
||||
}
|
||||
|
||||
func QuadraticBezierCurve2D(t float32, cPoint1, cPoint2, cPoint3 Vec2) Vec2 {
|
||||
if t < 0.0 || t > 1.0 {
|
||||
panic("Can't interpolate on bezier curve with t out of range [0.0,1.0]")
|
||||
}
|
||||
|
||||
return cPoint1.Mul((1.0 - t) * (1.0 - t)).Add(cPoint2.Mul(2 * (1 - t) * t)).Add(cPoint3.Mul(t * t))
|
||||
}
|
||||
|
||||
func QuadraticBezierCurve3D(t float32, cPoint1, cPoint2, cPoint3 Vec3) Vec3 {
|
||||
if t < 0.0 || t > 1.0 {
|
||||
panic("Can't interpolate on bezier curve with t out of range [0.0,1.0]")
|
||||
}
|
||||
|
||||
return cPoint1.Mul((1.0 - t) * (1.0 - t)).Add(cPoint2.Mul(2 * (1 - t) * t)).Add(cPoint3.Mul(t * t))
|
||||
}
|
||||
|
||||
func CubicBezierCurve2D(t float32, cPoint1, cPoint2, cPoint3, cPoint4 Vec2) Vec2 {
|
||||
if t < 0.0 || t > 1.0 {
|
||||
panic("Can't interpolate on bezier curve with t out of range [0.0,1.0]")
|
||||
}
|
||||
|
||||
return cPoint1.Mul((1 - t) * (1 - t) * (1 - t)).Add(cPoint2.Mul(3 * (1 - t) * (1 - t) * t)).Add(cPoint3.Mul(3 * (1 - t) * t * t)).Add(cPoint4.Mul(t * t * t))
|
||||
}
|
||||
|
||||
func CubicBezierCurve3D(t float32, cPoint1, cPoint2, cPoint3, cPoint4 Vec3) Vec3 {
|
||||
if t < 0.0 || t > 1.0 {
|
||||
panic("Can't interpolate on bezier curve with t out of range [0.0,1.0]")
|
||||
}
|
||||
|
||||
return cPoint1.Mul((1 - t) * (1 - t) * (1 - t)).Add(cPoint2.Mul(3 * (1 - t) * (1 - t) * t)).Add(cPoint3.Mul(3 * (1 - t) * t * t)).Add(cPoint4.Mul(t * t * t))
|
||||
}
|
||||
|
||||
// Returns the point at point t along an n-control point Bezier curve
|
||||
//
|
||||
// t must be in the range 0.0 and 1.0 or this function will panic. Consider [0.0,1.0] to be similar to a percentage,
|
||||
// 0.0 is first control point, and the point at 1.0 is the last control point. Any point in between is how far along the path you are between 0 and 1.
|
||||
//
|
||||
// This function is not sensitive to the coordinate system of the control points. It will correctly interpolate regardless of whether they're in screen coords,
|
||||
// gl coords, or something else entirely
|
||||
func BezierCurve2D(t float32, cPoints []Vec2) Vec2 {
|
||||
if t < 0.0 || t > 1.0 {
|
||||
panic("Input to bezier has t not in range [0,1]. If you think this is a precision error, use mathgl.Clamp[f|d] before calling this function")
|
||||
}
|
||||
|
||||
n := len(cPoints) - 1
|
||||
point := cPoints[0].Mul(float32(math.Pow(float64(1.0-t), float64(n))))
|
||||
|
||||
for i := 1; i <= n; i++ {
|
||||
point = point.Add(cPoints[i].Mul(float32(float64(choose(n, i)) * math.Pow(float64(1-t), float64(n-i)) * math.Pow(float64(t), float64(i))))) // P += P_i * nCi * (1-t)^(n-i) * t^i
|
||||
}
|
||||
|
||||
return point
|
||||
}
|
||||
|
||||
// Same as the 2D version, except the line is in 3D space
|
||||
func BezierCurve3D(t float32, cPoints []Vec3) Vec3 {
|
||||
if t < 0.0 || t > 1.0 {
|
||||
panic("Input to bezier has t not in range [0,1]. If you think this is a precision error, use mathgl.Clamp[f|d] before calling this function")
|
||||
}
|
||||
|
||||
n := len(cPoints) - 1
|
||||
point := cPoints[0].Mul(float32(math.Pow(float64(1.0-t), float64(n))))
|
||||
|
||||
for i := 1; i <= n; i++ {
|
||||
point = point.Add(cPoints[i].Mul(float32(float64(choose(n, i)) * math.Pow(float64(1-t), float64(n-i)) * math.Pow(float64(t), float64(i))))) // P += P_i * nCi * (1-t)^(n-i) * t^i
|
||||
}
|
||||
|
||||
return point
|
||||
}
|
||||
|
||||
// Generates a bezier curve with controlPoints cPoints. The numPoints argument
|
||||
// determines how many "samples" it makes along the line. For instance, a
|
||||
// call to this with numPoints 2 will have exactly two points: the start and end points
|
||||
// For any points above 2 it will divide it into numPoints-1 chunks (which means it will generate numPoints-2 vertices other than the beginning and end).
|
||||
// So for 3 points it will divide it in half, 4 points into thirds, and so on.
|
||||
//
|
||||
// This is likely to get rather expensive for anything over perhaps a cubic curve.
|
||||
func MakeBezierCurve2D(numPoints int, cPoints []Vec2) (line []Vec2) {
|
||||
line = make([]Vec2, numPoints)
|
||||
if numPoints == 0 {
|
||||
return
|
||||
} else if numPoints == 1 {
|
||||
line[0] = cPoints[0]
|
||||
return
|
||||
} else if numPoints == 2 {
|
||||
line[0] = cPoints[0]
|
||||
line[1] = cPoints[len(cPoints)-1]
|
||||
return
|
||||
}
|
||||
|
||||
line[0] = cPoints[0]
|
||||
for i := 1; i < numPoints-1; i++ {
|
||||
line[i] = BezierCurve2D(Clamp(float32(i)/float32(numPoints-1), 0.0, 1.0), cPoints)
|
||||
}
|
||||
line[numPoints-1] = cPoints[len(cPoints)-1]
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Same as the 2D version, except with the line in 3D space
|
||||
func MakeBezierCurve3D(numPoints int, cPoints []Vec3) (line []Vec3) {
|
||||
line = make([]Vec3, numPoints)
|
||||
if numPoints == 0 {
|
||||
return
|
||||
} else if numPoints == 1 {
|
||||
line[0] = cPoints[0]
|
||||
return
|
||||
} else if numPoints == 2 {
|
||||
line[0] = cPoints[0]
|
||||
line[1] = cPoints[len(cPoints)-1]
|
||||
return
|
||||
}
|
||||
|
||||
line[0] = cPoints[0]
|
||||
for i := 1; i < numPoints-1; i++ {
|
||||
line[i] = BezierCurve3D(Clamp(float32(i)/float32(numPoints-1), 0.0, 1.0), cPoints)
|
||||
}
|
||||
line[numPoints-1] = cPoints[len(cPoints)-1]
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Creates a 2-dimensional Bezier surface of arbitrary degree in 3D Space
|
||||
// Like the curve functions, if u or v are not in the range [0.0,1.0] the function will panic, use Clamp[f|d]
|
||||
// to ensure it is correct.
|
||||
//
|
||||
// The control point matrix must not be jagged, or this will end up panicking from an index out of bounds exception
|
||||
func BezierSurface(u, v float32, cPoints [][]Vec3) Vec3 {
|
||||
if u < 0.0 || u > 1.0 || v < 1.0 || v > 1.0 {
|
||||
panic("u or v not in range [0.0,1.0] in BezierSurface")
|
||||
}
|
||||
|
||||
n := len(cPoints) - 1
|
||||
m := len(cPoints[0]) - 1
|
||||
|
||||
point := cPoints[0][0].Mul(float32(math.Pow(float64(1.0-u), float64(n)) * math.Pow(float64(1.0-v), float64(m))))
|
||||
|
||||
for i := 0; i <= n; i++ {
|
||||
for j := 0; j <= m; j++ {
|
||||
if i == 0 && j == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
point = point.Add(cPoints[i][j].Mul(float32(float64(choose(n, i)) * math.Pow(float64(u), float64(i)) * math.Pow(float64(1.0-u), float64(n-i)) * float64(choose(m, j)) * math.Pow(float64(v), float64(j)) * math.Pow(float64(1.0-v), float64(m-j)))))
|
||||
}
|
||||
}
|
||||
|
||||
return point
|
||||
}
|
||||
|
||||
// Does interpolation over a spline of several bezier curves. Each bezier curve must have a finite range,
|
||||
// though the spline may be disjoint. The bezier curves are not required to be in any particular order.
|
||||
//
|
||||
// If t is out of the range of all given curves, this function will panic
|
||||
func BezierSplineInterpolate2D(t float32, ranges [][2]float32, cPoints [][]Vec2) Vec2 {
|
||||
if len(ranges) != len(cPoints) {
|
||||
panic("Each bezier curve needs a range")
|
||||
}
|
||||
|
||||
for i, curveRange := range ranges {
|
||||
if t >= curveRange[0] && t <= curveRange[1] {
|
||||
return BezierCurve2D((t-curveRange[0])/(curveRange[1]-curveRange[0]), cPoints[i])
|
||||
}
|
||||
}
|
||||
|
||||
panic("t is out of the range of all bezier curves in this spline")
|
||||
}
|
||||
|
||||
// Does interpolation over a spline of several bezier curves. Each bezier curve must have a finite range,
|
||||
// though the spline may be disjoint. The bezier curves are not required to be in any particular order.
|
||||
//
|
||||
// If t is out of the range of all given curves, this function will panic
|
||||
func BezierSplineInterpolate3D(t float32, ranges [][2]float32, cPoints [][]Vec3) Vec3 {
|
||||
if len(ranges) != len(cPoints) {
|
||||
panic("Each bezier curve needs a range")
|
||||
}
|
||||
|
||||
for i, curveRange := range ranges {
|
||||
if t >= curveRange[0] && t <= curveRange[1] {
|
||||
return BezierCurve3D((t-curveRange[0])/(curveRange[1]-curveRange[0]), cPoints[i])
|
||||
}
|
||||
}
|
||||
|
||||
panic("t is out of the range of all bezier curves in this spline")
|
||||
}
|
||||
|
||||
// Reticulates ALL the Splines
|
||||
//
|
||||
// For the overly serious: the function is just for fun. It does nothing except prints a Maxis reference. Technically you could "reticulate splines"
|
||||
// by joining a bunch of splines together, but that ruins the joke.
|
||||
func ReticulateSplines(ranges [][][2]float32, cPoints [][][]Vec2, withLlamas bool) {
|
||||
if !withLlamas {
|
||||
fmt.Println("You can't reticulate splines without llamas, silly.")
|
||||
} else {
|
||||
fmt.Println("Actually, you can't even reticulate splines WITH llamas")
|
||||
}
|
||||
}
|
||||
|
||||
// Transform from pixel coordinates to GL coordinates.
|
||||
//
|
||||
// This assumes that your pixel coordinate system considers its origin to be in the top left corner (GL's is in the bottom left).
|
||||
// The coordinates x and y may be out of the range [0,screenWidth-1] and [0,screeneHeight-1].
|
||||
//
|
||||
// GL's coordinate system maps [screenWidth-1,0] to [1.0,1.0] and [0,screenHeight-1] to [-1.0,-1.0]. If x and y are out of the range, they'll still
|
||||
// be mapped correctly, just off the screen. (e.g. if y = 2*(screenHeight-1) you'll get -3.0 for yOut)
|
||||
//
|
||||
// This is similar to Unproject, except for 2D cases and much simpler (especially since an inverse may always be found)
|
||||
func ScreenToGLCoords(x, y int, screenWidth, screenHeight int) (xOut, yOut float32) {
|
||||
xOut = 2.0*float32(x)/float32(screenWidth-1) - 1.0
|
||||
yOut = -2.0*float32(y)/float32(screenHeight-1) + 1.0
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Transform from GL's proportional system to pixel coordinates.
|
||||
//
|
||||
// Assumes the pixel coordinate system has its origin in the top left corner. (GL's is in the bottom left)
|
||||
//
|
||||
// GL's coordinate system maps [screenWidth-1,0] to [1.0,1.0] and [0,screenHeight-1] to [-1.0,-1.0]. If x and y are out of the range, they'll still
|
||||
// be mapped correctly, just off the screen. (e.g. if y=-3.0, you'll get 2*(screenHeight-1) for yOut)
|
||||
//
|
||||
// This is similar to Project, except for 2D cases and much simpler
|
||||
func GLToScreenCoords(x, y float32, screenWidth, screenHeight int) (xOut, yOut int) {
|
||||
xOut = int((x + 1.0) * float32(screenWidth-1) / 2.0)
|
||||
yOut = int((1.0 - y) * float32(screenHeight-1) / 2.0)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func choose(n, k int) (result int) {
|
||||
if k == 0 {
|
||||
return 1
|
||||
} else if n == 0 {
|
||||
return 0
|
||||
}
|
||||
result = (n - (k - 1))
|
||||
for i := 2; i <= k; i++ {
|
||||
result *= (n - (k - i)) / i
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
223
vendor/github.com/go-gl/mathgl/mgl32/transform.go
generated
vendored
Normal file
223
vendor/github.com/go-gl/mathgl/mgl32/transform.go
generated
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
// Copyright 2014 The go-gl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mgl32
|
||||
|
||||
import "math"
|
||||
|
||||
// Rotate2D returns a rotation Matrix about a angle in 2-D space. Specifically about the origin.
|
||||
// It is a 2x2 matrix, if you need a 3x3 for Homogeneous math (e.g. composition with a Translation matrix)
|
||||
// see HomogRotate2D
|
||||
func Rotate2D(angle float32) Mat2 {
|
||||
//angle = (angle * math.Pi) / 180.0
|
||||
sin, cos := float32(math.Sin(float64(angle))), float32(math.Cos(float64(angle)))
|
||||
return Mat2{cos, sin, -sin, cos}
|
||||
}
|
||||
|
||||
// Rotate3DX returns a 3x3 (non-homogeneous) Matrix that rotates by angle about the X-axis
|
||||
//
|
||||
// Where c is cos(angle) and s is sin(angle)
|
||||
// [1 0 0]
|
||||
// [0 c -s]
|
||||
// [0 s c ]
|
||||
func Rotate3DX(angle float32) Mat3 {
|
||||
//angle = (angle * math.Pi) / 180.0
|
||||
sin, cos := float32(math.Sin(float64(angle))), float32(math.Cos(float64(angle)))
|
||||
|
||||
return Mat3{1, 0, 0, 0, cos, sin, 0, -sin, cos}
|
||||
}
|
||||
|
||||
// Rotate3DY returns a 3x3 (non-homogeneous) Matrix that rotates by angle about the Y-axis
|
||||
//
|
||||
// Where c is cos(angle) and s is sin(angle)
|
||||
// [c 0 s]
|
||||
// [0 1 0]
|
||||
// [s 0 c ]
|
||||
func Rotate3DY(angle float32) Mat3 {
|
||||
//angle = (angle * math.Pi) / 180.0
|
||||
sin, cos := float32(math.Sin(float64(angle))), float32(math.Cos(float64(angle)))
|
||||
|
||||
return Mat3{cos, 0, -sin, 0, 1, 0, sin, 0, cos}
|
||||
}
|
||||
|
||||
// Rotate3DZ returns a 3x3 (non-homogeneous) Matrix that rotates by angle about the Z-axis
|
||||
//
|
||||
// Where c is cos(angle) and s is sin(angle)
|
||||
// [c -s 0]
|
||||
// [s c 0]
|
||||
// [0 0 1 ]
|
||||
func Rotate3DZ(angle float32) Mat3 {
|
||||
//angle = (angle * math.Pi) / 180.0
|
||||
sin, cos := float32(math.Sin(float64(angle))), float32(math.Cos(float64(angle)))
|
||||
|
||||
return Mat3{cos, sin, 0, -sin, cos, 0, 0, 0, 1}
|
||||
}
|
||||
|
||||
// Translate2D returns a homogeneous (3x3 for 2D-space) Translation matrix that moves a point by Tx units in the x-direction and Ty units in the y-direction
|
||||
//
|
||||
// [[1, 0, Tx]]
|
||||
// [[0, 1, Ty]]
|
||||
// [[0, 0, 1 ]]
|
||||
func Translate2D(Tx, Ty float32) Mat3 {
|
||||
return Mat3{1, 0, 0, 0, 1, 0, float32(Tx), float32(Ty), 1}
|
||||
}
|
||||
|
||||
// Translate3D returns a homogeneous (4x4 for 3D-space) Translation matrix that moves a point by Tx units in the x-direction, Ty units in the y-direction,
|
||||
// and Tz units in the z-direction
|
||||
//
|
||||
// [[1, 0, 0, Tx]]
|
||||
// [[0, 1, 0, Ty]]
|
||||
// [[0, 0, 1, Tz]]
|
||||
// [[0, 0, 0, 1 ]]
|
||||
func Translate3D(Tx, Ty, Tz float32) Mat4 {
|
||||
return Mat4{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, float32(Tx), float32(Ty), float32(Tz), 1}
|
||||
}
|
||||
|
||||
// Same as Rotate2D, except homogeneous (3x3 with the extra row/col being all zeroes with a one in the bottom right)
|
||||
func HomogRotate2D(angle float32) Mat3 {
|
||||
//angle = (angle * math.Pi) / 180.0
|
||||
sin, cos := float32(math.Sin(float64(angle))), float32(math.Cos(float64(angle)))
|
||||
return Mat3{cos, sin, 0, -sin, cos, 0, 0, 0, 1}
|
||||
}
|
||||
|
||||
// Same as Rotate3DX, except homogeneous (4x4 with the extra row/col being all zeroes with a one in the bottom right)
|
||||
func HomogRotate3DX(angle float32) Mat4 {
|
||||
//angle = (angle * math.Pi) / 180.0
|
||||
sin, cos := float32(math.Sin(float64(angle))), float32(math.Cos(float64(angle)))
|
||||
|
||||
return Mat4{1, 0, 0, 0, 0, cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1}
|
||||
}
|
||||
|
||||
// Same as Rotate3DY, except homogeneous (4x4 with the extra row/col being all zeroes with a one in the bottom right)
|
||||
func HomogRotate3DY(angle float32) Mat4 {
|
||||
//angle = (angle * math.Pi) / 180.0
|
||||
sin, cos := float32(math.Sin(float64(angle))), float32(math.Cos(float64(angle)))
|
||||
return Mat4{cos, 0, -sin, 0, 0, 1, 0, 0, sin, 0, cos, 0, 0, 0, 0, 1}
|
||||
}
|
||||
|
||||
// Same as Rotate3DZ, except homogeneous (4x4 with the extra row/col being all zeroes with a one in the bottom right)
|
||||
func HomogRotate3DZ(angle float32) Mat4 {
|
||||
//angle = (angle * math.Pi) / 180.0
|
||||
sin, cos := float32(math.Sin(float64(angle))), float32(math.Cos(float64(angle)))
|
||||
return Mat4{cos, sin, 0, 0, -sin, cos, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}
|
||||
}
|
||||
|
||||
// Scale3D creates a homogeneous 3D scaling matrix
|
||||
// [[ scaleX, 0 , 0 , 0 ]]
|
||||
// [[ 0 , scaleY, 0 , 0 ]]
|
||||
// [[ 0 , 0 , scaleZ, 0 ]]
|
||||
// [[ 0 , 0 , 0 , 1 ]]
|
||||
func Scale3D(scaleX, scaleY, scaleZ float32) Mat4 {
|
||||
|
||||
return Mat4{float32(scaleX), 0, 0, 0, 0, float32(scaleY), 0, 0, 0, 0, float32(scaleZ), 0, 0, 0, 0, 1}
|
||||
}
|
||||
|
||||
// Scale2D creates a homogeneous 2D scaling matrix
|
||||
// [[ scaleX, 0 , 0 ]]
|
||||
// [[ 0 , scaleY, 0 ]]
|
||||
// [[ 0 , 0 , 1 ]]
|
||||
func Scale2D(scaleX, scaleY float32) Mat3 {
|
||||
return Mat3{float32(scaleX), 0, 0, 0, float32(scaleY), 0, 0, 0, 1}
|
||||
}
|
||||
|
||||
// ShearX2D creates a homogeneous 2D shear matrix along the X-axis
|
||||
func ShearX2D(shear float32) Mat3 {
|
||||
return Mat3{1, 0, 0, float32(shear), 1, 0, 0, 0, 1}
|
||||
}
|
||||
|
||||
// ShearY2D creates a homogeneous 2D shear matrix along the Y-axis
|
||||
func ShearY2D(shear float32) Mat3 {
|
||||
return Mat3{1, float32(shear), 0, 0, 1, 0, 0, 0, 1}
|
||||
}
|
||||
|
||||
// ShearX3D creates a homogeneous 3D shear matrix along the X-axis
|
||||
func ShearX3D(shearY, shearZ float32) Mat4 {
|
||||
|
||||
return Mat4{1, float32(shearY), float32(shearZ), 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}
|
||||
}
|
||||
|
||||
// ShearY3D creates a homogeneous 3D shear matrix along the Y-axis
|
||||
func ShearY3D(shearX, shearZ float32) Mat4 {
|
||||
return Mat4{1, 0, 0, 0, float32(shearX), 1, float32(shearZ), 0, 0, 0, 1, 0, 0, 0, 0, 1}
|
||||
}
|
||||
|
||||
// ShearZ3D creates a homogeneous 3D shear matrix along the Z-axis
|
||||
func ShearZ3D(shearX, shearY float32) Mat4 {
|
||||
return Mat4{1, 0, 0, 0, 0, 1, 0, 0, float32(shearX), float32(shearY), 1, 0, 0, 0, 0, 1}
|
||||
}
|
||||
|
||||
// HomogRotate3D creates a 3D rotation Matrix that rotates by (radian) angle about some arbitrary axis given by a Vector.
|
||||
// It produces a homogeneous matrix (4x4)
|
||||
//
|
||||
// Where c is cos(angle) and s is sin(angle), and x, y, and z are the first, second, and third elements of the axis vector (respectively):
|
||||
//
|
||||
// [[ x^2(1-c)+c, xy(1-c)-zs, xz(1-c)+ys, 0 ]]
|
||||
// [[ xy(1-c)+zs, y^2(1-c)+c, yz(1-c)-xs, 0 ]]
|
||||
// [[ xz(1-c)-ys, yz(1-c)+xs, z^2(1-c)+c, 0 ]]
|
||||
// [[ 0 , 0 , 0 , 1 ]]
|
||||
func HomogRotate3D(angle float32, axis Vec3) Mat4 {
|
||||
x, y, z := axis[0], axis[1], axis[2]
|
||||
s, c := float32(math.Sin(float64(angle))), float32(math.Cos(float64(angle)))
|
||||
k := 1 - c
|
||||
|
||||
return Mat4{x*x*k + c, x*y*k + z*s, x*z*k - y*s, 0, x*y*k - z*s, y*y*k + c, y*z*k + x*s, 0, x*z*k + y*s, y*z*k - x*s, z*z*k + c, 0, 0, 0, 0, 1}
|
||||
}
|
||||
|
||||
// Extracts the 3d scaling from a homogeneous matrix
|
||||
func Extract3DScale(m Mat4) (x, y, z float32) {
|
||||
return float32(math.Sqrt(float64(m[0]*m[0] + m[1]*m[1] + m[2]*m[2]))),
|
||||
float32(math.Sqrt(float64(m[4]*m[4] + m[5]*m[5] + m[6]*m[6]))),
|
||||
float32(math.Sqrt(float64(m[8]*m[8] + m[9]*m[9] + m[10]*m[10])))
|
||||
}
|
||||
|
||||
// Extracts the maximum scaling from a homogeneous matrix
|
||||
func ExtractMaxScale(m Mat4) float32 {
|
||||
scaleX := float64(m[0]*m[0] + m[1]*m[1] + m[2]*m[2])
|
||||
scaleY := float64(m[4]*m[4] + m[5]*m[5] + m[6]*m[6])
|
||||
scaleZ := float64(m[8]*m[8] + m[9]*m[9] + m[10]*m[10])
|
||||
|
||||
return float32(math.Sqrt(math.Max(scaleX, math.Max(scaleY, scaleZ))))
|
||||
}
|
||||
|
||||
// Calculates the Normal of the Matrix (aka the inverse transpose)
|
||||
func Mat4Normal(m Mat4) Mat3 {
|
||||
n := m.Inv().Transpose()
|
||||
return Mat3{n[0], n[1], n[2], n[4], n[5], n[6], n[8], n[9], n[10]}
|
||||
}
|
||||
|
||||
// Multiplies a 3D vector by a transformation given by
|
||||
// the homogeneous 4D matrix m, applying any translation.
|
||||
// If this transformation is non-affine, it will project this
|
||||
// vector onto the plane w=1 before returning the result.
|
||||
//
|
||||
// This is similar to saying you're transforming and projecting a point.
|
||||
//
|
||||
// This is effectively equivalent to the GLSL code
|
||||
// vec4 r = (m * vec4(v,1.));
|
||||
// r = r/r.w;
|
||||
// vec3 newV = r.xyz;
|
||||
func TransformCoordinate(v Vec3, m Mat4) Vec3 {
|
||||
t := v.Vec4(1)
|
||||
t = m.Mul4x1(t)
|
||||
t = t.Mul(1 / t[3])
|
||||
|
||||
return t.Vec3()
|
||||
}
|
||||
|
||||
// Multiplies a 3D vector by a transformation given by
|
||||
// the homogeneous 4D matrix m, NOT applying any translations.
|
||||
//
|
||||
// This is similar to saying you're applying a transformation
|
||||
// to a direction or normal. Rotation still applies (as does scaling),
|
||||
// but translating a direction or normal is meaningless.
|
||||
//
|
||||
// This is effectively equivalent to the GLSL code
|
||||
// vec4 r = (m * vec4(v,0.));
|
||||
// vec3 newV = r.xyz
|
||||
func TransformNormal(v Vec3, m Mat4) Vec3 {
|
||||
t := v.Vec4(0)
|
||||
t = m.Mul4x1(t)
|
||||
|
||||
return t.Vec3()
|
||||
}
|
142
vendor/github.com/go-gl/mathgl/mgl32/util.go
generated
vendored
Normal file
142
vendor/github.com/go-gl/mathgl/mgl32/util.go
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
// Copyright 2014 The go-gl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run codegen.go -template vector.tmpl -output vector.go
|
||||
//go:generate go run codegen.go -template matrix.tmpl -output matrix.go
|
||||
//go:generate go run codegen.go -mgl64
|
||||
|
||||
package mgl32
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// Epsilon is some tiny value that determines how precisely equal we want our floats to be
|
||||
// This is exported and left as a variable in case you want to change the default threshold for the
|
||||
// purposes of certain methods (e.g. Unproject uses the default epsilon when determining
|
||||
// if the determinant is "close enough" to zero to mean there's no inverse).
|
||||
//
|
||||
// This is, obviously, not mutex protected so be **absolutely sure** that no functions using Epsilon
|
||||
// are being executed when you change this.
|
||||
var Epsilon float32 = 1e-10
|
||||
|
||||
// A direct copy of the math package's Abs. This is here for the mgl32
|
||||
// package, to prevent rampant type conversions during equality tests.
|
||||
func Abs(a float32) float32 {
|
||||
if a < 0 {
|
||||
return -a
|
||||
} else if a == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// FloatEqual is a safe utility function to compare floats.
|
||||
// It's Taken from http://floating-point-gui.de/errors/comparison/
|
||||
//
|
||||
// It is slightly altered to not call Abs when not needed.
|
||||
func FloatEqual(a, b float32) bool {
|
||||
return FloatEqualThreshold(a, b, Epsilon)
|
||||
}
|
||||
|
||||
// FloatEqualFunc is a utility closure that will generate a function that
|
||||
// always approximately compares floats like FloatEqualThreshold with a different
|
||||
// threshold.
|
||||
func FloatEqualFunc(epsilon float32) func(float32, float32) bool {
|
||||
return func(a, b float32) bool {
|
||||
return FloatEqualThreshold(a, b, epsilon)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
MinNormal = float32(1.1754943508222875e-38) // 1 / 2**(127 - 1)
|
||||
MinValue = float32(math.SmallestNonzeroFloat32)
|
||||
MaxValue = float32(math.MaxFloat32)
|
||||
|
||||
InfPos = float32(math.Inf(1))
|
||||
InfNeg = float32(math.Inf(-1))
|
||||
NaN = float32(math.NaN())
|
||||
)
|
||||
|
||||
// FloatEqualThreshold is a utility function to compare floats.
|
||||
// It's Taken from http://floating-point-gui.de/errors/comparison/
|
||||
//
|
||||
// It is slightly altered to not call Abs when not needed.
|
||||
//
|
||||
// This differs from FloatEqual in that it lets you pass in your comparison threshold, so that you can adjust the comparison value to your specific needs
|
||||
func FloatEqualThreshold(a, b, epsilon float32) bool {
|
||||
if a == b { // Handles the case of inf or shortcuts the loop when no significant error has accumulated
|
||||
return true
|
||||
}
|
||||
|
||||
diff := Abs(a - b)
|
||||
if a*b == 0 || diff < MinNormal { // If a or b are 0 or both are extremely close to it
|
||||
return diff < epsilon*epsilon
|
||||
}
|
||||
|
||||
// Else compare difference
|
||||
return diff/(Abs(a)+Abs(b)) < epsilon
|
||||
}
|
||||
|
||||
// Clamp takes in a value and two thresholds. If the value is smaller than the low
|
||||
// threshold, it returns the low threshold. If it's bigger than the high threshold
|
||||
// it returns the high threshold. Otherwise it returns the value.
|
||||
//
|
||||
// Useful to prevent some functions from freaking out because a value was
|
||||
// teeeeechnically out of range.
|
||||
func Clamp(a, low, high float32) float32 {
|
||||
if a < low {
|
||||
return low
|
||||
} else if a > high {
|
||||
return high
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// ClampFunc generates a closure that returns its parameter
|
||||
// clamped to the range [low,high].
|
||||
func ClampFunc(low, high float32) func(float32) float32 {
|
||||
return func(a float32) float32 {
|
||||
return Clamp(a, low, high)
|
||||
}
|
||||
}
|
||||
|
||||
/* The IsClamped functions use strict equality (meaning: not the FloatEqual function)
|
||||
there shouldn't be any major issues with this since clamp is often used to fix minor errors*/
|
||||
|
||||
// Checks if a is clamped between low and high as if
|
||||
// Clamp(a, low, high) had been called.
|
||||
//
|
||||
// In most cases it's probably better to just call Clamp
|
||||
// without checking this since it's relatively cheap.
|
||||
func IsClamped(a, low, high float32) bool {
|
||||
return a >= low && a <= high
|
||||
}
|
||||
|
||||
// If a > b, then a will be set to the value of b.
|
||||
func SetMin(a, b *float32) {
|
||||
if *b < *a {
|
||||
*a = *b
|
||||
}
|
||||
}
|
||||
|
||||
// If a < b, then a will be set to the value of b.
|
||||
func SetMax(a, b *float32) {
|
||||
if *a < *b {
|
||||
*a = *b
|
||||
}
|
||||
}
|
||||
|
||||
// Round shortens a float32 value to a specified precision (number of digits after the decimal point)
|
||||
// with "round half up" tie-braking rule. Half-way values (23.5) are always rounded up (24).
|
||||
func Round(v float32, precision int) float32 {
|
||||
p := float64(precision)
|
||||
t := float64(v) * math.Pow(10, p)
|
||||
if t > 0 {
|
||||
return float32(math.Floor(t+0.5) / math.Pow(10, p))
|
||||
}
|
||||
return float32(math.Ceil(t-0.5) / math.Pow(10, p))
|
||||
}
|
350
vendor/github.com/go-gl/mathgl/mgl32/vecn.go
generated
vendored
Normal file
350
vendor/github.com/go-gl/mathgl/mgl32/vecn.go
generated
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
// Copyright 2014 The go-gl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package mgl32
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// A vector of N elements backed by a slice
|
||||
//
|
||||
// As with MatMxN, this is not for hardcore linear algebra with large dimensions. Use github.com/gonum/matrix
|
||||
// or something like BLAS/LAPACK for that. This is for corner cases in 3D math where you require
|
||||
// something a little bigger that 4D, but still relatively small.
|
||||
//
|
||||
// This VecN uses several sync.Pool objects as a memory pool. The rule is that for any sized vector, the backing slice
|
||||
// has CAPACITY (not length) of 2^p where p is Ceil(log_2(N)) -- or in other words, rounding up the base-2
|
||||
// log of the size of the vector. E.G. a VecN of size 17 will have a backing slice of Cap 32.
|
||||
type VecN struct {
|
||||
vec []float32
|
||||
}
|
||||
|
||||
// Creates a new vector with a backing slice filled with the contents
|
||||
// of initial. It is NOT backed by initial, but rather a slice with cap
|
||||
// 2^p where p is Ceil(log_2(len(initial))), with the data from initial copied into
|
||||
// it.
|
||||
func NewVecNFromData(initial []float32) *VecN {
|
||||
if initial == nil {
|
||||
return &VecN{}
|
||||
}
|
||||
var internal []float32
|
||||
if shouldPool {
|
||||
internal = grabFromPool(len(initial))
|
||||
} else {
|
||||
internal = make([]float32, len(initial))
|
||||
}
|
||||
copy(internal, initial)
|
||||
return &VecN{vec: internal}
|
||||
}
|
||||
|
||||
// Creates a new vector with a backing slice of
|
||||
// 2^p where p = Ceil(log_2(n))
|
||||
func NewVecN(n int) *VecN {
|
||||
if shouldPool {
|
||||
return &VecN{vec: grabFromPool(n)}
|
||||
} else {
|
||||
return &VecN{vec: make([]float32, n)}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the raw slice backing the VecN
|
||||
//
|
||||
// This may be sent back to the memory pool at any time
|
||||
// and you aren't advised to rely on this value
|
||||
func (vn VecN) Raw() []float32 {
|
||||
return vn.vec
|
||||
}
|
||||
|
||||
// Gets the element at index i from the vector.
|
||||
// This does not bounds check, and will panic if i is
|
||||
// out of range.
|
||||
func (vn VecN) Get(i int) float32 {
|
||||
return vn.vec[i]
|
||||
}
|
||||
|
||||
func (vn *VecN) Set(i int, val float32) {
|
||||
vn.vec[i] = val
|
||||
}
|
||||
|
||||
// Sends the allocated memory through the callback if it exists
|
||||
func (vn *VecN) destroy() {
|
||||
if vn == nil || vn.vec == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if shouldPool {
|
||||
returnToPool(vn.vec)
|
||||
}
|
||||
vn.vec = nil
|
||||
}
|
||||
|
||||
// Resizes the underlying slice to the desired amount, reallocating or retrieving from the pool
|
||||
// if necessary. The values after a Resize cannot be expected to be related to the values before a Resize.
|
||||
//
|
||||
// If the caller is a nil pointer, this returns a value as if NewVecN(n) had been called,
|
||||
// otherwise it simply returns the caller.
|
||||
func (vn *VecN) Resize(n int) *VecN {
|
||||
if vn == nil {
|
||||
return NewVecN(n)
|
||||
}
|
||||
|
||||
if n <= cap(vn.vec) {
|
||||
if vn.vec != nil {
|
||||
vn.vec = vn.vec[:n]
|
||||
} else {
|
||||
vn.vec = []float32{}
|
||||
}
|
||||
return vn
|
||||
}
|
||||
|
||||
if shouldPool && vn.vec != nil {
|
||||
returnToPool(vn.vec)
|
||||
}
|
||||
*vn = (*NewVecN(n))
|
||||
|
||||
return vn
|
||||
}
|
||||
|
||||
// Sets the vector's backing slice to the given
|
||||
// new one.
|
||||
func (vn *VecN) SetBackingSlice(newSlice []float32) {
|
||||
vn.vec = newSlice
|
||||
}
|
||||
|
||||
// Return the len of the vector's underlying slice.
|
||||
// This is not titled Len because it conflicts the package's
|
||||
// convention of calling the Norm the Len.
|
||||
func (vn *VecN) Size() int {
|
||||
return len(vn.vec)
|
||||
}
|
||||
|
||||
// Returns the cap of the vector's underlying slice.
|
||||
func (vn *VecN) Cap() int {
|
||||
return cap(vn.vec)
|
||||
}
|
||||
|
||||
// Sets the vector's size to n and zeroes out the vector.
|
||||
// If n is bigger than the vector's size, it will realloc.
|
||||
func (vn *VecN) Zero(n int) {
|
||||
vn.Resize(n)
|
||||
for i := range vn.vec {
|
||||
vn.vec[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
// Adds vn and addend, storing the result in dst.
|
||||
// If dst does not have sufficient size it will be resized
|
||||
// Dst may be one of the other arguments. If dst is nil, it will be allocated.
|
||||
// The value returned is dst, for easier method chaining
|
||||
//
|
||||
// If vn and addend are not the same size, this function will add min(vn.Size(), addend.Size())
|
||||
// elements.
|
||||
func (vn *VecN) Add(dst *VecN, subtrahend *VecN) *VecN {
|
||||
if vn == nil || subtrahend == nil {
|
||||
return nil
|
||||
}
|
||||
size := intMin(len(vn.vec), len(subtrahend.vec))
|
||||
dst = dst.Resize(size)
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
dst.vec[i] = vn.vec[i] + subtrahend.vec[i]
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Subtracts addend from vn, storing the result in dst.
|
||||
// If dst does not have sufficient size it will be resized
|
||||
// Dst may be one of the other arguments. If dst is nil, it will be allocated.
|
||||
// The value returned is dst, for easier method chaining
|
||||
//
|
||||
// If vn and addend are not the same size, this function will add min(vn.Size(), addend.Size())
|
||||
// elements.
|
||||
func (vn *VecN) Sub(dst *VecN, addend *VecN) *VecN {
|
||||
if vn == nil || addend == nil {
|
||||
return nil
|
||||
}
|
||||
size := intMin(len(vn.vec), len(addend.vec))
|
||||
dst = dst.Resize(size)
|
||||
|
||||
for i := 0; i < size; i++ {
|
||||
dst.vec[i] = vn.vec[i] - addend.vec[i]
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Takes the binary cross product of vn and other, and stores it in dst.
|
||||
// If either vn or other are not of size 3 this function will panic
|
||||
//
|
||||
// If dst is not of sufficient size, or is nil, a new slice is allocated.
|
||||
// Dst is permitted to be one of the other arguments
|
||||
func (vn *VecN) Cross(dst *VecN, other *VecN) *VecN {
|
||||
if vn == nil || other == nil {
|
||||
return nil
|
||||
}
|
||||
if len(vn.vec) != 3 || len(other.vec) != 3 {
|
||||
panic("Cannot take binary cross product of non-3D elements (7D cross product not implemented)")
|
||||
}
|
||||
|
||||
dst = dst.Resize(3)
|
||||
dst.vec[0], dst.vec[1], dst.vec[2] = vn.vec[1]*other.vec[2]-vn.vec[2]*other.vec[1], vn.vec[2]*other.vec[0]-vn.vec[0]*other.vec[2], vn.vec[0]*other.vec[1]-vn.vec[1]*other.vec[0]
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
func intMin(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// Computes the dot product of two VecNs, if
|
||||
// the two vectors are not of the same length -- this
|
||||
// will return NaN.
|
||||
func (vn *VecN) Dot(other *VecN) float32 {
|
||||
if vn == nil || other == nil || len(vn.vec) != len(other.vec) {
|
||||
return float32(math.NaN())
|
||||
}
|
||||
|
||||
var result float32 = 0.0
|
||||
for i, el := range vn.vec {
|
||||
result += el * other.vec[i]
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Computes the vector length (also called the Norm) of the
|
||||
// vector. Equivalent to math.Sqrt(vn.Dot(vn)) with the appropriate
|
||||
// type conversions.
|
||||
//
|
||||
// If vn is nil, this returns NaN
|
||||
func (vn *VecN) Len() float32 {
|
||||
if vn == nil {
|
||||
return float32(math.NaN())
|
||||
}
|
||||
if len(vn.vec) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return float32(math.Sqrt(float64(vn.Dot(vn))))
|
||||
}
|
||||
|
||||
// Normalizes the vector and stores the result in dst, which
|
||||
// will be returned. Dst will be appropraitely resized to the
|
||||
// size of vn.
|
||||
//
|
||||
// The destination can be vn itself and nothing will go wrong.
|
||||
//
|
||||
// This is equivalent to vn.Mul(dst, 1/vn.Len())
|
||||
func (vn *VecN) Normalize(dst *VecN) *VecN {
|
||||
if vn == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return vn.Mul(dst, 1/vn.Len())
|
||||
}
|
||||
|
||||
// Multiplied the vector by some scalar value and stores the result in dst, which
|
||||
// will be returned. Dst will be appropraitely resized to the
|
||||
// size of vn.
|
||||
//
|
||||
// The destination can be vn itself and nothing will go wrong.
|
||||
func (vn *VecN) Mul(dst *VecN, c float32) *VecN {
|
||||
if vn == nil {
|
||||
return nil
|
||||
}
|
||||
dst = dst.Resize(len(vn.vec))
|
||||
|
||||
for i, el := range vn.vec {
|
||||
dst.vec[i] = el * c
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
// Performs the vector outer product between vn and v2.
|
||||
// The outer product is like a "reverse" dot product. Where the dot product
|
||||
// aligns both vectors with the "sized" part facing "inward" (Vec3*Vec3=Mat1x3*Mat3x1=Mat1x1=Scalar).
|
||||
// The outer product multiplied them with it facing "outward"
|
||||
// (Vec3*Vec3=Mat3x1*Mat1x3=Mat3x3).
|
||||
//
|
||||
// The matrix dst will be Reshaped to the correct size, if vn or v2 are nil,
|
||||
// this returns nil.
|
||||
func (vn *VecN) OuterProd(dst *MatMxN, v2 *VecN) *MatMxN {
|
||||
if vn == nil || v2 == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
dst = dst.Reshape(len(vn.vec), len(v2.vec))
|
||||
|
||||
for c, el1 := range v2.vec {
|
||||
for r, el2 := range vn.vec {
|
||||
dst.Set(r, c, el1*el2)
|
||||
}
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
|
||||
func (vn *VecN) ApproxEqual(vn2 *VecN) bool {
|
||||
if vn == nil || vn2 == nil || len(vn.vec) != len(vn2.vec) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, el := range vn.vec {
|
||||
if !FloatEqual(el, vn2.vec[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (vn *VecN) ApproxEqualThreshold(vn2 *VecN, epsilon float32) bool {
|
||||
if vn == nil || vn2 == nil || len(vn.vec) != len(vn2.vec) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, el := range vn.vec {
|
||||
if !FloatEqualThreshold(el, vn2.vec[i], epsilon) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (vn *VecN) ApproxEqualFunc(vn2 *VecN, comp func(float32, float32) bool) bool {
|
||||
if vn == nil || vn2 == nil || len(vn.vec) != len(vn2.vec) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, el := range vn.vec {
|
||||
if !comp(el, vn2.vec[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (vn *VecN) Vec2() Vec2 {
|
||||
raw := vn.Raw()
|
||||
return Vec2{raw[0], raw[1]}
|
||||
}
|
||||
|
||||
func (vn *VecN) Vec3() Vec3 {
|
||||
raw := vn.Raw()
|
||||
return Vec3{raw[0], raw[1], raw[2]}
|
||||
}
|
||||
|
||||
func (vn *VecN) Vec4() Vec4 {
|
||||
raw := vn.Raw()
|
||||
return Vec4{raw[0], raw[1], raw[2], raw[3]}
|
||||
}
|
562
vendor/github.com/go-gl/mathgl/mgl32/vector.go
generated
vendored
Normal file
562
vendor/github.com/go-gl/mathgl/mgl32/vector.go
generated
vendored
Normal file
@@ -0,0 +1,562 @@
|
||||
// Copyright 2014 The go-gl/mathgl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This file is generated by codegen.go; DO NOT EDIT
|
||||
// Edit vector.tmpl and run "go generate" to make changes.
|
||||
|
||||
package mgl32
|
||||
|
||||
import (
|
||||
"golang.org/x/image/math/f32"
|
||||
"math"
|
||||
)
|
||||
|
||||
type Vec2 f32.Vec2
|
||||
type Vec3 f32.Vec3
|
||||
type Vec4 f32.Vec4
|
||||
|
||||
func (v Vec2) Vec3(z float32) Vec3 {
|
||||
return Vec3{v[0], v[1], z}
|
||||
}
|
||||
|
||||
func (v Vec2) Vec4(z, w float32) Vec4 {
|
||||
return Vec4{v[0], v[1], z, w}
|
||||
}
|
||||
|
||||
func (v Vec3) Vec2() Vec2 {
|
||||
return Vec2{v[0], v[1]}
|
||||
}
|
||||
|
||||
func (v Vec3) Vec4(w float32) Vec4 {
|
||||
return Vec4{v[0], v[1], v[2], w}
|
||||
}
|
||||
|
||||
func (v Vec4) Vec2() Vec2 {
|
||||
return Vec2{v[0], v[1]}
|
||||
}
|
||||
|
||||
func (v Vec4) Vec3() Vec3 {
|
||||
return Vec3{v[0], v[1], v[2]}
|
||||
}
|
||||
|
||||
// Elem extracts the elements of the vector for direct value assignment.
|
||||
func (v Vec2) Elem() (x, y float32) {
|
||||
return v[0], v[1]
|
||||
}
|
||||
|
||||
// Elem extracts the elements of the vector for direct value assignment.
|
||||
func (v Vec3) Elem() (x, y, z float32) {
|
||||
return v[0], v[1], v[2]
|
||||
}
|
||||
|
||||
// Elem extracts the elements of the vector for direct value assignment.
|
||||
func (v Vec4) Elem() (x, y, z, w float32) {
|
||||
return v[0], v[1], v[2], v[3]
|
||||
}
|
||||
|
||||
// The vector cross product is an operation only defined on 3D vectors. It is equivalent to
|
||||
// Vec3{v1[1]*v2[2]-v1[2]*v2[1], v1[2]*v2[0]-v1[0]*v2[2], v1[0]*v2[1] - v1[1]*v2[0]}.
|
||||
// Another interpretation is that it's the vector whose magnitude is |v1||v2|sin(theta)
|
||||
// where theta is the angle between v1 and v2.
|
||||
//
|
||||
// The cross product is most often used for finding surface normals. The cross product of vectors
|
||||
// will generate a vector that is perpendicular to the plane they form.
|
||||
//
|
||||
// Technically, a generalized cross product exists as an "(N-1)ary" operation
|
||||
// (that is, the 4D cross product requires 3 4D vectors). But the binary
|
||||
// 3D (and 7D) cross product is the most important. It can be considered
|
||||
// the area of a parallelogram with sides v1 and v2.
|
||||
//
|
||||
// Like the dot product, the cross product is roughly a measure of directionality.
|
||||
// Two normalized perpendicular vectors will return a vector with a magnitude of
|
||||
// 1.0 or -1.0 and two parallel vectors will return a vector with magnitude 0.0.
|
||||
// The cross product is "anticommutative" meaning v1.Cross(v2) = -v2.Cross(v1),
|
||||
// this property can be useful to know when finding normals,
|
||||
// as taking the wrong cross product can lead to the opposite normal of the one you want.
|
||||
func (v1 Vec3) Cross(v2 Vec3) Vec3 {
|
||||
return Vec3{v1[1]*v2[2] - v1[2]*v2[1], v1[2]*v2[0] - v1[0]*v2[2], v1[0]*v2[1] - v1[1]*v2[0]}
|
||||
}
|
||||
|
||||
// Add performs element-wise addition between two vectors. It is equivalent to iterating
|
||||
// over every element of v1 and adding the corresponding element of v2 to it.
|
||||
func (v1 Vec2) Add(v2 Vec2) Vec2 {
|
||||
return Vec2{v1[0] + v2[0], v1[1] + v2[1]}
|
||||
}
|
||||
|
||||
// Sub performs element-wise subtraction between two vectors. It is equivalent to iterating
|
||||
// over every element of v1 and subtracting the corresponding element of v2 from it.
|
||||
func (v1 Vec2) Sub(v2 Vec2) Vec2 {
|
||||
return Vec2{v1[0] - v2[0], v1[1] - v2[1]}
|
||||
}
|
||||
|
||||
// Mul performs a scalar multiplication between the vector and some constant value
|
||||
// c. This is equivalent to iterating over every vector element and multiplying by c.
|
||||
func (v1 Vec2) Mul(c float32) Vec2 {
|
||||
return Vec2{v1[0] * c, v1[1] * c}
|
||||
}
|
||||
|
||||
// Dot returns the dot product of this vector with another. There are multiple ways
|
||||
// to describe this value. One is the multiplication of their lengths and cos(theta) where
|
||||
// theta is the angle between the vectors: v1.v2 = |v1||v2|cos(theta).
|
||||
//
|
||||
// The other (and what is actually done) is the sum of the element-wise multiplication of all
|
||||
// elements. So for instance, two Vec3s would yield v1.x * v2.x + v1.y * v2.y + v1.z * v2.z.
|
||||
//
|
||||
// This means that the dot product of a vector and itself is the square of its Len (within
|
||||
// the bounds of floating points error).
|
||||
//
|
||||
// The dot product is roughly a measure of how closely two vectors are to pointing in the same
|
||||
// direction. If both vectors are normalized, the value will be -1 for opposite pointing,
|
||||
// one for same pointing, and 0 for perpendicular vectors.
|
||||
func (v1 Vec2) Dot(v2 Vec2) float32 {
|
||||
return v1[0]*v2[0] + v1[1]*v2[1]
|
||||
}
|
||||
|
||||
// Len returns the vector's length. Note that this is NOT the dimension of
|
||||
// the vector (len(v)), but the mathematical length. This is equivalent to the square
|
||||
// root of the sum of the squares of all elements. E.G. for a Vec2 it's
|
||||
// math.Hypot(v[0], v[1]).
|
||||
func (v1 Vec2) Len() float32 {
|
||||
|
||||
return float32(math.Hypot(float64(v1[0]), float64(v1[1])))
|
||||
|
||||
}
|
||||
|
||||
// Normalize normalizes the vector. Normalization is (1/|v|)*v,
|
||||
// making this equivalent to v.Scale(1/v.Len()). If the len is 0.0,
|
||||
// this function will return an infinite value for all elements due
|
||||
// to how floating point division works in Go (n/0.0 = math.Inf(Sign(n))).
|
||||
//
|
||||
// Normalization makes a vector's Len become 1.0 (within the margin of floating point error),
|
||||
// while maintaining its directionality.
|
||||
//
|
||||
// (Can be seen here: http://play.golang.org/p/Aaj7SnbqIp )
|
||||
func (v1 Vec2) Normalize() Vec2 {
|
||||
l := 1.0 / v1.Len()
|
||||
return Vec2{v1[0] * l, v1[1] * l}
|
||||
}
|
||||
|
||||
// ApproxEqual takes in a vector and does an element-wise
|
||||
// approximate float comparison as if FloatEqual had been used
|
||||
func (v1 Vec2) ApproxEqual(v2 Vec2) bool {
|
||||
for i := range v1 {
|
||||
if !FloatEqual(v1[i], v2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ApproxThresholdEq takes in a threshold for comparing two floats, and uses it to do an
|
||||
// element-wise comparison of the vector to another.
|
||||
func (v1 Vec2) ApproxEqualThreshold(v2 Vec2, threshold float32) bool {
|
||||
for i := range v1 {
|
||||
if !FloatEqualThreshold(v1[i], v2[i], threshold) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ApproxFuncEq takes in a func that compares two floats, and uses it to do an element-wise
|
||||
// comparison of the vector to another. This is intended to be used with FloatEqualFunc
|
||||
func (v1 Vec2) ApproxFuncEqual(v2 Vec2, eq func(float32, float32) bool) bool {
|
||||
for i := range v1 {
|
||||
if !eq(v1[i], v2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// This is an element access func, it is equivalent to v[n] where
|
||||
// n is some valid index. The mappings are XYZW (X=0, Y=1 etc). Benchmarks
|
||||
// show that this is more or less as fast as direct acces, probably due to
|
||||
// inlining, so use v[0] or v.X() depending on personal preference.
|
||||
func (v Vec2) X() float32 {
|
||||
return v[0]
|
||||
}
|
||||
|
||||
// This is an element access func, it is equivalent to v[n] where
|
||||
// n is some valid index. The mappings are XYZW (X=0, Y=1 etc). Benchmarks
|
||||
// show that this is more or less as fast as direct acces, probably due to
|
||||
// inlining, so use v[0] or v.X() depending on personal preference.
|
||||
func (v Vec2) Y() float32 {
|
||||
return v[1]
|
||||
}
|
||||
|
||||
// Does the vector outer product
|
||||
// of two vectors. The outer product produces an
|
||||
// 2x2 matrix. E.G. a Vec2 * Vec2 = Mat2.
|
||||
//
|
||||
// The outer product can be thought of as the "opposite"
|
||||
// of the Dot product. The Dot product treats both vectors like matrices
|
||||
// oriented such that the left one has N columns and the right has N rows.
|
||||
// So Vec3.Vec3 = Mat1x3*Mat3x1 = Mat1 = Scalar.
|
||||
//
|
||||
// The outer product orients it so they're facing "outward": Vec2*Vec3
|
||||
// = Mat2x1*Mat1x3 = Mat2x3.
|
||||
func (v1 Vec2) OuterProd2(v2 Vec2) Mat2 {
|
||||
return Mat2{v1[0] * v2[0], v1[1] * v2[0], v1[0] * v2[1], v1[1] * v2[1]}
|
||||
}
|
||||
|
||||
// Does the vector outer product
|
||||
// of two vectors. The outer product produces an
|
||||
// 2x3 matrix. E.G. a Vec2 * Vec3 = Mat2x3.
|
||||
//
|
||||
// The outer product can be thought of as the "opposite"
|
||||
// of the Dot product. The Dot product treats both vectors like matrices
|
||||
// oriented such that the left one has N columns and the right has N rows.
|
||||
// So Vec3.Vec3 = Mat1x3*Mat3x1 = Mat1 = Scalar.
|
||||
//
|
||||
// The outer product orients it so they're facing "outward": Vec2*Vec3
|
||||
// = Mat2x1*Mat1x3 = Mat2x3.
|
||||
func (v1 Vec2) OuterProd3(v2 Vec3) Mat2x3 {
|
||||
return Mat2x3{v1[0] * v2[0], v1[1] * v2[0], v1[0] * v2[1], v1[1] * v2[1], v1[0] * v2[2], v1[1] * v2[2]}
|
||||
}
|
||||
|
||||
// Does the vector outer product
|
||||
// of two vectors. The outer product produces an
|
||||
// 2x4 matrix. E.G. a Vec2 * Vec4 = Mat2x4.
|
||||
//
|
||||
// The outer product can be thought of as the "opposite"
|
||||
// of the Dot product. The Dot product treats both vectors like matrices
|
||||
// oriented such that the left one has N columns and the right has N rows.
|
||||
// So Vec3.Vec3 = Mat1x3*Mat3x1 = Mat1 = Scalar.
|
||||
//
|
||||
// The outer product orients it so they're facing "outward": Vec2*Vec3
|
||||
// = Mat2x1*Mat1x3 = Mat2x3.
|
||||
func (v1 Vec2) OuterProd4(v2 Vec4) Mat2x4 {
|
||||
return Mat2x4{v1[0] * v2[0], v1[1] * v2[0], v1[0] * v2[1], v1[1] * v2[1], v1[0] * v2[2], v1[1] * v2[2], v1[0] * v2[3], v1[1] * v2[3]}
|
||||
}
|
||||
|
||||
// Add performs element-wise addition between two vectors. It is equivalent to iterating
|
||||
// over every element of v1 and adding the corresponding element of v2 to it.
|
||||
func (v1 Vec3) Add(v2 Vec3) Vec3 {
|
||||
return Vec3{v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]}
|
||||
}
|
||||
|
||||
// Sub performs element-wise subtraction between two vectors. It is equivalent to iterating
|
||||
// over every element of v1 and subtracting the corresponding element of v2 from it.
|
||||
func (v1 Vec3) Sub(v2 Vec3) Vec3 {
|
||||
return Vec3{v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]}
|
||||
}
|
||||
|
||||
// Mul performs a scalar multiplication between the vector and some constant value
|
||||
// c. This is equivalent to iterating over every vector element and multiplying by c.
|
||||
func (v1 Vec3) Mul(c float32) Vec3 {
|
||||
return Vec3{v1[0] * c, v1[1] * c, v1[2] * c}
|
||||
}
|
||||
|
||||
// Dot returns the dot product of this vector with another. There are multiple ways
|
||||
// to describe this value. One is the multiplication of their lengths and cos(theta) where
|
||||
// theta is the angle between the vectors: v1.v2 = |v1||v2|cos(theta).
|
||||
//
|
||||
// The other (and what is actually done) is the sum of the element-wise multiplication of all
|
||||
// elements. So for instance, two Vec3s would yield v1.x * v2.x + v1.y * v2.y + v1.z * v2.z.
|
||||
//
|
||||
// This means that the dot product of a vector and itself is the square of its Len (within
|
||||
// the bounds of floating points error).
|
||||
//
|
||||
// The dot product is roughly a measure of how closely two vectors are to pointing in the same
|
||||
// direction. If both vectors are normalized, the value will be -1 for opposite pointing,
|
||||
// one for same pointing, and 0 for perpendicular vectors.
|
||||
func (v1 Vec3) Dot(v2 Vec3) float32 {
|
||||
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]
|
||||
}
|
||||
|
||||
// Len returns the vector's length. Note that this is NOT the dimension of
|
||||
// the vector (len(v)), but the mathematical length. This is equivalent to the square
|
||||
// root of the sum of the squares of all elements. E.G. for a Vec2 it's
|
||||
// math.Hypot(v[0], v[1]).
|
||||
func (v1 Vec3) Len() float32 {
|
||||
|
||||
return float32(math.Sqrt(float64(v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2])))
|
||||
|
||||
}
|
||||
|
||||
// Normalize normalizes the vector. Normalization is (1/|v|)*v,
|
||||
// making this equivalent to v.Scale(1/v.Len()). If the len is 0.0,
|
||||
// this function will return an infinite value for all elements due
|
||||
// to how floating point division works in Go (n/0.0 = math.Inf(Sign(n))).
|
||||
//
|
||||
// Normalization makes a vector's Len become 1.0 (within the margin of floating point error),
|
||||
// while maintaining its directionality.
|
||||
//
|
||||
// (Can be seen here: http://play.golang.org/p/Aaj7SnbqIp )
|
||||
func (v1 Vec3) Normalize() Vec3 {
|
||||
l := 1.0 / v1.Len()
|
||||
return Vec3{v1[0] * l, v1[1] * l, v1[2] * l}
|
||||
}
|
||||
|
||||
// ApproxEqual takes in a vector and does an element-wise
|
||||
// approximate float comparison as if FloatEqual had been used
|
||||
func (v1 Vec3) ApproxEqual(v2 Vec3) bool {
|
||||
for i := range v1 {
|
||||
if !FloatEqual(v1[i], v2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ApproxThresholdEq takes in a threshold for comparing two floats, and uses it to do an
|
||||
// element-wise comparison of the vector to another.
|
||||
func (v1 Vec3) ApproxEqualThreshold(v2 Vec3, threshold float32) bool {
|
||||
for i := range v1 {
|
||||
if !FloatEqualThreshold(v1[i], v2[i], threshold) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ApproxFuncEq takes in a func that compares two floats, and uses it to do an element-wise
|
||||
// comparison of the vector to another. This is intended to be used with FloatEqualFunc
|
||||
func (v1 Vec3) ApproxFuncEqual(v2 Vec3, eq func(float32, float32) bool) bool {
|
||||
for i := range v1 {
|
||||
if !eq(v1[i], v2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// This is an element access func, it is equivalent to v[n] where
|
||||
// n is some valid index. The mappings are XYZW (X=0, Y=1 etc). Benchmarks
|
||||
// show that this is more or less as fast as direct acces, probably due to
|
||||
// inlining, so use v[0] or v.X() depending on personal preference.
|
||||
func (v Vec3) X() float32 {
|
||||
return v[0]
|
||||
}
|
||||
|
||||
// This is an element access func, it is equivalent to v[n] where
|
||||
// n is some valid index. The mappings are XYZW (X=0, Y=1 etc). Benchmarks
|
||||
// show that this is more or less as fast as direct acces, probably due to
|
||||
// inlining, so use v[0] or v.X() depending on personal preference.
|
||||
func (v Vec3) Y() float32 {
|
||||
return v[1]
|
||||
}
|
||||
|
||||
// This is an element access func, it is equivalent to v[n] where
|
||||
// n is some valid index. The mappings are XYZW (X=0, Y=1 etc). Benchmarks
|
||||
// show that this is more or less as fast as direct acces, probably due to
|
||||
// inlining, so use v[0] or v.X() depending on personal preference.
|
||||
func (v Vec3) Z() float32 {
|
||||
return v[2]
|
||||
}
|
||||
|
||||
// Does the vector outer product
|
||||
// of two vectors. The outer product produces an
|
||||
// 3x2 matrix. E.G. a Vec3 * Vec2 = Mat3x2.
|
||||
//
|
||||
// The outer product can be thought of as the "opposite"
|
||||
// of the Dot product. The Dot product treats both vectors like matrices
|
||||
// oriented such that the left one has N columns and the right has N rows.
|
||||
// So Vec3.Vec3 = Mat1x3*Mat3x1 = Mat1 = Scalar.
|
||||
//
|
||||
// The outer product orients it so they're facing "outward": Vec2*Vec3
|
||||
// = Mat2x1*Mat1x3 = Mat2x3.
|
||||
func (v1 Vec3) OuterProd2(v2 Vec2) Mat3x2 {
|
||||
return Mat3x2{v1[0] * v2[0], v1[1] * v2[0], v1[2] * v2[0], v1[0] * v2[1], v1[1] * v2[1], v1[2] * v2[1]}
|
||||
}
|
||||
|
||||
// Does the vector outer product
|
||||
// of two vectors. The outer product produces an
|
||||
// 3x3 matrix. E.G. a Vec3 * Vec3 = Mat3.
|
||||
//
|
||||
// The outer product can be thought of as the "opposite"
|
||||
// of the Dot product. The Dot product treats both vectors like matrices
|
||||
// oriented such that the left one has N columns and the right has N rows.
|
||||
// So Vec3.Vec3 = Mat1x3*Mat3x1 = Mat1 = Scalar.
|
||||
//
|
||||
// The outer product orients it so they're facing "outward": Vec2*Vec3
|
||||
// = Mat2x1*Mat1x3 = Mat2x3.
|
||||
func (v1 Vec3) OuterProd3(v2 Vec3) Mat3 {
|
||||
return Mat3{v1[0] * v2[0], v1[1] * v2[0], v1[2] * v2[0], v1[0] * v2[1], v1[1] * v2[1], v1[2] * v2[1], v1[0] * v2[2], v1[1] * v2[2], v1[2] * v2[2]}
|
||||
}
|
||||
|
||||
// Does the vector outer product
|
||||
// of two vectors. The outer product produces an
|
||||
// 3x4 matrix. E.G. a Vec3 * Vec4 = Mat3x4.
|
||||
//
|
||||
// The outer product can be thought of as the "opposite"
|
||||
// of the Dot product. The Dot product treats both vectors like matrices
|
||||
// oriented such that the left one has N columns and the right has N rows.
|
||||
// So Vec3.Vec3 = Mat1x3*Mat3x1 = Mat1 = Scalar.
|
||||
//
|
||||
// The outer product orients it so they're facing "outward": Vec2*Vec3
|
||||
// = Mat2x1*Mat1x3 = Mat2x3.
|
||||
func (v1 Vec3) OuterProd4(v2 Vec4) Mat3x4 {
|
||||
return Mat3x4{v1[0] * v2[0], v1[1] * v2[0], v1[2] * v2[0], v1[0] * v2[1], v1[1] * v2[1], v1[2] * v2[1], v1[0] * v2[2], v1[1] * v2[2], v1[2] * v2[2], v1[0] * v2[3], v1[1] * v2[3], v1[2] * v2[3]}
|
||||
}
|
||||
|
||||
// Add performs element-wise addition between two vectors. It is equivalent to iterating
|
||||
// over every element of v1 and adding the corresponding element of v2 to it.
|
||||
func (v1 Vec4) Add(v2 Vec4) Vec4 {
|
||||
return Vec4{v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2], v1[3] + v2[3]}
|
||||
}
|
||||
|
||||
// Sub performs element-wise subtraction between two vectors. It is equivalent to iterating
|
||||
// over every element of v1 and subtracting the corresponding element of v2 from it.
|
||||
func (v1 Vec4) Sub(v2 Vec4) Vec4 {
|
||||
return Vec4{v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2], v1[3] - v2[3]}
|
||||
}
|
||||
|
||||
// Mul performs a scalar multiplication between the vector and some constant value
|
||||
// c. This is equivalent to iterating over every vector element and multiplying by c.
|
||||
func (v1 Vec4) Mul(c float32) Vec4 {
|
||||
return Vec4{v1[0] * c, v1[1] * c, v1[2] * c, v1[3] * c}
|
||||
}
|
||||
|
||||
// Dot returns the dot product of this vector with another. There are multiple ways
|
||||
// to describe this value. One is the multiplication of their lengths and cos(theta) where
|
||||
// theta is the angle between the vectors: v1.v2 = |v1||v2|cos(theta).
|
||||
//
|
||||
// The other (and what is actually done) is the sum of the element-wise multiplication of all
|
||||
// elements. So for instance, two Vec3s would yield v1.x * v2.x + v1.y * v2.y + v1.z * v2.z.
|
||||
//
|
||||
// This means that the dot product of a vector and itself is the square of its Len (within
|
||||
// the bounds of floating points error).
|
||||
//
|
||||
// The dot product is roughly a measure of how closely two vectors are to pointing in the same
|
||||
// direction. If both vectors are normalized, the value will be -1 for opposite pointing,
|
||||
// one for same pointing, and 0 for perpendicular vectors.
|
||||
func (v1 Vec4) Dot(v2 Vec4) float32 {
|
||||
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2] + v1[3]*v2[3]
|
||||
}
|
||||
|
||||
// Len returns the vector's length. Note that this is NOT the dimension of
|
||||
// the vector (len(v)), but the mathematical length. This is equivalent to the square
|
||||
// root of the sum of the squares of all elements. E.G. for a Vec2 it's
|
||||
// math.Hypot(v[0], v[1]).
|
||||
func (v1 Vec4) Len() float32 {
|
||||
|
||||
return float32(math.Sqrt(float64(v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2] + v1[3]*v1[3])))
|
||||
|
||||
}
|
||||
|
||||
// Normalize normalizes the vector. Normalization is (1/|v|)*v,
|
||||
// making this equivalent to v.Scale(1/v.Len()). If the len is 0.0,
|
||||
// this function will return an infinite value for all elements due
|
||||
// to how floating point division works in Go (n/0.0 = math.Inf(Sign(n))).
|
||||
//
|
||||
// Normalization makes a vector's Len become 1.0 (within the margin of floating point error),
|
||||
// while maintaining its directionality.
|
||||
//
|
||||
// (Can be seen here: http://play.golang.org/p/Aaj7SnbqIp )
|
||||
func (v1 Vec4) Normalize() Vec4 {
|
||||
l := 1.0 / v1.Len()
|
||||
return Vec4{v1[0] * l, v1[1] * l, v1[2] * l, v1[3] * l}
|
||||
}
|
||||
|
||||
// ApproxEqual takes in a vector and does an element-wise
|
||||
// approximate float comparison as if FloatEqual had been used
|
||||
func (v1 Vec4) ApproxEqual(v2 Vec4) bool {
|
||||
for i := range v1 {
|
||||
if !FloatEqual(v1[i], v2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ApproxThresholdEq takes in a threshold for comparing two floats, and uses it to do an
|
||||
// element-wise comparison of the vector to another.
|
||||
func (v1 Vec4) ApproxEqualThreshold(v2 Vec4, threshold float32) bool {
|
||||
for i := range v1 {
|
||||
if !FloatEqualThreshold(v1[i], v2[i], threshold) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ApproxFuncEq takes in a func that compares two floats, and uses it to do an element-wise
|
||||
// comparison of the vector to another. This is intended to be used with FloatEqualFunc
|
||||
func (v1 Vec4) ApproxFuncEqual(v2 Vec4, eq func(float32, float32) bool) bool {
|
||||
for i := range v1 {
|
||||
if !eq(v1[i], v2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// This is an element access func, it is equivalent to v[n] where
|
||||
// n is some valid index. The mappings are XYZW (X=0, Y=1 etc). Benchmarks
|
||||
// show that this is more or less as fast as direct acces, probably due to
|
||||
// inlining, so use v[0] or v.X() depending on personal preference.
|
||||
func (v Vec4) X() float32 {
|
||||
return v[0]
|
||||
}
|
||||
|
||||
// This is an element access func, it is equivalent to v[n] where
|
||||
// n is some valid index. The mappings are XYZW (X=0, Y=1 etc). Benchmarks
|
||||
// show that this is more or less as fast as direct acces, probably due to
|
||||
// inlining, so use v[0] or v.X() depending on personal preference.
|
||||
func (v Vec4) Y() float32 {
|
||||
return v[1]
|
||||
}
|
||||
|
||||
// This is an element access func, it is equivalent to v[n] where
|
||||
// n is some valid index. The mappings are XYZW (X=0, Y=1 etc). Benchmarks
|
||||
// show that this is more or less as fast as direct acces, probably due to
|
||||
// inlining, so use v[0] or v.X() depending on personal preference.
|
||||
func (v Vec4) Z() float32 {
|
||||
return v[2]
|
||||
}
|
||||
|
||||
// This is an element access func, it is equivalent to v[n] where
|
||||
// n is some valid index. The mappings are XYZW (X=0, Y=1 etc). Benchmarks
|
||||
// show that this is more or less as fast as direct acces, probably due to
|
||||
// inlining, so use v[0] or v.X() depending on personal preference.
|
||||
func (v Vec4) W() float32 {
|
||||
return v[3]
|
||||
}
|
||||
|
||||
// Does the vector outer product
|
||||
// of two vectors. The outer product produces an
|
||||
// 4x2 matrix. E.G. a Vec4 * Vec2 = Mat4x2.
|
||||
//
|
||||
// The outer product can be thought of as the "opposite"
|
||||
// of the Dot product. The Dot product treats both vectors like matrices
|
||||
// oriented such that the left one has N columns and the right has N rows.
|
||||
// So Vec3.Vec3 = Mat1x3*Mat3x1 = Mat1 = Scalar.
|
||||
//
|
||||
// The outer product orients it so they're facing "outward": Vec2*Vec3
|
||||
// = Mat2x1*Mat1x3 = Mat2x3.
|
||||
func (v1 Vec4) OuterProd2(v2 Vec2) Mat4x2 {
|
||||
return Mat4x2{v1[0] * v2[0], v1[1] * v2[0], v1[2] * v2[0], v1[3] * v2[0], v1[0] * v2[1], v1[1] * v2[1], v1[2] * v2[1], v1[3] * v2[1]}
|
||||
}
|
||||
|
||||
// Does the vector outer product
|
||||
// of two vectors. The outer product produces an
|
||||
// 4x3 matrix. E.G. a Vec4 * Vec3 = Mat4x3.
|
||||
//
|
||||
// The outer product can be thought of as the "opposite"
|
||||
// of the Dot product. The Dot product treats both vectors like matrices
|
||||
// oriented such that the left one has N columns and the right has N rows.
|
||||
// So Vec3.Vec3 = Mat1x3*Mat3x1 = Mat1 = Scalar.
|
||||
//
|
||||
// The outer product orients it so they're facing "outward": Vec2*Vec3
|
||||
// = Mat2x1*Mat1x3 = Mat2x3.
|
||||
func (v1 Vec4) OuterProd3(v2 Vec3) Mat4x3 {
|
||||
return Mat4x3{v1[0] * v2[0], v1[1] * v2[0], v1[2] * v2[0], v1[3] * v2[0], v1[0] * v2[1], v1[1] * v2[1], v1[2] * v2[1], v1[3] * v2[1], v1[0] * v2[2], v1[1] * v2[2], v1[2] * v2[2], v1[3] * v2[2]}
|
||||
}
|
||||
|
||||
// Does the vector outer product
|
||||
// of two vectors. The outer product produces an
|
||||
// 4x4 matrix. E.G. a Vec4 * Vec4 = Mat4.
|
||||
//
|
||||
// The outer product can be thought of as the "opposite"
|
||||
// of the Dot product. The Dot product treats both vectors like matrices
|
||||
// oriented such that the left one has N columns and the right has N rows.
|
||||
// So Vec3.Vec3 = Mat1x3*Mat3x1 = Mat1 = Scalar.
|
||||
//
|
||||
// The outer product orients it so they're facing "outward": Vec2*Vec3
|
||||
// = Mat2x1*Mat1x3 = Mat2x3.
|
||||
func (v1 Vec4) OuterProd4(v2 Vec4) Mat4 {
|
||||
return Mat4{v1[0] * v2[0], v1[1] * v2[0], v1[2] * v2[0], v1[3] * v2[0], v1[0] * v2[1], v1[1] * v2[1], v1[2] * v2[1], v1[3] * v2[1], v1[0] * v2[2], v1[1] * v2[2], v1[2] * v2[2], v1[3] * v2[2], v1[0] * v2[3], v1[1] * v2[3], v1[2] * v2[3], v1[3] * v2[3]}
|
||||
}
|
207
vendor/github.com/go-gl/mathgl/mgl32/vector.tmpl
generated
vendored
Normal file
207
vendor/github.com/go-gl/mathgl/mgl32/vector.tmpl
generated
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
// Copyright 2014 The go-gl/mathgl Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// <<.Comment>>
|
||||
// Edit <<.TemplateName>> and run "go generate" to make changes.
|
||||
|
||||
package mgl32
|
||||
|
||||
import (
|
||||
"golang.org/x/image/math/f32"
|
||||
"math"
|
||||
)
|
||||
|
||||
type Vec2 f32.Vec2
|
||||
type Vec3 f32.Vec3
|
||||
type Vec4 f32.Vec4
|
||||
|
||||
func (v Vec2) Vec3(z float32) Vec3 {
|
||||
return Vec3{v[0], v[1], z}
|
||||
}
|
||||
|
||||
func (v Vec2) Vec4(z, w float32) Vec4 {
|
||||
return Vec4{v[0], v[1], z, w}
|
||||
}
|
||||
|
||||
func (v Vec3) Vec2() Vec2 {
|
||||
return Vec2{v[0], v[1]}
|
||||
}
|
||||
|
||||
func (v Vec3) Vec4(w float32) Vec4 {
|
||||
return Vec4{v[0], v[1], v[2], w}
|
||||
}
|
||||
|
||||
func (v Vec4) Vec2() Vec2 {
|
||||
return Vec2{v[0], v[1]}
|
||||
}
|
||||
|
||||
func (v Vec4) Vec3() Vec3 {
|
||||
return Vec3{v[0], v[1], v[2]}
|
||||
}
|
||||
|
||||
// Elem extracts the elements of the vector for direct value assignment.
|
||||
func (v Vec2) Elem() (x, y float32) {
|
||||
return v[0], v[1]
|
||||
}
|
||||
|
||||
// Elem extracts the elements of the vector for direct value assignment.
|
||||
func (v Vec3) Elem() (x, y, z float32) {
|
||||
return v[0], v[1], v[2]
|
||||
}
|
||||
|
||||
// Elem extracts the elements of the vector for direct value assignment.
|
||||
func (v Vec4) Elem() (x, y, z, w float32) {
|
||||
return v[0], v[1], v[2], v[3]
|
||||
}
|
||||
|
||||
// The vector cross product is an operation only defined on 3D vectors. It is equivalent to
|
||||
// Vec3{v1[1]*v2[2]-v1[2]*v2[1], v1[2]*v2[0]-v1[0]*v2[2], v1[0]*v2[1] - v1[1]*v2[0]}.
|
||||
// Another interpretation is that it's the vector whose magnitude is |v1||v2|sin(theta)
|
||||
// where theta is the angle between v1 and v2.
|
||||
//
|
||||
// The cross product is most often used for finding surface normals. The cross product of vectors
|
||||
// will generate a vector that is perpendicular to the plane they form.
|
||||
//
|
||||
// Technically, a generalized cross product exists as an "(N-1)ary" operation
|
||||
// (that is, the 4D cross product requires 3 4D vectors). But the binary
|
||||
// 3D (and 7D) cross product is the most important. It can be considered
|
||||
// the area of a parallelogram with sides v1 and v2.
|
||||
//
|
||||
// Like the dot product, the cross product is roughly a measure of directionality.
|
||||
// Two normalized perpendicular vectors will return a vector with a magnitude of
|
||||
// 1.0 or -1.0 and two parallel vectors will return a vector with magnitude 0.0.
|
||||
// The cross product is "anticommutative" meaning v1.Cross(v2) = -v2.Cross(v1),
|
||||
// this property can be useful to know when finding normals,
|
||||
// as taking the wrong cross product can lead to the opposite normal of the one you want.
|
||||
func (v1 Vec3) Cross(v2 Vec3) Vec3 {
|
||||
return Vec3{v1[1]*v2[2] - v1[2]*v2[1], v1[2]*v2[0] - v1[0]*v2[2], v1[0]*v2[1] - v1[1]*v2[0]}
|
||||
}
|
||||
|
||||
|
||||
<</* Common functions for all vectors */>>
|
||||
<<range $m := enum 2 3 4>>
|
||||
<<$type := typename $m 1>>
|
||||
|
||||
// Add performs element-wise addition between two vectors. It is equivalent to iterating
|
||||
// over every element of v1 and adding the corresponding element of v2 to it.
|
||||
func (v1 <<$type>>) Add(v2 <<$type>>) <<$type>> {
|
||||
return <<$type>>{<<range $i := iter 0 $m>> v1[<<$i>>] + v2[<<$i>>], <<end>>}
|
||||
}
|
||||
|
||||
// Sub performs element-wise subtraction between two vectors. It is equivalent to iterating
|
||||
// over every element of v1 and subtracting the corresponding element of v2 from it.
|
||||
func (v1 <<$type>>) Sub(v2 <<$type>>) <<$type>> {
|
||||
return <<$type>>{<<range $i := iter 0 $m>> v1[<<$i>>] - v2[<<$i>>], <<end>>}
|
||||
}
|
||||
|
||||
// Mul performs a scalar multiplication between the vector and some constant value
|
||||
// c. This is equivalent to iterating over every vector element and multiplying by c.
|
||||
func (v1 <<$type>>) Mul(c float32) <<$type>> {
|
||||
return <<$type>>{<<range $i := iter 0 $m>> v1[<<$i>>] * c, <<end>>}
|
||||
}
|
||||
|
||||
// Dot returns the dot product of this vector with another. There are multiple ways
|
||||
// to describe this value. One is the multiplication of their lengths and cos(theta) where
|
||||
// theta is the angle between the vectors: v1.v2 = |v1||v2|cos(theta).
|
||||
//
|
||||
// The other (and what is actually done) is the sum of the element-wise multiplication of all
|
||||
// elements. So for instance, two Vec3s would yield v1.x * v2.x + v1.y * v2.y + v1.z * v2.z.
|
||||
//
|
||||
// This means that the dot product of a vector and itself is the square of its Len (within
|
||||
// the bounds of floating points error).
|
||||
//
|
||||
// The dot product is roughly a measure of how closely two vectors are to pointing in the same
|
||||
// direction. If both vectors are normalized, the value will be -1 for opposite pointing,
|
||||
// one for same pointing, and 0 for perpendicular vectors.
|
||||
func (v1 <<$type>>) Dot(v2 <<$type>>) float32 {
|
||||
return <<range $i := iter 0 $m>><<sep "+" $i>> v1[<<$i>>]*v2[<<$i>>] <<end>>
|
||||
}
|
||||
|
||||
// Len returns the vector's length. Note that this is NOT the dimension of
|
||||
// the vector (len(v)), but the mathematical length. This is equivalent to the square
|
||||
// root of the sum of the squares of all elements. E.G. for a Vec2 it's
|
||||
// math.Hypot(v[0], v[1]).
|
||||
func (v1 <<$type>>) Len() float32 {
|
||||
<<if eq $m 2 >>
|
||||
return float32(math.Hypot(float64(v1[0]), float64(v1[1])))
|
||||
<<else>>
|
||||
return float32(math.Sqrt(float64(<<repeat $m "v1[%d]*v1[%d]" "+">>)))
|
||||
<<end>>
|
||||
}
|
||||
|
||||
// Normalize normalizes the vector. Normalization is (1/|v|)*v,
|
||||
// making this equivalent to v.Scale(1/v.Len()). If the len is 0.0,
|
||||
// this function will return an infinite value for all elements due
|
||||
// to how floating point division works in Go (n/0.0 = math.Inf(Sign(n))).
|
||||
//
|
||||
// Normalization makes a vector's Len become 1.0 (within the margin of floating point error),
|
||||
// while maintaining its directionality.
|
||||
//
|
||||
// (Can be seen here: http://play.golang.org/p/Aaj7SnbqIp )
|
||||
func (v1 <<$type>>) Normalize() <<$type>> {
|
||||
l := 1.0 / v1.Len()
|
||||
return <<$type>>{<<range $i := iter 0 $m>>v1[<<$i>>] * l,<<end>>}
|
||||
}
|
||||
|
||||
// ApproxEqual takes in a vector and does an element-wise
|
||||
// approximate float comparison as if FloatEqual had been used
|
||||
func (v1 <<$type>>) ApproxEqual(v2 <<$type>>) bool {
|
||||
for i := range v1 {
|
||||
if !FloatEqual(v1[i], v2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ApproxThresholdEq takes in a threshold for comparing two floats, and uses it to do an
|
||||
// element-wise comparison of the vector to another.
|
||||
func (v1 <<$type>>) ApproxEqualThreshold(v2 <<$type>>, threshold float32) bool {
|
||||
for i := range v1 {
|
||||
if !FloatEqualThreshold(v1[i], v2[i], threshold) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ApproxFuncEq takes in a func that compares two floats, and uses it to do an element-wise
|
||||
// comparison of the vector to another. This is intended to be used with FloatEqualFunc
|
||||
func (v1 <<$type>>) ApproxFuncEqual(v2 <<$type>>, eq func(float32, float32) bool) bool {
|
||||
for i := range v1 {
|
||||
if !eq(v1[i], v2[i]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
<<range $i := iter 0 $m>>
|
||||
// This is an element access func, it is equivalent to v[n] where
|
||||
// n is some valid index. The mappings are XYZW (X=0, Y=1 etc). Benchmarks
|
||||
// show that this is more or less as fast as direct acces, probably due to
|
||||
// inlining, so use v[0] or v.X() depending on personal preference.
|
||||
func (v <<$type>>) <<elementname $i>>() float32 {
|
||||
return v[<<$i>>]
|
||||
}
|
||||
<<end>>
|
||||
|
||||
<<range $n := enum 2 3 4>>
|
||||
// Does the vector outer product
|
||||
// of two vectors. The outer product produces an
|
||||
// <<$m>>x<<$n>> matrix. E.G. a Vec<<$m>> * Vec<<$n>> = <<typename $m $n>>.
|
||||
//
|
||||
// The outer product can be thought of as the "opposite"
|
||||
// of the Dot product. The Dot product treats both vectors like matrices
|
||||
// oriented such that the left one has N columns and the right has N rows.
|
||||
// So Vec3.Vec3 = Mat1x3*Mat3x1 = Mat1 = Scalar.
|
||||
//
|
||||
// The outer product orients it so they're facing "outward": Vec2*Vec3
|
||||
// = Mat2x1*Mat1x3 = Mat2x3.
|
||||
func (v1 <<$type>>) OuterProd<<$n>>(v2 <<typename $n 1>>) <<typename $m $n>> {
|
||||
return <<typename $m $n>>{<<range $i := matiter $m $n>>v1[<<$i.M>>] * v2[<<$i.N>>], <<end>>}
|
||||
}
|
||||
<<end>>
|
||||
|
||||
<<end>> <</* range $m */>>
|
Reference in New Issue
Block a user