├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── doc ├── Makefile ├── boxes.adoc ├── colony.css ├── complex.adoc ├── datahandling.adoc ├── hostmem.adoc ├── index.adoc ├── index.html ├── introduction.adoc ├── matrices.adoc ├── powered-by-lua.gif ├── preface.adoc ├── quaternions.adoc ├── rects.adoc ├── tracing.adoc ├── transforms.adoc ├── vectors.adoc └── viewing.adoc ├── examples ├── interactive.lua ├── matrices.lua ├── moonglmath.sh ├── quaternions.lua ├── vectors.lua └── versions.lua ├── moonglmath ├── boxsugar.lua ├── complexsugar.lua ├── matsugar.lua ├── quatsugar.lua ├── rectsugar.lua ├── utils.lua └── vecsugar.lua ├── src ├── Makefile ├── _make ├── box.c ├── compat-5.3.c ├── compat-5.3.h ├── complex.c ├── datahandling.c ├── enums.c ├── enums.h ├── funcs.c ├── hostmem.c ├── internal.h ├── main.c ├── mat.c ├── moonglmath.h ├── moonglmath_local.h ├── num.c ├── objects.c ├── objects.h ├── quat.c ├── rect.c ├── tracing.c ├── transform.c ├── tree.h ├── udata.c ├── udata.h ├── utils.c ├── vec.c └── viewing.c └── thirdparty ├── asciidoctor-styles-license ├── lua-compat-5.3-license ├── openbsd-tree-license └── powered-by-lua-license /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.dll 3 | *.so 4 | *.o 5 | *.swp 6 | *.symbols 7 | core.* 8 | local/ 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Stefano Trettel 4 | 5 | Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | 25 | 26 | (See also the THIRD-PARTY LICENSES contained in the thirdparty/ directory 27 | of the Software repository.) 28 | 29 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | default: build 3 | 4 | build install uninstall where: 5 | @cd src; $(MAKE) $@ 6 | 7 | clean : 8 | @cd src; $(MAKE) $@ 9 | @cd doc; $(MAKE) $@ 10 | 11 | docs: 12 | @cd doc; $(MAKE) 13 | 14 | cleanall: clean 15 | 16 | backup: clean 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## MoonGLMATH: Math library for MoonGL 2 | 3 | MoonGLMATH is a Lua math library for [MoonGL](https://github.com/stetre/moongl). 4 | 5 | It runs on GNU/Linux and on Windows (MSYS2/MinGW-w64) and requires [Lua](http://www.lua.org/) (>=5.3). 6 | 7 | _Authored by:_ _[Stefano Trettel](https://www.linkedin.com/in/stetre)_ 8 | 9 | [![Lua logo](./doc/powered-by-lua.gif)](http://www.lua.org/) 10 | 11 | #### License 12 | 13 | MIT/X11 license (same as Lua). See [LICENSE](./LICENSE). 14 | 15 | #### Documentation 16 | 17 | See the [Reference Manual](https://stetre.github.io/moonglmath/doc/index.html). 18 | 19 | #### Getting and installing 20 | 21 | Setup the build environment as described [here](https://github.com/stetre/moonlibs), then: 22 | 23 | ```sh 24 | $ git clone https://github.com/stetre/moonglmath 25 | $ cd moonglmath 26 | moonglmath$ make 27 | moonglmath$ make install # or 'sudo make install' (Ubuntu) 28 | ``` 29 | 30 | #### Example 31 | 32 | The example below creates a few vectors and matrices and performs some operations 33 | on them, just to give a taste of MoonGLMATH. 34 | 35 | Other examples can be found in the **examples/** directory contained in the release package. 36 | 37 | ```lua 38 | -- Script: hello.lua 39 | 40 | glmath = require("moonglmath") 41 | 42 | -- create a few size-3 vectors and 3x3 matrices: 43 | u = glmath.vec3(2.3, 1.5, math.pi) 44 | v = glmath.vec3(1, 2, 3) 45 | A = glmath.mat3(3, 1, 5, 2, 8, 7, 9, 4, 6) 46 | I = glmath.mat3() -- identity 47 | 48 | s = u * v -- dot product 49 | w = u % v -- cross product 50 | s = A:det() -- determinant 51 | B = A^-1 -- matrix inverse 52 | B = A:inv() -- matrix inverse 53 | A = B * A -- matrix multiplication 54 | I = A^-1 * A -- matrix multiplication 55 | w = A * v -- matrix*vector 56 | 57 | print(u[1], u[2], u[3]) -- vector components 58 | print(u.x, u.y, u.z) -- position syntactic sugar 59 | print(u.r, u.g, u.b) -- color syntactic sugar 60 | print(u.s, u.t, u.p) -- texture syntactic sugar 61 | 62 | ``` 63 | 64 | The script can be executed at the shell prompt with the standard Lua interpreter: 65 | 66 | ```shell 67 | $ lua hello.lua 68 | ``` 69 | 70 | #### See also 71 | 72 | * [MoonLibs - Graphics and Audio Lua Libraries](https://github.com/stetre/moonlibs). 73 | 74 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | TgtAdoc := index 2 | TgtPdf := MoonGLMATH-RefMan 3 | 4 | Stylesdir = ./ 5 | Stylesheet = colony.css 6 | Style = -a stylesheet=$(Stylesheet) -a stylesdir=$(Stylesdir) 7 | Style = 8 | 9 | ifdef TgtAdoc 10 | # one file only 11 | Src = $(TgtAdoc).adoc 12 | else 13 | # all .adoc files 14 | Src := $(wildcard *.adoc) 15 | endif 16 | 17 | Xml := $(Src:.adoc=.xml) 18 | Html := $(Src:.adoc=.html) 19 | Pdf := $(Src:.adoc=.pdf) 20 | 21 | default: html 22 | 23 | check: 24 | 25 | clean: 26 | @-rm -f *~ 27 | @-rm -f *.pdf 28 | @-rm -f *.pdfmarks 29 | @-rm -f *.xml 30 | @-rm -f *.html 31 | @-rm -f *.epub 32 | @-rm -f *.fo 33 | @-rm -f *.log 34 | 35 | install: 36 | 37 | html: clean 38 | @asciidoctor $(Style) $(Src) 39 | 40 | preview: html 41 | @google-chrome $(Html) 42 | 43 | ifdef TgtAdoc 44 | # one file only 45 | pdf: clean 46 | @asciidoctor-pdf $(TgtAdoc).adoc -o $(TgtPdf).pdf 47 | else 48 | # all .adoc files 49 | pdf: clean 50 | @asciidoctor-pdf -a pdf-style=asciidoctor $(TgtAdoc).adoc 51 | endif 52 | 53 | docs: html pdf 54 | -------------------------------------------------------------------------------- /doc/boxes.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Boxes 3 | 4 | MoonGLMATH supports 2D and 3D axis-aligned boxes. 5 | 6 | A box *b* is implemented as a table having the field *b.dimensions* (= _2_ or _3_), 7 | and the coordinates of the vertices in the array part, starting from index 1, as follows: 8 | 9 | * _{ minx, maxx, miny, maxy }_ if _v.dimensions_=_2_ (2D box), or 10 | * _{ minx, maxx, miny, maxy, minz, maxz }_ if _v.dimensions_=_3_ (3D box). 11 | 12 | The coordinates are Lua link:++http://www.lua.org/manual/5.3/manual.html#2.1++[number]s 13 | and can be accessed through standard indexing (that is, *b[1]* is _minx_, *b[2]* 14 | is _maxx_, and so on). They can also be accessed using the following syntactic sugar: 15 | *b.minx* is an alias for *b[1]*, *b.maxx* is an alias for *b[2]*, and so on. 16 | 17 | The following constructors can be used to create boxes. 18 | 19 | [[glmath.boxN]] 20 | * _b_ = *box2*(_..._) + 21 | _b_ = *box3*(_..._) + 22 | [small]#Create an axis-aligned box. 23 | The *boxN* function creates a N-dimensional box (where N may be 2 or 3). Values to initialize the box coordinates may be optionally passed as a list of numbers, or as a previously created box (exceeding values are discarded, while missing values are replaced with zeros). No consistency check is performed on the passed coordinates.# 24 | 25 | [[glmath.toboxN]] 26 | * _t_ = *tobox2*(_t_) + 27 | _t_ = *tobox3*(_t_) + 28 | [small]#Turn an appropriately sized table into a box, by adding the relevant meta information to it.# 29 | 30 | .examples 31 | [source,lua] 32 | ---- 33 | b = glmath.box2() --> b = [ 0, 0, 0, 0 ] 34 | b = glmath.box3() --> b = [ 0, 0, 0, 0, 0, 0 ] 35 | b = glmath.box3(-1, 1, -2, 2) --> b = [ -1, 1, -2, 2 ] 36 | ---- 37 | 38 | [[glmath.isboxN]] 39 | * _boolean_ = *isbox2*(_b_) + 40 | _boolean_ = *isbox3*(_b_) + 41 | [small]#Check if _b_ is a box of the given dimensions (e.g. *isbox2* checks if _b_ is a 2D box).# 42 | 43 | //// 44 | 45 | ''' 46 | Boxes have the following functions, also available as methods of their first argument: 47 | 48 | TBD 49 | 50 | ''' 51 | The following *box operators* are supported: 52 | 53 | TBD 54 | 55 | //// 56 | -------------------------------------------------------------------------------- /doc/complex.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Complex numbers 3 | 4 | A complex number *z* = _re_ + i·_im_ (where _i_ is the square root of _-1_) is implemented 5 | as a table holding _re_ and _im_ in its array part (i.e. _{ re, im }_). 6 | 7 | The real and imaginary parts are Lua link:++http://www.lua.org/manual/5.3/manual.html#2.1++[number]s 8 | and can be accessed through standard indexing (that is, *z[1]* is the real part _re_, and *z[2]* is 9 | the imaginary part _im_), or using the *re-im* syntactic sugar (*z.re* and *z.im* are aliases for *z[1]* and *z[2]*, respectively). 10 | 11 | The following constructor can be used to create complex numbers: 12 | 13 | [[glmath.complex]] 14 | * _z_ = *complex*([_re_], [_im_]) + 15 | _z_ = *complex*(_z_) + 16 | _{z~1~, z~2~, ...}_ = *complex*(_{re~1~, im~1~, re~2~, im~2~, ...}_) + 17 | [small]#Create a complex number from its real and imaginary parts (which default to _0_) or from a 18 | previously created complex number _z_.# 19 | 20 | [[glmath.tocomplex]] 21 | * _t_ = *tocomplex*(_t_) + 22 | [small]#Turn an appropriately sized table into a complex number, by adding the relevant meta information to it.# 23 | 24 | .examples 25 | [source,lua] 26 | ---- 27 | z = glmath.complex() --> z = 0 + 0i 28 | z = glmath.complex(2) --> z = 2 + 0i 29 | z = glmath.complex(nil, 5) --> z = 0 + 5i 30 | z = glmath.complex(3, 4) --> z = 3 + 4i 31 | w = glmath.complex(z) --> w = 3 + 4i 32 | t = glmath.complex({1, 2, 3, 4}) --> t[1] = 1 + 2i, t[2] = 3 + 4i 33 | ---- 34 | 35 | [[glmath.iscomplex]] 36 | * _boolean_ = *iscomplex*(_z_) + 37 | [small]#Returns _true_ if _z_ is a complex number or a Lua number, _false_ otherwise.# 38 | 39 | ''' 40 | 41 | The complex functions and operators listed below are based on the C99 functions 42 | for the complex type 43 | (see link:++https://en.wikipedia.org/wiki/C_mathematical_functions#complex.h++[] or _man complex(7)_ for more details). 44 | 45 | Complex functions accept also real numbers (i.e. plain Lua numbers) as arguments, which they understand 46 | as complex numbers with _im=0_. The same holds for binary complex operators, 47 | where one of the two operands can be a real number (if both are, the standard Lua operators for 48 | numbers are obviously used). 49 | 50 | 51 | Complex *functions*, also available as methods for their first argument: 52 | 53 | * _re_ = *creal*(_z_) + 54 | _im_ = *cimag*(_z_) + 55 | _re_, _im_ = *parts*(_z_) + 56 | _|z|_ = *cabs*(_z_) + 57 | _|z|_ = *norm*(_z_) + 58 | _rad_ = *carg*(_z_) + 59 | _|z|^2^_ = *norm2*(_z_) + 60 | _z/|z|_ = *normalize*(_z_) + 61 | _z^pass:[*]^_ = *conj*(_z_) + 62 | _z~1~_ = *cproj*(_z_) + 63 | _z^-1^_ = *inv*(_z_) + 64 | 65 | * _e^z^_ = *cexp*(_z_) + 66 | _ln(z)_ = *clog*(_z_) + 67 | _z^1/2^_ = *csqrt*(_z_) + 68 | _z^w^_ = *cpow*(_z_, _w_) + 69 | 70 | * _z~1~_ = *csin*(_z_) + 71 | _z~1~_ = *ccos*(_z_) + 72 | _z~1~_ = *ctan*(_z_) + 73 | _z~1~_ = *casin*(_z_) + 74 | _z~1~_ = *cacos*(_z_) + 75 | _z~1~_ = *catan*(_z_) + 76 | 77 | * _z~1~_ = *csinh*(_z_) + 78 | _z~1~_ = *ccosh*(_z_) + 79 | _z~1~_ = *ctanh*(_z_) + 80 | _z~1~_ = *casinh*(_z_) + 81 | _z~1~_ = *cacosh*(_z_) + 82 | _z~1~_ = *catanh*(_z_) + 83 | 84 | ''' 85 | 86 | Complex *operators*: 87 | 88 | * *Unary minus*: _z = -z~1~_. 89 | * *Addition*: _z = z~1~ + z~2~_. 90 | * *Subtraction*: _z = z~1~ - z~2~_. 91 | * *Multiplication*: _z = z~1~ * z~2~_. 92 | * *Division*: _z = z~1~ / z~2~_. 93 | * *Power*: _z = z~1~ ^ z~2~_. 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /doc/datahandling.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[datahandling]] 3 | == Data handling 4 | 5 | This section describes additional utilities that can be used to encode data from Lua 6 | variables to binary strings and viceversa. 7 | 8 | [[datahandling_flatten]] 9 | * _val~1~_, _..._, _val~N~_ = *flatten*(_table_) + 10 | [small]#Flattens out the given _table_ and returns the terminal elements in the order they are found. + 11 | Similar to Lua's 12 | http://www.lua.org/manual/5.3/manual.html#pdf-table.unpack[table.unpack]( ), but it also unpacks 13 | any nested table. Only the array part of the table and of nested tables is considered.# 14 | 15 | [[datahandling_flatten_table]] 16 | * {_val~1~_, _..._, _val~N~_} = *flatten_table*(_table_) + 17 | [small]#Same as <>( ), but returns the values in a flat table. 18 | Unlike <>( ), this function can be used also with very large tables.# 19 | 20 | [[datahandling_sizeof]] 21 | * _size_ = *sizeof*(<>) + 22 | [small]#Returns the size in bytes of the given _type_.# 23 | 24 | [[datahandling_pack]] 25 | * _data_ = *pack*(<>, _val~1~_, _..._, _val~N~_) + 26 | _data_ = *pack*(<>, _table_) + 27 | [small]#Packs the numbers _val~1~_, _..._, _val~N~_, encoding them according to the given _type_, and returns the resulting binary string. + 28 | The values may also be passed in a (possibly nested) table. Only the array part of the table (and of nested tables) is considered.# 29 | 30 | [[datahandling_unpack]] 31 | * {_val~1~_, _..._, _val~N~_} = *unpack*(<>, _data_) + 32 | [small]#Unpacks the binary string _data_, interpreting it as a sequence of values of the given _type_, 33 | and returns the extracted values in a flat table. + 34 | The length of _data_ must be a multiple of <>(_type_).# 35 | 36 | [[type]] 37 | [small]#*type*: data types (and their corresponding C99 types) + 38 | Values: '_char_' (int8_t), '_uchar_' (uint8_t), '_short_' (int16_t), '_ushort_' (uint16_t), '_int_' (int32_t), '_uint_' (uint32_t), '_long_' (int64_t), '_ulong_' (uint64_t), '_float_' (float), '_double_' (double).# 39 | 40 | 41 | -------------------------------------------------------------------------------- /doc/hostmem.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[hostmem]] 3 | == Host memory objects 4 | 5 | An *hostmem* object encapsulates a pointer to host accessible memory 6 | footnote:[ 7 | The term 'host' is here used as for the Khronos OpenCL specs, to denote the machine 8 | where the application is running, as opposed to a device such as a GPU. 9 | ], 10 | with methods to access it from Lua and to retrieve pointers to any of its locations in form of 11 | http://www.lua.org/manual/5.3/manual.html#lua_pushlightuserdata[lightuserdata]. 12 | 13 | The memory encapsulated by an hostmem object may be either memory allocated via 14 | the <>( ) or the <>( ) 15 | functions, or memory obtained by other means (e.g. mapped memory or shared virtual memory) 16 | and passed to the <>( ) constructor. 17 | 18 | Hostmem objects are automatically deleted at exit, but they may also be deleted manually 19 | via the <>( ) function (or the corresponding method). 20 | 21 | [[hostmem_malloc]] 22 | * _hostmem_ = *malloc*(_size_) + 23 | _hostmem_ = *malloc*(_data_) + 24 | _hostmem_ = *malloc*(<>, {_value~1~_, _..._, _value~N~_}) + 25 | _hostmem_ = *malloc*(<>, _value~1~_, _..._, _value~N~_) + 26 | [small]#Allocates host memory and creates an _hostmem_ object to encapsulate it. + 27 | *malloc*(_size_), where _size_ is an integer, allocates _size_ bytes of contiguous memory 28 | and initializes them to 0; + 29 | *malloc*(_data_), where _data_ is a binary string, allocates _#data_ bytes of contiguous 30 | memory and initializes them with the contents of _data_; + 31 | *malloc*(_type_, _..._) is functionally equivalent to _malloc(glmath.pack(type, ...))_.# 32 | 33 | [[hostmem_aligned_alloc]] 34 | * _hostmem_ = *aligned_alloc*(_alignment_, _size_) + 35 | _hostmem_ = *aligned_alloc*(_alignment_, _data_) + 36 | _hostmem_ = *aligned_alloc*(_alignment_, <>, {_value~1~_, _..._, _value~N~_}) + 37 | _hostmem_ = *aligned_alloc*(_alignment_, <>, _value~1~_, _..._, _value~N~_) + 38 | [small]#Same as <>( ), with the additional _alignment_ parameter to control 39 | memory address alignment (rfr. _aligned_alloc(3)_).# 40 | 41 | [[hostmem_hostmem]] 42 | * _hostmem_ = *hostmem*(_size_, _ptr_) + 43 | _hostmem_ = *hostmem*(_data_) + 44 | [small]#Creates a _hostmem_ object encapsulating user provided memory. + 45 | Such memory may be provided in form of a lightuserdata (_ptr_) containing a valid pointer to _size_ bytes of contiguous memory, or as a binary string (_data_). + 46 | In both cases, care must be taken that the memory area remains valid until the _hostmem_ object is 47 | deleted, or at least until it is accessed via its methods. 48 | In the _data_ case, this means ensuring that _data_ is not garbage collected during the hostmem object lifetime. + 49 | (Note that _malloc(data)_ and _hostmem(data)_ differ in that the former allocates memory and copies 50 | _data_ in it, while the latter just stores a pointer to _data_).# 51 | 52 | [[hostmem_free]] 53 | * *free*(_hostmem_) + 54 | hostmem++:++*free*( ) + 55 | [small]#Deletes the _hostmem_ object. If _hostmem_ was created with 56 | <>( ) or <>( ), this function also releases the encapsulated memory.# 57 | 58 | [[hostmem_ptr]] 59 | * _ptr_ = hostmem++:++*ptr*([_offset_=0], [_nbytes_=0]) + 60 | [small]#Returns a pointer (lightuserdata) to the location at _offset_ bytes from the beginning of the encapsulated memory. + 61 | Raises an error if the requested location is beyond the boundaries of the memory area, or if there are not at least _nbytes_ of memory after it.# 62 | 63 | [[hostmem_size]] 64 | * _nbytes_ = hostmem++:++*size*([_offset_=0]) + 65 | _nbytes_ = hostmem++:++*size*(_ptr_) + 66 | [small]#Returns the number of bytes of memory available after _offset_ bytes from the beginning 67 | of the encapsulated memory area, or after _ptr_ (a lightuserdata obtained with hostmem:<>( )).# 68 | 69 | [[hostmem_read]] 70 | * _data_ = hostmem++:++*read*([_offset_], [_nbytes_]) + 71 | {_val~1~_, _..._, _val~N~_} = hostmem++:++*read*([_offset_], [_nbytes_], <>) + 72 | [small]#Reads _nbytes_ of data starting from _offset_, and returns it as a binary string or as 73 | a table of primitive values. + 74 | The _offset_ parameter defaults to 0, and _nbytes_ defaults to the memory size minus _offset_. + 75 | _hostmem:read(offset, nbytes, type)_ is functionally equivalent to 76 | _glmath.unpack(type, hostmem:read(offset, nbytes))_.# 77 | 78 | [[hostmem_write]] 79 | * hostmem++:++*write*(_offset_, _nil_, _data_) + 80 | hostmem++:++*write*(_offset_, <>, _val~1~_, _..._, _val~N~_) + 81 | hostmem++:++*write*(_offset_, <>, {_value~1~_, _..._, _value~N~_}) + 82 | [small]#Writes to the encapsulated memory area, starting from the byte at _offset_. + 83 | *write*(_offset_, _nil_, _data_) writes the contents of _data_ (a binary string); + 84 | *write*(_offset_, _type_, _..._) is equivalent to _write(offset, nil, glmath.pack(type, ...))_.# 85 | 86 | [[hostmem_copy]] 87 | * hostmem++:++*copy*(_offset_, _size_, _srcptr_) + 88 | hostmem++:++*copy*(_offset_, _size_, _srchostmem_, _srcoffset_) + 89 | [small]#Copies _size_ bytes to the encapsulated memory area, starting from the byte at _offset_. + 90 | *copy*(_offset_, _size_, _srcptr_), copies the _size_ bytes pointed to by _srcptr_ (a lightuserdata). + 91 | *copy*(_offset_, _size_, _srchostmem_, _srcoffset_), copies _size_ bytes from the memory encapsulated 92 | by _srchostmem_ (a hostmem object), starting from the location at _srcoffset_.# 93 | 94 | [[hostmem_clear]] 95 | * hostmem++:++*clear*(_offset_, _nbytes_, [_val_=0]) + 96 | [small]#Clears _nbytes_ of memory starting from _offset_. If the _val_ parameter is given, 97 | the bytes are set to its value instead of 0 (_val_ may be an integer or a character, i.e. 98 | a string of length 1).# 99 | 100 | 101 | -------------------------------------------------------------------------------- /doc/index.adoc: -------------------------------------------------------------------------------- 1 | = MoonGLMATH Reference Manual 2 | Stefano Trettel 3 | v0.6, 2020-02-29 4 | :toc: left 5 | :toclevels: 4 6 | :stylesdir: ./ 7 | :stylesheet: colony.css 8 | :source-highlighter: pygments 9 | :pygments-style: autumn 10 | :source-language: lua 11 | :exampledir: ../examples 12 | 13 | image::powered-by-lua.gif[Lua logo, link=http://www.lua.org] 14 | 15 | include::preface.adoc[] 16 | 17 | include::introduction.adoc[] 18 | 19 | include::vectors.adoc[] 20 | 21 | include::matrices.adoc[] 22 | 23 | include::quaternions.adoc[] 24 | 25 | include::boxes.adoc[] 26 | 27 | include::rects.adoc[] 28 | 29 | include::complex.adoc[] 30 | 31 | include::transforms.adoc[] 32 | 33 | include::viewing.adoc[] 34 | 35 | include::datahandling.adoc[] 36 | include::hostmem.adoc[] 37 | include::tracing.adoc[] 38 | 39 | -------------------------------------------------------------------------------- /doc/introduction.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Introduction 3 | 4 | MoonGLMATH is a basic graphics math library in Lua, intended to be used with 5 | https://github.com/stetre/moongl[MoonGL] and the other libraries of the 6 | https://github.com/stetre/moonlibs[MoonLibs collection] (but it does not depend on them, and viceversa). 7 | 8 | By now it has only the minimal features needed for graphics programming: real vectors and real matrices 9 | up to 4 and 4x4 dimensions, quaternions, 2D and 3D axis-aligned boxes, 2D axis-aligned rectangles, complex numbers, and a few functions to generate transformation matrices. 10 | 11 | Like MoonGL and the other <>, it is not designed for 12 | performance but for ease of use (the main purpose of these libraries is to lighten the burden 13 | of programming while studying computer graphics). 14 | 15 | -------------------------------------------------------------------------------- /doc/matrices.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Matrices 3 | 4 | MoonGLMATH supports numeric matrices of size NxM, with N and M ranging from 2 to 4 inclusive. 5 | 6 | A matrix *m* is implemented as a table having its rows in the array part, 7 | starting from index 1; each row is also a table having the elements in the array part. 8 | Additionally, the matrix also has the non-array fields *m.rows* and 9 | *m.columns*, whose values are the number of rows and of columns, respectively. 10 | 11 | Matrix elements are Lua link:++http://www.lua.org/manual/5.3/manual.html#2.1++[number]s 12 | and can be accessed through standard indexing. That is, *m[i][j]* is the element in the 13 | i-th row and j-th column of the matrix *m*. 14 | 15 | Matrix elements can also be accessed using the *m._ij* syntactic sugar, with i and j 16 | ranging from 1 to 4 inclusive, which is an alias for *m[i][j]* (e.g. *m._23* is the 17 | same as *m[2][3]*). 18 | 19 | The following constructors can be used to create matrices. 20 | 21 | [[glmath.matN]] 22 | * _m_ = *mat2*(_..._) + 23 | _m_ = *mat3*(_..._) + 24 | _m_ = *mat4*(_..._) + 25 | _m_ = *mat2x3*(_..._) + 26 | _m_ = *mat3x2*(_..._) + 27 | _m_ = *mat2x4*(_..._) + 28 | _m_ = *mat4x2*(_..._) + 29 | _m_ = *mat3x4*(_..._) + 30 | _m_ = *mat4x3*(_..._) + 31 | [small]#Create a matrix. The *matN* function creates a square matrix vector size NxN, while 32 | the *matNxM* creates a rectangular matrix of size NxM. 33 | Values to initialize the matrix elements may be optionally passed as a list of numbers 34 | (to fill the matrix in row-major order), as a list of row vectors (to fill the matrix rows), 35 | as a list of column vectors (to fill the matrix columns), or as a matrix (to copy the elements 36 | from). In all cases, exceeding values are discarded, while missing values are replaced with zeros. 37 | As an exception, the *matN* function, when invoked without arguments, returns the NxN 38 | identity matrix.# 39 | 40 | [[glmath.tomatN]] 41 | * _t_ = *tomat2*(_t_) + 42 | _t_ = *tomat3*(_t_) + 43 | _t_ = *tomat4*(_t_) + 44 | _t_ = *tomat2x3*(_t_) + 45 | _t_ = *tomat3x2*(_t_) + 46 | _t_ = *tomat2x4*(_t_) + 47 | _t_ = *tomat4x2*(_t_) + 48 | _t_ = *tomat3x4*(_t_) + 49 | _t_ = *tomat4x3*(_t_) + 50 | [small]#Turn an appropriately sized table into a matrix, by adding the relevant meta information to it.# 51 | 52 | .examples 53 | [source,lua] 54 | ---- 55 | m = glmath.mat3() --> m = {{ 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }} 56 | m = glmath.mat2x3() --> m = {{ 0, 0, 0 }, { 0, 0, 0 }} 57 | m = glmath.mat2x3(1, 2, 3, 4) --> m = {{ 1, 2, 3 }, { 4, 0, 0 }} 58 | m = glmath.mat3x2(1, 2, 3, 4) --> m = {{ 1, 2 }, { 3, 4 }, { 0, 0 }} 59 | m = glmath.mat3(m) --> m = {{ 1, 2, 0 }, { 3, 4, 0 }, { 0, 0, 0 }} 60 | v1 = glmath.vec2(1, 2) 61 | v2 = glmath.vec2(3, 4) 62 | m = glmath.mat2(v1, v2) --> m = {{ 1, 3 }, { 2, 4 }} 63 | m = glmath.mat3(v1, v2) --> m = {{ 1, 3, 0 }, { 2, 4, 0 }, { 0, 0, 0 }} 64 | v1 = glmath.vec2r(1, 2) 65 | v2 = glmath.vec2r(3, 4) 66 | m = glmath.mat2(v1, v2) --> m = {{ 1, 2 }, { 3, 4 }} 67 | m = glmath.mat3(v1, v2) --> m = {{ 1, 2, 0 }, { 3, 4, 0 }, { 0, 0, 0 }} 68 | ---- 69 | 70 | [[glmath.ismatN]] 71 | * _boolean_ = *ismat2*(_v_) + 72 | _boolean_ = *ismat3*(_v_) + 73 | _boolean_ = *ismat4*(_v_) + 74 | _boolean_ = *ismat2x3*(_v_) + 75 | _boolean_ = *ismat3x2*(_v_) + 76 | _boolean_ = *ismat2x4*(_v_) + 77 | _boolean_ = *ismat4x2*(_v_) + 78 | _boolean_ = *ismat3x4*(_v_) + 79 | _boolean_ = *ismat4x3*(_v_) + 80 | [small]#Check if _m_ is a matrix of a given size (e.g. *ismat2* checks if _m_ is a 2x2 matrix).# 81 | 82 | ''' 83 | 84 | Matrices have the following *functions and methods* (functions are also available as methods of their first argument): 85 | 86 | * _determinant_ = *det*(_m_) + 87 | _trace_ = *trace*(_m_) + 88 | _adjoint_ = *adj*(_m_) + 89 | _m^-1^_ = *inv*(_m_) + 90 | [small]#Apply only to square matrices. If _m_ is singular, _inv(m)_ returns _nil_.# 91 | 92 | * _m^T^_ = *transpose*(_m_) + 93 | 94 | * _q_ = <>(_m_) + 95 | 96 | * _v_ = *m:row*(_i_) + 97 | [small]#Returns the _i-th_ row as a row vector (<>).# 98 | 99 | * _v_ = *m:column*(_i_) + 100 | [small]#Returns the _i-th_ column as a column vector (<>).# 101 | 102 | * _m~clamped~_ = *clamp*(_m_, _m~min~_, _m~max~_) + 103 | [small]#Element-wise clamp.# 104 | 105 | * _m~mix~_ = *mix*(_m_, _m~1~_, _k_) + 106 | [small]#Element-wise blend _m~mix~ = (1-k)*m +k*m~1~_, where _k_ is a number.# 107 | 108 | * _m~step~_ = *step*(_m_, _m~edge~_) + 109 | [small]#Element-wise step: _m~step~=0.0_ if _m≤m~edge~_, _m~step~=1.0_ otherwise (element subscripts are omitted for clarity). + 110 | The _m~edge~_ argument may be a number, meaning a matrix with all elements equal to that number.# 111 | 112 | [[mat_smoothstep]] 113 | * _m~smoothstep~_ = *smoothstep*(_m_, _m~0~_, _m~1~_) + 114 | [small]#Element-wise smoothstep: omitting element subscripts, _m~smoothstep~_ is _0.0_ if _m≤m~0~_, _1.0_ if _m≥m~1~_, and is obtained by smooth Hermite interpolation if _m~0~<m<m~1~_ 115 | (i.e. _m~smoothstep~=3t^2^-2t^3^_, where _t=(m-m~0~)/(m~1~-m~0~)_). The result is undefined if _m~0~≥m~1~_. + 116 | The _m~0~_ and _m~1~_ argument may be both be a number, meaning a matrix with all elements equal to that number.# 117 | 118 | * _m~fade~_ = *fade*(_m_, _m~0~_, _m~1~_) + 119 | [small]#Element-wise improved smoothstep. Same as <>( ), but with the smoother interpolation function _m~fade~=6t^5^-15t^4^+10t^3^_ (Perlin improved).# 120 | 121 | 122 | ''' 123 | The following *matrix operators* are supported: 124 | 125 | * *Unary minus*: _m = -m~1~_. 126 | * *Addition*: _m = m~1~ + m~2~_. 127 | * *Subtraction*: _m = m~1~ - m~2~_. 128 | * *Multiplication by a scalar*: _m = s * m~1~_, and _m = m~1~ * s_, where _s_ is a number. 129 | * *Division by a scalar*: _m = m~1~ / s_, where _s_ is a number. 130 | * *Integer power*: _m = m~1~ ^ n_, where _m~1~_ is a square matrix and _n_ is an integer. 131 | * *Matrix multiplication*: _m = m~1~ * m~2~_, where _m~1~_ is a NxK matrix and _m~2~_ a KxM matrix. 132 | The result _m_ is an NxM matrix. 133 | * *Matrix-vector multiplication*: _u_ = _m_ * _v_ where _m_ is an NxM matrix and _v_ is a size M column vector. The result _u_ is a size N column vector. 134 | * *Vector-matrix multiplication*: _u_ = _v_ * _m_ where _v_ is a size N row vector and _m_ is an NxM matrix. The result _u_ is a size M row vector. 135 | 136 | 137 | -------------------------------------------------------------------------------- /doc/powered-by-lua.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stetre/moonglmath/764ec9e02124fd99f9ffa71f19c51300d8fba0f6/doc/powered-by-lua.gif -------------------------------------------------------------------------------- /doc/preface.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Preface 3 | 4 | This is the reference manual of *MoonGLMATH*, which is a 5 | http://www.lua.org[*Lua*] math library for 6 | https://github.com/stetre/moongl[*MoonGL*]. 7 | footnote:[ 8 | This manual is written in 9 | http://www.methods.co.nz/asciidoc/[AsciiDoc], rendered with 10 | http://asciidoctor.org/[AsciiDoctor] and a CSS from the 11 | https://github.com/asciidoctor/asciidoctor-stylesheet-factory[AsciiDoctor Stylesheet Factory]. 12 | The PDF version is produced with 13 | https://github.com/asciidoctor/asciidoctor-pdf[AsciiDoctor-Pdf].] 14 | 15 | It is assumed that the reader is familiar with the Lua programming language. 16 | 17 | For convenience of reference, this document contains external (deep) links to the 18 | http://www.lua.org/manual/5.3/manual.html[Lua Reference Manual]. 19 | 20 | === Getting and installing 21 | 22 | For installation intructions, refer to the README file in the 23 | https://github.com/stetre/moonglmath[*MoonGLMATH official repository*] 24 | on GitHub. 25 | 26 | //// 27 | The *official repository* of MoonGLMATH is on GitHub at the following link: 28 | *https://github.com/stetre/moonglmath* . 29 | 30 | MoonGLMATH runs on GNU/Linux and requires 31 | *http://www.lua.org[Lua]* version 5.3 or greater. 32 | 33 | To install MoonGLMATH, download the 34 | https://github.com/stetre/moonglmath/releases[latest release] and do the following: 35 | 36 | [source,shell] 37 | ---- 38 | # ... download moonglmath-0.1.tar.gz ... 39 | [ ]$ tar -zxpvf moonglmath-0.1.tar.gz 40 | [ ]$ cd moonglmath-0.1 41 | [moonglmath-0.1]$ make 42 | [moonglmath-0.1]$ make check 43 | [moonglmath-0.1]$ sudo make install 44 | ---- 45 | 46 | The _$make check_ command shows you what will be installed and where (please read 47 | its output before executing _$make install_). 48 | By default, MoonGLMATH installs its components in subdirectories of `/usr/local/` 49 | (and creates such directories, if needed). 50 | This behaviour can be changed by defining PREFIX with the desired alternative 51 | base installation directory. For example, this will install the components 52 | in `/home/joe/local`: 53 | 54 | [source,shell] 55 | ---- 56 | [moonglmath-0.1]$ make 57 | [moonglmath-0.1]$ make install PREFIX=/home/joe/local 58 | ---- 59 | //// 60 | 61 | === Module organization 62 | 63 | The MoonGLMATH module is loaded using Lua's 64 | http://www.lua.org/manual/5.3/manual.html#pdf-require[require]() and 65 | returns a table containing the functions it provides 66 | (as usual with Lua modules). This manual assumes that such 67 | table is named *glmath*, i.e. that it is loaded with: 68 | 69 | [source,lua,indent=1] 70 | ---- 71 | glmath = require("moonglmath") 72 | ---- 73 | 74 | but nothing forbids the use of a different name. 75 | 76 | === Examples 77 | 78 | A few examples can be found in the *examples/* directory of the release package. 79 | 80 | === License 81 | 82 | MoonGLMATH is released under the *MIT/X11 license* (same as 83 | http://www.lua.org/license.html[Lua], and with the same only requirement to give proper 84 | credits to the original author). 85 | The copyright notice is in the LICENSE file in the base directory 86 | of the https://github.com/stetre/moonglmath[official repository] on GitHub. 87 | 88 | [[see-also]] 89 | === See also 90 | 91 | MoonGLMATH is part of https://github.com/stetre/moonlibs[MoonLibs], a collection of 92 | Lua libraries for graphics and audio programming. 93 | 94 | -------------------------------------------------------------------------------- /doc/quaternions.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Quaternions 3 | 4 | A quaternion *q* = (_w_, *v*) = _w_ + i·_x_ + j·_y_ + k·_z_ is implemented as a table having 5 | the quaternion elements in the array part, starting from index 1. 6 | 7 | Quaternion elements are Lua link:++http://www.lua.org/manual/5.3/manual.html#2.1++[number]s 8 | and can be accessed through standard indexing (that is, *q[1]* is the scalar part _w_, 9 | and *q[2]* to *q[4]* are the _x_, _y_ and _z_ components of the vector part, or imaginary part, *v*). 10 | 11 | Quaternion elements can also be accessed using the *wxyz* syntactic sugar: 12 | *q.w*, *q.x*, *q.y*, and *q.z* are aliases for *q[1]*, *q[2]*, *q[3]*, and *q[4]*, respectively. 13 | 14 | The following constructor can be used to create quaternions. 15 | 16 | [[glmath.quat]] 17 | * _q_ = *quat*([_w_], [_x_], [_y_], [_z_]) + 18 | _q_ = *quat*(_w_, _v_) + 19 | _q_ = *quat*(_v~axis~_, _angle_) + 20 | _q_ = *quat*(_q_) + 21 | _q_ = *quat*(_m_) + 22 | [small]#Create a quaternion. 23 | Values to initialize the quaternion elements may be optionally passed as 24 | a list of numbers, as a scalar _w_ and a vector _v_, or as a previously created quaternion _q_ 25 | (exceeding values are discarded, while missing values are replaced with zeros). 26 | If a matrix _m_ is passed instead, the constructor assumes - without checking it - that _m_ is a 27 | rotation matrix and returns the equivalent quaternion 28 | (_m_ may be either a 3x3 or a 4x4 matrix, in which case its upper-left 3x3 submatrix 29 | is regarded as the rotation matrix).# 30 | 31 | [[glmath.toquat]] 32 | * _t_ = *toquat*(_t_) + 33 | [small]#Turn an appropriately sized table into a quaternion, by adding the relevant meta information to it.# 34 | 35 | 36 | .examples 37 | [source,lua] 38 | ---- 39 | q = glmath.quat() --> q = < 0, 0, 0 > 40 | q = glmath.quat(0, 1, 2, 3) --> q = < 0, 1, 2, 3 > 41 | 42 | w = 0 43 | v = glmath.vec3(1, 2, 3) 44 | q = glmath.quat(w, v) --> q = < 0, 1, 2, 3 > 45 | 46 | m = glmath.mat3(1, 0, 0, 0, 0, -1, 0, 1, 0) 47 | q = glmath.quat(m) --> q = < 0.707107, 0.707107, 0, 0 > 48 | ---- 49 | 50 | [[glmath.isquat]] 51 | * _boolean_ = *isquat*(_q_) + 52 | [small]#Returns _true_ if _q_ is a quaternion, _false_ otherwise.# 53 | 54 | ''' 55 | 56 | Quaternions have the following *functions and methods* (functions are also available as methods of their first argument): 57 | 58 | * _w_, _v_ = *parts*(_q_) + 59 | [small]#Returns the scalar and vector parts of _q_ (_w_ is a number and _v_ is a <>).# 60 | 61 | * _q^pass:[*]^_ = *conj*(_q_) + 62 | _|q|_ = *norm*(_q_) + 63 | _|q|^2^_ = *norm2*(_q_) + 64 | _q/|q|_ = *normalize*(_q_) + 65 | _q^-1^_ = *inv*(_q_) + 66 | 67 | * _m_ = *q:mat3*( ) + 68 | _m_ = *q:mat4*( ) + 69 | [small]#Convert the quaternion _q_ to a 3x3 or a 4x4 rotation matrix.# 70 | 71 | * _q~mix~_ = *mix*(_q_, _q~1~_, _k_) + 72 | [small]#Element-wise blend _q~mix~ = (1-k)*q +k*q~1~_, where _k_ is a number.# 73 | 74 | * _q~slerp~_ = *slerp*(_q_, _q~1~_, _k_) + 75 | [small]#Spherical linear interpolation.# 76 | 77 | ''' 78 | The following *quaternion operators* are supported: 79 | 80 | * *Unary minus*: _q = -q~1~_. 81 | * *Addition*: _q = q~1~ + q~2~_. 82 | * *Subtraction*: _q = q~1~ - q~2~_. 83 | * *Multiplication by a scalar*: _q = s * q~1~_, and _q = q~1~ * s_, where _s_ is a number. 84 | * *Division by a scalar*: _q = q~1~ / s_, where _s_ is a number. 85 | * *Integer power*: _q = q~1~ ^ n_, where _n_ is an integer. 86 | * *Quaternion multiplication*: _q = q~1~ * q~2~_. 87 | 88 | -------------------------------------------------------------------------------- /doc/rects.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Rectangles 3 | 4 | MoonGLMATH supports 2D axis-aligned rectangles, which are essentially the same as 2D boxes but specified differently. 5 | 6 | A rect *r* is implemented as a table having, in the array part, the coordinates _(x, y)_ of its lower-left corner and its width _w_ and height _h_, as follows: _{ x, y, w, h }_. 7 | 8 | The coordinates are Lua link:++http://www.lua.org/manual/5.3/manual.html#2.1++[number]s 9 | and can be accessed through standard indexing (that is, *r[1]* is _x_, *r[2]* 10 | is _y_, and so on). They can also be accessed using the following syntactic sugar: 11 | *r.x* is an alias for *r[1]*, *r.y* is an alias for *r[2]*, and so on. 12 | 13 | The following constructor can be used to create rects. 14 | 15 | [[glmath.rect]] 16 | * _r_ = *rect*(_..._) + 17 | [small]#Creates a 2D axis-aligned rect. Values to initialize the rect may be optionally passed as a list of numbers, or as a previously created rect (exceeding values are discarded, while missing values are replaced with zeros). No consistency check is performed on the passed coordinates.# 18 | 19 | [[glmath.torect]] 20 | * _t_ = *torect*(_t_) + 21 | [small]#Turn an appropriately sized table into a rect, by adding the relevant meta information to it.# 22 | 23 | .examples 24 | [source,lua] 25 | ---- 26 | r = glmath.rect() --> r = [ 0, 0, 0, 0 ] 27 | r = glmath.rect(-1, 1, 2, 3) --> r = [ -1, 1, 2, 3 ] 28 | ---- 29 | 30 | [[glmath.isrect]] 31 | * _boolean_ = *isrect*(_r_) + 32 | [small]#Check if _r_ is a rect.# 33 | 34 | //// 35 | 36 | ''' 37 | Boxes have the following functions, also available as methods of their first argument: 38 | 39 | TBD 40 | 41 | ''' 42 | The following *rect operators* are supported: 43 | 44 | TBD 45 | 46 | //// 47 | -------------------------------------------------------------------------------- /doc/tracing.adoc: -------------------------------------------------------------------------------- 1 | 2 | [[tracing]] 3 | == Tracing utilities 4 | 5 | [[trace_objects]] 6 | * *trace_objects*(_boolean_) + 7 | [small]#Enable/disable tracing of objects creation and destruction (which by default 8 | is disabled). + 9 | If enabled, a printf is generated whenever an object is created or deleted, 10 | indicating the object type and the value of its raw handle.# 11 | 12 | [[now]] 13 | * _t_ = *now*( ) + 14 | [small]#Returns the current time in seconds (a Lua number). + 15 | This is implemented with monotonic _clock_gettime(3)_, if available, or 16 | with _gettimeofday(3)_ otherwise.# 17 | 18 | [[since]] 19 | * _dt_ = *since*(_t_) + 20 | [small]#Returns the time in seconds (a Lua number) elapsed since the time _t_, 21 | previously obtained with the <>( ) function.# 22 | 23 | [[stats]] 24 | * _mean_, _var_, _min_, _max_ = *stats*(_{number}_) + 25 | [small]#Computes the mean, variance, and the minimum and maximum values for the given array 26 | of numbers.# 27 | 28 | [[dumpdata]] 29 | * *dumpdata*(_{number}_, _filename_, [_mode='w'_]) + 30 | [small]#Writes the given array of numbers to the given file file (plain ascii format, two columns index-value). + 31 | The data can then be displayed, for example, using gnuplot (_gnuplot> plot "filename" using 1:2 with lines_). + 32 | _mode_ is the same as in http://www.lua.org/manual/5.3/manual.html#pdf-io.open[io.open]( ).# 33 | 34 | -------------------------------------------------------------------------------- /doc/transforms.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Basic Transforms 3 | 4 | * _m_ = *translate*(_v_) + 5 | _m_ = *translate*(_x_ , _y_ , _z_) + 6 | [small]#Returns the 4x4 translation matrix, given the vector _v_ or its components _x_, _y_, and _z_.# 7 | 8 | * _m_ = *scale*(_v_) + 9 | _m_ = *scale*(_x_, [_y_] , [_z_]) + 10 | [small]#Returns the 4x4 scaling matrix, given the scaling factors _x_, _y_, and _z_, which may 11 | also be passed as a vector. + 12 | If _y_ and _z_ are not given, they are assumed equal to _x_ (i.e. uniform scaling by a factor _x_).# 13 | 14 | 15 | * _m_ = *rotate*(_angle_, _v_) + 16 | _m_ = *rotate*(_angle_, _x_ , _y_ , _z_) + 17 | [small]#Return the 4x4 rotation matrix given the _angle_ (in radians) and the direction vector 18 | _v_ = (_x_, _y_, _z_).# 19 | 20 | * _m_ = *rotate_x*(_angle_) + 21 | _m_ = *rotate_y*(_angle_) + 22 | _m_ = *rotate_z*(_angle_) + 23 | [small]#Return the 4x4 rotation matrix for a rotation by _angle_ radians around the x, y or z axis, respectively.# 24 | 25 | //// 26 | .Elementary transforms 27 | [source,lua] 28 | ---- 29 | 30 | glmath.translate(x,y,z) = {{ 1, 0, 0, x }, 31 | { 0, 1, 0, y }, 32 | { 0, 0, 1, z }, 33 | { 0, 0, 0, 1 }} 34 | 35 | glmath.scale(x,y,z) = {{ x, 0, 0, 0 }, 36 | { 0, y, 0, 0 }, 37 | { 0, 0, z, 0 }, 38 | { 0, 0, 0, 1 }} 39 | 40 | -- c = cos(phi), s = sin(phi) 41 | glmath.rotate_x(phi, x, y, z) = {{ c+(1-c)x^2, (1-c)xy-sz, (1-c)xz+sy, 0 }, 42 | { (1-c)xy+sz, c+(1-c)y^2, (1-c)yz-sx, 0 }, 43 | { (1-c)xz-sy, (1-c)yz+sx, c+(1-c)z^2, 0 }, 44 | { 0 , 0 , 0 , 1 }} 45 | 46 | glmath.rotate_x(phi) = {{ 1, 0, 0, 0 }, 47 | { 0, c, -s, 0 }, 48 | { 0, s, c, 0 }, 49 | { 0, 0, 0, 1 }} 50 | 51 | glmath.rotate_y(phi) = {{ c, 0, s, 0 }, 52 | { 0, 1, 0, 0 }, 53 | { -s, 0, c, 0 }, 54 | { 0, 0, 0, 1 }} 55 | 56 | glmath.rotate_z(phi) = {{ c, -s, 0, 0 }, 57 | { s, c, 0, 0 }, 58 | { 0, 0, 1, 0 }, 59 | { 0, 0, 0, 1 }} 60 | 61 | ---- 62 | //// 63 | 64 | 65 | -------------------------------------------------------------------------------- /doc/vectors.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Vectors 3 | 4 | MoonGLMATH supports row and column numeric vectors of size 2, 3, and 4. 5 | 6 | A vector *v* is implemented as a table having the vector elements in the array part, 7 | starting from index 1. 8 | Additionally, it also has the non-array fields *v.size* (= _2_, _3_, or _4_) and 9 | *v.type* (= '_column_' or '_row_'). 10 | 11 | Vector elements are Lua link:++http://www.lua.org/manual/5.3/manual.html#2.1++[number]s 12 | and can be accessed through standard indexing (that is, *v[1]* is the first element, *v[2]* 13 | is the second element and so on). 14 | 15 | Vector elements can also be accessed using the *xyzw*, *rgba* and *stpq* syntactic sugar 16 | for positions, colors and texture coordinates (*v.x*, *v.r* and *v.s* are aliases for *v[1]*, 17 | *v.y*, *v.g* and *v.t* are aliases for *v[2]*, and so on). 18 | 19 | The following constructors can be used to create vectors. 20 | 21 | [[glmath.vecN]] 22 | * _v_ = *vec2*(_..._) + 23 | _v_ = *vec3*(_..._) + 24 | _v_ = *vec4*(_..._) + 25 | _v_ = *vec2r*(_..._) + 26 | _v_ = *vec3r*(_..._) + 27 | _v_ = *vec4r*(_..._) + 28 | [small]#Create a vector. 29 | The *vecN* function creates a column vector of size N (where N may be 2, 3 or 4), whereas the *vecNr* function creates a row vector of the same size. Values to initialize the vector elements may be optionally passed as a list of numbers, or as a previously created vector (exceeding values are discarded, while missing values are replaced with zeros).# 30 | 31 | [[glmath.tovecN]] 32 | * _t_ = *tovec2*(_t_) + 33 | _t_ = *tovec3*(_t_) + 34 | _t_ = *tovec4*(_t_) + 35 | _t_ = *tovec2r*(_t_) + 36 | _t_ = *tovec3r*(_t_) + 37 | _t_ = *tovec4r*(_t_) + 38 | [small]#Turn an appropriately sized table into a vector, by adding the relevant meta information to it.# 39 | 40 | .examples 41 | [source,lua] 42 | ---- 43 | v = glmath.vec3() --> v = { 0, 0, 0 }' 44 | v = glmath.vec3(11, 22) --> v = { 11, 22, 0 }' 45 | v = glmath.vec2(v) --> v = { 11, 22 }' 46 | v = glmath.vec4(v) --> v = { 11, 22, 0, 0 }' 47 | v = glmath.vec2(1, 2, 3, 4) --> v = { 1, 2 }' 48 | ---- 49 | 50 | [[glmath.isvecN]] 51 | * _boolean_ = *isvec2*(_v_) + 52 | _boolean_ = *isvec3*(_v_) + 53 | _boolean_ = *isvec4*(_v_) + 54 | _boolean_ = *isvec2r*(_v_) + 55 | _boolean_ = *isvec3r*(_v_) + 56 | _boolean_ = *isvec4r*(_v_) + 57 | [small]#Check if _v_ is a vector of a given type (e.g. *isvec2r* checks if _v_ is a row vector of size 2).# 58 | 59 | ''' 60 | Vectors have the following functions, also available as methods of their first argument: 61 | 62 | * _|v|_ = *norm*(_v_) + 63 | _|v|^2^_ = *norm2*(_v_) + 64 | _v/|v|_ = *normalize*(_v_) + 65 | _v^T^_ = *transpose*(_v_) + 66 | 67 | * _v~clamped~_ = *clamp*(_v_, _v~min~_, _v~max~_) + 68 | [small]#Element-wise clamp.# 69 | 70 | * _v~mix~_ = *mix*(_v_, _v~1~_, _k_) + 71 | [small]#Element-wise blend _v~mix~ = (1-k)*v +k*v~1~_, where _k_ is a number.# 72 | 73 | * _v~step~_ = *step*(_v_, _v~edge~_) + 74 | [small]#Element-wise step: _v~step~=0.0_ if _v≤v~edge~_, _v~step~=1.0_ otherwise (element subscripts are omitted for clarity). + 75 | The _v~edge~_ argument may be a number, meaning a vector with all elements equal to that number.# 76 | 77 | [[vec_smoothstep]] 78 | * _v~smoothstep~_ = *smoothstep*(_v_, _v~0~_, _v~1~_) + 79 | [small]#Element-wise smoothstep: omitting element subscripts, _v~smoothstep~_ is _0.0_ if _v≤v~0~_, _1.0_ if _v≥v~1~_, and is obtained by smooth Hermite interpolation if _v~0~<v<v~1~_ 80 | (i.e. _v~smoothstep~=3t^2^-2t^3^_, where _t=(v-v~0~)/(v~1~-v~0~)_). The result is undefined if _v~0~≥v~1~_. + 81 | The _v~0~_ and _v~1~_ argument may be both be a number, meaning a vector with all elements equal to that number.# 82 | 83 | * _v~fade~_ = *fade*(_v_, _v~0~_, _v~1~_) + 84 | [small]#Element-wise improved smoothstep. Same as <>( ), but with the smoother interpolation function _v~fade~=6t^5^-15t^4^+10t^3^_ (Perlin improved).# 85 | 86 | 87 | 88 | ''' 89 | The following *vector operators* are supported: 90 | 91 | * *Unary minus*: _v = -v~1~_. 92 | * *Addition*: _v = v~1~ + v~2~_. 93 | * *Subtraction*: _v = v~1~ - v~2~_. 94 | * *Multiplication by a scalar*: _v = s * v1_, and _v = v~1~ * s_, where _s_ is a number. 95 | * *Division by a scalar*: _v = v~1~ / s_, where _s_ is a number. 96 | * *Dot product*: _s = v~1~ * v~2~_, where _v~1~_ and _v~2~_ are vectors of the same size (row*column, but row*row and column*column are accepted as well). 97 | * *Multiplication*: _m = v~1~ * v~2~_, where _v~1~_ is a column vector and _v~2~_ is a row vector of the same size. The result is a square matrix. 98 | * *Cross product*: _v = v~1~ % v~2~_, where _v~1~_ and _v~3~_ are size 3 vectors. Works also on operands of size 2 and 4, adapting them to size 3 (size 2 operands are extended to size 3 by adding a zero element, while size 4 operands are reduced to size 3 by ignoring the 4-th element). 99 | The result is always a size 3 vector. 100 | 101 | -------------------------------------------------------------------------------- /doc/viewing.adoc: -------------------------------------------------------------------------------- 1 | 2 | == Camera and Projections 3 | 4 | The functions below follow the traditional OpenGL conventions, where the camera (or viewer) 5 | is in the origin, looking towards the negative z-axis, with the positive x-axis pointing to 6 | its right and the positive y-axis pointing up, and the _near_ and _far_ parameters represent 7 | the distance of the near and far planes from the origin along the viewing direction 8 | (i.e. they are the negated z-coordinates of the two planes). 9 | 10 | * _m_ = *look_at*(_eye_, _at_, _up_) + 11 | [small]#Returns a 4x4 matrix to transform from world coordinates to camera coordinates, 12 | given the camera position and orientation in world coordinates: 13 | _eye_ is the camera position, _at_ is its target point, and _up_ is the 14 | direction from the camera to a point on the vertical above the target.# 15 | 16 | * _m_ = *ortho*(_left_, _right_, _bottom_, _top_, [_near_], [_far_]) + 17 | [small]#Returns a 4x4 ortographic projection matrix that transforms an axis-aligned box 18 | into the axis-aligned cube of side 2 centered at the origin. + 19 | The box is bounded by the planes _x=left_, _x=right_, _y=bottom_, _y=top_, _z=-near_, and _z=-far_. + 20 | The _near_ and _far_ values default to -1.0 and 1.0 respectively (2D projection).# 21 | 22 | * _m_ = *frustum*(_left_, _right_, _bottom_, _top_, _near_, _far_) + 23 | [small]#Returns a 4x4 perspective projection matrix. 24 | The view frustum has the center of projection in the origin, its near face is 25 | the rectangle (_left 12 | -- 13 | -- 14 | 15 | glmath = require("moonglmath") 16 | 17 | -- globalize all glmath functions: 18 | for k, v in pairs(glmath) do 19 | if(k~="type") then _ENV[k] = v end 20 | end 21 | 22 | -- globalize all math functions (except for type()): 23 | for k, v in pairs(math) do 24 | if(k~="type") then _ENV[k] = v end 25 | end 26 | -------------------------------------------------------------------------------- /examples/matrices.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | -- MoonGLMATH example: matrices.lua 3 | 4 | local glmath = require("moonglmath") 5 | 6 | local m = glmath.mat3() 7 | print(m) 8 | 9 | m = glmath.mat2x3() 10 | print(m) 11 | 12 | m = glmath.mat2x3(1, 2, 3, 4) 13 | print(m) 14 | 15 | m = glmath.mat3x2(1, 2, 3, 4) 16 | print(m) 17 | 18 | m = glmath.mat3(m) 19 | print(m) 20 | 21 | local v1 = glmath.vec2(1, 2) 22 | local v2 = glmath.vec2(3, 4) 23 | m = glmath.mat2(v1, v2) 24 | print(m) 25 | 26 | m = glmath.mat3(v1, v2) 27 | print(m) 28 | 29 | v1 = glmath.vec2r(1, 2) 30 | v2 = glmath.vec2r(3, 4) 31 | m = glmath.mat2(v1, v2) 32 | print(m) 33 | 34 | m = glmath.mat3(v1, v2) 35 | print(m) 36 | 37 | m = glmath.mat2(1, 2, 3, 4) 38 | print(m) 39 | 40 | print("det", m, m:det()) 41 | print("trace", m, m:trace()) 42 | print("transpose", m, m:transpose()) 43 | print("adj", m, m:adj()) 44 | print("inv", m, m:inv(), m*m:inv()) 45 | 46 | print("unary minus", m, -m) 47 | print("addition", m, m+m) 48 | print("subtraction", m, m-m) 49 | print("multiplication by a scalar", m, 2*m, m*2) 50 | print("division by a scalar", m, m/2) 51 | print("matrix multiplication", m, m*m) 52 | local v = glmath.vec2(1, 2) 53 | print("matrix-vector multiplication", m, m*v) 54 | -------------------------------------------------------------------------------- /examples/moonglmath.sh: -------------------------------------------------------------------------------- 1 | # MoonGLMATH shell (the standard Lua shell enriched with glmath stuff) 2 | lua -i interactive.lua 3 | -------------------------------------------------------------------------------- /examples/quaternions.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | -- MoonGLMATH example: quaternions.lua 3 | 4 | local glmath = require("moonglmath") 5 | 6 | local q1 = glmath.quat(1, 2, 3, 4) 7 | print(q1) 8 | 9 | local q2 = glmath.quat(4, 3, 2, 1) 10 | print(q2) 11 | 12 | 13 | print("scalar and vector parts", q1, q1:parts()) 14 | print("unary minus", q1, -q1) 15 | print("addition", q1, q2, q1+q2) 16 | print("subtraction", q1, q2, q1-q2) 17 | print("multiplication", q1, q2, q1*q2) 18 | print("integer power", q1, q1^3, q1*q1*q1) 19 | print("norm", q1, q1:norm()) -- also glmath.norm(q1) 20 | print("conjugate", q1, q1:conj()) -- also glmath.conj(q1) 21 | print("inverse", q1, q1:inv()) -- q^-1 would do also 22 | print("multiplication by a scalar", q1, 2*q1, q1*2) 23 | print("division by a scalar", q1, q1/2) 24 | print("normalization", q1, q1:normalize()) -- glmath.normalize(q1) 25 | print("3x3 rotation matrix", q1, q1:mat3()) 26 | print("4x4 rotation matrix", q1, q1:mat4()) 27 | 28 | -- create a quaternion representing a rotation 29 | local axis, angle = glmath.vec3(0, 0, 1), math.pi/2 30 | local q3 = glmath.quat(axis, angle) 31 | print(q3, q3:norm()) 32 | -- compute the corresponding rotation matrix 33 | local m = q3:mat3() 34 | print(m) 35 | -- apply the rotation to a vector: 36 | print(m*glmath.vec3(1, 3, 5)) 37 | -------------------------------------------------------------------------------- /examples/vectors.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | -- MoonGLMATH example: vectors.lua 3 | 4 | local glmath = require("moonglmath") 5 | 6 | local v = glmath.vec3() 7 | print(v) 8 | 9 | v = glmath.vec3(11, 22) 10 | print(v) 11 | 12 | v = glmath.vec2(v) 13 | print(v) 14 | 15 | v = glmath.vec4(v) 16 | print(v) 17 | 18 | v = glmath.vec2(1, 2, 3, 4) 19 | print(v) 20 | 21 | local e1 = glmath.vec3(1,0,0) 22 | local e2 = glmath.vec3(0,1,0) 23 | local e3 = glmath.vec3(0,0,1) 24 | print("canonical basis", e1, e2, e3) 25 | 26 | print("transpose", v, v:transpose()) 27 | print("norm", v, v:norm()) 28 | print("unary minus", v, -v) 29 | print("addition", v, v+v) 30 | print("subtraction", v, v-v) 31 | print("multiplication by a scalar", v, 2*v, v*2) 32 | print("division by a scalar", v, v/2) 33 | print("dot product", v, v*v) 34 | print("cross product", e1, e2, e1%e2) 35 | 36 | -------------------------------------------------------------------------------- /examples/versions.lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env lua 2 | -- MoonGLMATH example: versions.lua 3 | 4 | local glmath = require("moonglmath") 5 | print(_VERSION) 6 | print(glmath._VERSION) 7 | 8 | -------------------------------------------------------------------------------- /moonglmath/boxsugar.lua: -------------------------------------------------------------------------------- 1 | -- The MIT License (MIT) 2 | -- 3 | -- Copyright (c) 2016 Stefano Trettel 4 | -- 5 | -- Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | -- 7 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 8 | -- of this software and associated documentation files (the "Software"), to deal 9 | -- in the Software without restriction, including without limitation the rights 10 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | -- copies of the Software, and to permit persons to whom the Software is 12 | -- furnished to do so, subject to the following conditions: 13 | -- 14 | -- The above copyright notice and this permission notice shall be included in all 15 | -- copies or substantial portions of the Software. 16 | -- 17 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | -- SOFTWARE. 24 | -- 25 | 26 | 27 | -- 28 | -- Adds named-components access to MoonGLMATH boxes 29 | -- ( v.minx becomes an alias for b[1], v.maxx becomes an alias for b[2], and so on). 30 | -- 31 | 32 | --local glmath = require("moonglmath") 33 | --local mt = getmetatable(glmath.box2()) 34 | do 35 | local mt = getmetatable(moonglmath.box2()) 36 | local methods = mt.__index 37 | 38 | local rd = {} -- read functions 39 | local wr = {} -- write indices 40 | 41 | -- position components 42 | rd.minx = function(self) return self[1] end 43 | rd.maxx = function(self) return self[2] end 44 | rd.miny = function(self) return self[3] end 45 | rd.maxy = function(self) return self[4] end 46 | rd.minz = function(self) return self[5] end 47 | rd.maxz = function(self) return self[6] end 48 | wr.minx, wr.maxx, wr.miny, wr.maxy, wr.minz, wr.maxz = 1,2,3,4,5,6 49 | 50 | mt.__index = function(self, key) 51 | local f = rd[key] 52 | if f then return f(self) end 53 | return methods[key] 54 | end 55 | 56 | mt.__newindex = function(self, key, val) 57 | if type(key) == "number" or key == "dimensions" then 58 | rawset(self, key, val) 59 | return 60 | end 61 | local i = wr[key] 62 | if i then 63 | rawset(self, i, val) 64 | else 65 | error("cannot write field '" .. key .."'", 2) 66 | end 67 | end 68 | 69 | moonglmath.tobox2 = function(t) setmetatable(t, mt) t.dimensions=2 return t end 70 | moonglmath.tobox3 = function(t) setmetatable(t, mt) t.dimensions=3 return t end 71 | 72 | end 73 | -------------------------------------------------------------------------------- /moonglmath/complexsugar.lua: -------------------------------------------------------------------------------- 1 | -- The MIT License (MIT) 2 | -- 3 | -- Copyright (c) 2018 Stefano Trettel 4 | -- 5 | -- Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | -- 7 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 8 | -- of this software and associated documentation files (the "Software"), to deal 9 | -- in the Software without restriction, including without limitation the rights 10 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | -- copies of the Software, and to permit persons to whom the Software is 12 | -- furnished to do so, subject to the following conditions: 13 | -- 14 | -- The above copyright notice and this permission notice shall be included in all 15 | -- copies or substantial portions of the Software. 16 | -- 17 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | -- SOFTWARE. 24 | -- 25 | 26 | do 27 | local mt = getmetatable(moonglmath.complex()) 28 | local methods = mt.__index 29 | 30 | local rd = {} -- read functions 31 | local wr = {} -- write indices 32 | 33 | -- position components 34 | rd.re = function(self) return self[1] end 35 | rd.im = function(self) return self[2] end 36 | wr.re, wr.im = 1,2 37 | 38 | mt.__index = function(self, key) 39 | local f = rd[key] 40 | if f then return f(self) end 41 | return methods[key] 42 | end 43 | 44 | mt.__newindex = function(self, key, val) 45 | if type(key) == "number" then 46 | rawset(self, key, val) 47 | return 48 | end 49 | local i = wr[key] 50 | if i then 51 | rawset(self, i, val) 52 | else 53 | error("cannot write field '" .. key .."'", 2) 54 | end 55 | end 56 | 57 | moonglmath.tocomplex = function(t) setmetatable(t, mt) return t end 58 | 59 | end 60 | -------------------------------------------------------------------------------- /moonglmath/matsugar.lua: -------------------------------------------------------------------------------- 1 | -- The MIT License (MIT) 2 | -- 3 | -- Copyright (c) 2016 Stefano Trettel 4 | -- 5 | -- Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | -- 7 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 8 | -- of this software and associated documentation files (the "Software"), to deal 9 | -- in the Software without restriction, including without limitation the rights 10 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | -- copies of the Software, and to permit persons to whom the Software is 12 | -- furnished to do so, subject to the following conditions: 13 | -- 14 | -- The above copyright notice and this permission notice shall be included in all 15 | -- copies or substantial portions of the Software. 16 | -- 17 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | -- SOFTWARE. 24 | -- 25 | 26 | do 27 | local mt = getmetatable(moonglmath.mat2()) 28 | local methods = mt.__index 29 | 30 | local rd = {} -- read functions 31 | local wr = {} -- write indices 32 | 33 | -- position components 34 | rd._11 = function(self) return self[1][1] end 35 | rd._12 = function(self) return self[1][2] end 36 | rd._13 = function(self) return self[1][3] end 37 | rd._14 = function(self) return self[1][4] end 38 | rd._21 = function(self) return self[2][1] end 39 | rd._22 = function(self) return self[2][2] end 40 | rd._23 = function(self) return self[2][3] end 41 | rd._24 = function(self) return self[2][4] end 42 | rd._31 = function(self) return self[3][1] end 43 | rd._32 = function(self) return self[3][2] end 44 | rd._33 = function(self) return self[3][3] end 45 | rd._34 = function(self) return self[3][4] end 46 | rd._41 = function(self) return self[4][1] end 47 | rd._42 = function(self) return self[4][2] end 48 | rd._43 = function(self) return self[4][3] end 49 | rd._44 = function(self) return self[4][4] end 50 | 51 | wr._11 = function() return 1, 1 end 52 | wr._12 = function() return 1, 2 end 53 | wr._13 = function() return 1, 3 end 54 | wr._14 = function() return 1, 4 end 55 | wr._21 = function() return 2, 1 end 56 | wr._22 = function() return 2, 2 end 57 | wr._23 = function() return 2, 3 end 58 | wr._24 = function() return 2, 4 end 59 | wr._31 = function() return 3, 1 end 60 | wr._32 = function() return 3, 2 end 61 | wr._33 = function() return 3, 3 end 62 | wr._34 = function() return 3, 4 end 63 | wr._41 = function() return 4, 1 end 64 | wr._42 = function() return 4, 2 end 65 | wr._43 = function() return 4, 3 end 66 | wr._44 = function() return 4, 4 end 67 | 68 | 69 | mt.__index = function(self, key) 70 | local f = rd[key] 71 | if f then return f(self) end 72 | return methods[key] 73 | end 74 | 75 | mt.__newindex = function(self, key, val) 76 | local f = wr[key] 77 | if f then 78 | local i,j = f() 79 | local row = self[i] 80 | rawset(row, j, val) 81 | else 82 | rawset(self, key, val) 83 | end 84 | end 85 | 86 | moonglmath.tomat2 = function(t) setmetatable(t, mt) t.rows=2 t.columns=2 return t end 87 | moonglmath.tomat3 = function(t) setmetatable(t, mt) t.rows=3 t.columns=3 return t end 88 | moonglmath.tomat4 = function(t) setmetatable(t, mt) t.rows=4 t.columns=4 return t end 89 | moonglmath.tomat2x3 = function(t) setmetatable(t, mt) t.rows=2 t.columns=3 return t end 90 | moonglmath.tomat3x2 = function(t) setmetatable(t, mt) t.rows=3 t.columns=2 return t end 91 | moonglmath.tomat2x4 = function(t) setmetatable(t, mt) t.rows=2 t.columns=4 return t end 92 | moonglmath.tomat4x2 = function(t) setmetatable(t, mt) t.rows=4 t.columns=2 return t end 93 | moonglmath.tomat3x4 = function(t) setmetatable(t, mt) t.rows=3 t.columns=4 return t end 94 | moonglmath.tomat4x3 = function(t) setmetatable(t, mt) t.rows=4 t.columns=3 return t end 95 | 96 | end 97 | -------------------------------------------------------------------------------- /moonglmath/quatsugar.lua: -------------------------------------------------------------------------------- 1 | -- The MIT License (MIT) 2 | -- 3 | -- Copyright (c) 2016 Stefano Trettel 4 | -- 5 | -- Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | -- 7 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 8 | -- of this software and associated documentation files (the "Software"), to deal 9 | -- in the Software without restriction, including without limitation the rights 10 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | -- copies of the Software, and to permit persons to whom the Software is 12 | -- furnished to do so, subject to the following conditions: 13 | -- 14 | -- The above copyright notice and this permission notice shall be included in all 15 | -- copies or substantial portions of the Software. 16 | -- 17 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | -- SOFTWARE. 24 | -- 25 | 26 | do 27 | local mt = getmetatable(moonglmath.quat()) 28 | local methods = mt.__index 29 | 30 | local rd = {} -- read functions 31 | local wr = {} -- write indices 32 | 33 | -- position components 34 | rd.w = function(self) return self[1] end 35 | rd.x = function(self) return self[2] end 36 | rd.y = function(self) return self[3] end 37 | rd.z = function(self) return self[4] end 38 | wr.w, wr.x, wr.y, wr.z = 1,2,3,4 39 | 40 | mt.__index = function(self, key) 41 | local f = rd[key] 42 | if f then return f(self) end 43 | return methods[key] 44 | end 45 | 46 | mt.__newindex = function(self, key, val) 47 | if type(key) == "number" then 48 | rawset(self, key, val) 49 | return 50 | end 51 | local i = wr[key] 52 | if i then 53 | rawset(self, i, val) 54 | else 55 | error("cannot write field '" .. key .."'", 2) 56 | end 57 | end 58 | 59 | moonglmath.toquat = function(t) setmetatable(t, mt) return t end 60 | 61 | end 62 | -------------------------------------------------------------------------------- /moonglmath/rectsugar.lua: -------------------------------------------------------------------------------- 1 | -- The MIT License (MIT) 2 | -- 3 | -- Copyright (c) 2016 Stefano Trettel 4 | -- 5 | -- Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | -- 7 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 8 | -- of this software and associated documentation files (the "Software"), to deal 9 | -- in the Software without restriction, including without limitation the rights 10 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | -- copies of the Software, and to permit persons to whom the Software is 12 | -- furnished to do so, subject to the following conditions: 13 | -- 14 | -- The above copyright notice and this permission notice shall be included in all 15 | -- copies or substantial portions of the Software. 16 | -- 17 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | -- SOFTWARE. 24 | -- 25 | 26 | 27 | -- 28 | -- Adds named-components access to MoonGLMATH rects 29 | -- ( v.x becomes an alias for b[1], v.y becomes an alias for b[2], and so on). 30 | -- 31 | do 32 | local mt = getmetatable(moonglmath.rect()) 33 | local methods = mt.__index 34 | 35 | local rd = {} -- read functions 36 | local wr = {} -- write indices 37 | 38 | -- position components 39 | rd.x = function(self) return self[1] end 40 | rd.y = function(self) return self[2] end 41 | rd.w = function(self) return self[3] end 42 | rd.h = function(self) return self[4] end 43 | wr.x, wr.y, wr.w, wr.h = 1,2,3,4 44 | 45 | mt.__index = function(self, key) 46 | local f = rd[key] 47 | if f then return f(self) end 48 | return methods[key] 49 | end 50 | 51 | mt.__newindex = function(self, key, val) 52 | if type(key) == "number" or key == "dimensions" then 53 | rawset(self, key, val) 54 | return 55 | end 56 | local i = wr[key] 57 | if i then 58 | rawset(self, i, val) 59 | else 60 | error("cannot write field '" .. key .."'", 2) 61 | end 62 | end 63 | 64 | moonglmath.torect = function(t) setmetatable(t, mt) return t end 65 | 66 | end 67 | -------------------------------------------------------------------------------- /moonglmath/utils.lua: -------------------------------------------------------------------------------- 1 | -- The MIT License (MIT) 2 | -- 3 | -- Copyright (c) 2016 Stefano Trettel 4 | -- 5 | -- Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | -- 7 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 8 | -- of this software and associated documentation files (the "Software"), to deal 9 | -- in the Software without restriction, including without limitation the rights 10 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | -- copies of the Software, and to permit persons to whom the Software is 12 | -- furnished to do so, subject to the following conditions: 13 | -- 14 | -- The above copyright notice and this permission notice shall be included in all 15 | -- copies or substantial portions of the Software. 16 | -- 17 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | -- SOFTWARE. 24 | -- 25 | 26 | -- 27 | -- Adds named-components access to MoonGLMATH boxes 28 | -- ( v.minx becomes an alias for b[1], v.maxx becomes an alias for b[2], and so on). 29 | -- 30 | 31 | --local glmath = require("moonglmath") 32 | --local mt = getmetatable(glmath.box2()) 33 | do 34 | local glmath = moonglmath 35 | 36 | local function dumpdata(data, filename, mode) 37 | -- Dumps data in a file to be used with gnuplot 38 | -- (eg. gnuplot> plot "data.log" using 1:2 with lines) 39 | -- 'data' = sequence of numbers (array without gaps starting from index=1) 40 | -- 'filename'= name of file where to dump the data 41 | local file = assert(io.open(filename, mode or "w")) 42 | for i,v in ipairs(data) do 43 | file:write(string.format("%u %.9f\n",i,v)) 44 | end 45 | file:close() 46 | end 47 | 48 | local function stats(data) 49 | -- Computes mean, variax, minimum and maximum over 50 | -- the sequence of numbers contained in data 51 | local max,min = 0, math.huge 52 | local mean, delta, m2, var = 0, 0, 0, 0 53 | for i=1,#data do 54 | local d = data[i] 55 | if d < min then min = d end 56 | if d > max then max = d end 57 | delta = d - mean 58 | mean = mean + delta/i 59 | m2 = m2 + delta*(d-mean) 60 | end 61 | if #data > 1 then 62 | var = m2 / (#data-1) 63 | end 64 | return mean, var, min, max 65 | end 66 | 67 | moonglmath.stats = stats 68 | moonglmath.dumpdata = dumpdata 69 | 70 | end 71 | -------------------------------------------------------------------------------- /moonglmath/vecsugar.lua: -------------------------------------------------------------------------------- 1 | -- The MIT License (MIT) 2 | -- 3 | -- Copyright (c) 2016 Stefano Trettel 4 | -- 5 | -- Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | -- 7 | -- Permission is hereby granted, free of charge, to any person obtaining a copy 8 | -- of this software and associated documentation files (the "Software"), to deal 9 | -- in the Software without restriction, including without limitation the rights 10 | -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | -- copies of the Software, and to permit persons to whom the Software is 12 | -- furnished to do so, subject to the following conditions: 13 | -- 14 | -- The above copyright notice and this permission notice shall be included in all 15 | -- copies or substantial portions of the Software. 16 | -- 17 | -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | -- SOFTWARE. 24 | -- 25 | 26 | 27 | -- 28 | -- Adds named-components access to MoonGLMATH vectors 29 | -- ( v.x becomes an alias for v[1], v.y becomes an alias for v[2], and so on). 30 | -- 31 | -- 32 | -- 33 | -- 34 | 35 | --local glmath = require("moonglmath") 36 | --local mt = getmetatable(glmath.vec2()) 37 | do 38 | local mt = getmetatable(moonglmath.vec2()) 39 | local methods = mt.__index 40 | 41 | local rd = {} -- read functions 42 | local wr = {} -- write indices 43 | 44 | -- position components 45 | rd.x = function(self) return self[1] end 46 | rd.y = function(self) return self[2] end 47 | rd.z = function(self) return self[3] end 48 | rd.w = function(self) return self[4] end 49 | wr.x, wr.y, wr.z, wr.w = 1,2,3,4 50 | 51 | -- color components 52 | rd.r = function(self) return self[1] end 53 | rd.g = function(self) return self[2] end 54 | rd.b = function(self) return self[3] end 55 | rd.a = function(self) return self[4] end 56 | wr.r, wr.g, wr.b, wr.a = 1,2,3,4 57 | 58 | -- texture components 59 | rd.s = function(self) return self[1] end 60 | rd.t = function(self) return self[2] end 61 | rd.p = function(self) return self[3] end 62 | rd.q = function(self) return self[4] end 63 | wr.s, wr.t, wr.p, wr.q = 1,2,3,4 64 | 65 | mt.__index = function(self, key) 66 | local f = rd[key] 67 | if f then return f(self) end 68 | return methods[key] 69 | end 70 | 71 | mt.__newindex = function(self, key, val) 72 | if type(key) == "number" or key == "size" or key == "type" then 73 | rawset(self, key, val) 74 | return 75 | end 76 | local i = wr[key] 77 | if i then 78 | rawset(self, i, val) 79 | else 80 | error("cannot write field '" .. key .."'", 2) 81 | end 82 | end 83 | 84 | moonglmath.tovec2 = function(t) setmetatable(t, mt) t.type="column" t.size=2 return t end 85 | moonglmath.tovec3 = function(t) setmetatable(t, mt) t.type="column" t.size=3 return t end 86 | moonglmath.tovec4 = function(t) setmetatable(t, mt) t.type="column" t.size=4 return t end 87 | moonglmath.tovec2r = function(t) setmetatable(t, mt) t.type="row" t.size=2 return t end 88 | moonglmath.tovec3r = function(t) setmetatable(t, mt) t.type="row" t.size=3 return t end 89 | moonglmath.tovec4r = function(t) setmetatable(t, mt) t.type="row" t.size=4 return t end 90 | 91 | end 92 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | 2 | ifdef MINGW_PREFIX 3 | MINGW=1 4 | else 5 | OS=$(shell uname) 6 | ifeq ($(OS),Darwin) 7 | MACOS=1 8 | else 9 | LINUX=1 10 | endif 11 | endif 12 | 13 | 14 | # Lua version 15 | LUAVER?=$(shell lua -e 'print(string.match(_VERSION, "%d+%.%d+") or "5.3")') 16 | ifeq ($(LUAVER),) 17 | # lua-interpreter not found 18 | LUAVER=5.3 19 | endif 20 | 21 | ifdef MACOS 22 | DLL_EXT=dylib 23 | endif 24 | 25 | ifdef LINUX 26 | DLL_EXT=so 27 | endif 28 | 29 | ifdef MINGW 30 | DLL_EXT=dll 31 | endif 32 | 33 | # Base install directory 34 | ifdef MACOS 35 | PREFIX?=/usr/local 36 | endif 37 | 38 | ifdef LINUX 39 | PREFIX?=/usr/local 40 | endif 41 | 42 | ifdef MINGW 43 | PREFIX?=$(MINGW_PREFIX) 44 | endif 45 | 46 | 47 | # Directory where to install Lua modules 48 | L_DIR=$(PREFIX)/share/lua/$(LUAVER) 49 | # Directory where to install Lua C modules 50 | C_DIR=$(PREFIX)/lib/lua/$(LUAVER) 51 | # Directory where to install C headers 52 | H_DIR=$(PREFIX)/include 53 | # Directory where to install C libraries 54 | S_DIR=$(PREFIX)/lib 55 | 56 | ifeq ($(D),1) 57 | DEBUG=1 58 | endif 59 | 60 | Tgt := moonglmath 61 | Src := $(wildcard *.c) 62 | Objs := $(Src:.c=.o) 63 | 64 | COPT += -O2 65 | #COPT += -O0 -g 66 | COPT += -Wall -Wextra -Wpedantic 67 | COPT += -DCOMPAT53_PREFIX=moonglmath_compat_ 68 | COPT += -std=gnu99 69 | COPT += -DLUAVER=$(LUAVER) 70 | 71 | ifdef MACOS 72 | COPT += -fpic 73 | COPT += -DMACOS 74 | INCDIR = -I/usr/include -I/usr/include/lua$(LUAVER) -I$(PREFIX)/include/lua$(LUAVER) 75 | LIBDIR = -L/usr/lib -L$(PREFIX)/lib 76 | LIBS = -lm -llua$(LUAVER) 77 | endif 78 | ifdef LINUX 79 | COPT += -fpic 80 | COPT += -DLINUX 81 | INCDIR = -I/usr/include -I/usr/include/lua$(LUAVER) 82 | LIBDIR = -L/usr/lib 83 | LIBS = -lm 84 | endif 85 | ifdef MINGW 86 | COPT += -DMINGW 87 | LIBS = -lm -llua 88 | endif 89 | ifdef DEBUG 90 | COPT += -DDEBUG 91 | #COPT += -Wfatal-errors 92 | COPT += -Wshadow -Wsign-compare -Wundef -Wwrite-strings 93 | COPT += -Wdisabled-optimization -Wdeclaration-after-statement 94 | COPT += -Wmissing-prototypes -Wstrict-prototypes -Wnested-externs 95 | COPT += -Wc++-compat -Wold-style-definition 96 | endif 97 | 98 | override CFLAGS = $(COPT) $(INCDIR) 99 | 100 | default: build 101 | 102 | where: 103 | @echo "PREFIX="$(PREFIX) 104 | @echo "LUAVER="$(LUAVER) 105 | @echo $(L_DIR) 106 | @echo $(C_DIR) 107 | @echo $(H_DIR) 108 | @echo $(S_DIR) 109 | 110 | clean: 111 | @-rm -f *.so *.dll *.o *.err *.map *.S *~ *.log 112 | @-rm -f $(Tgt).symbols 113 | 114 | install: 115 | @-mkdir -pv $(H_DIR) 116 | @-mkdir -pv $(C_DIR) 117 | @-mkdir -pv $(S_DIR) 118 | @-mkdir -pv $(L_DIR) 119 | @-cp -fpv $(Tgt).h $(H_DIR) 120 | @-cp -fpv $(Tgt)_local.h $(H_DIR) 121 | @-cp -fpvr ../$(Tgt) $(L_DIR) 122 | ifdef MACOS 123 | @-cp -fpv $(Tgt).$(DLL_EXT) $(C_DIR) 124 | @-ln -fsv $(C_DIR)/$(Tgt).$(DLL_EXT) $(S_DIR)/lib$(Tgt).$(DLL_EXT) 125 | @-ln -fsv $(C_DIR)/$(Tgt).$(DLL_EXT) $(C_DIR)/$(Tgt).so 126 | endif 127 | ifdef LINUX 128 | @-cp -fpv $(Tgt).so $(C_DIR) 129 | @-ln -fsv $(C_DIR)/$(Tgt).so $(S_DIR)/lib$(Tgt).so 130 | endif 131 | ifdef MINGW 132 | @-cp -fpv $(Tgt).dll $(C_DIR) 133 | endif 134 | 135 | uninstall: 136 | @-rm -f $(H_DIR)/$(Tgt).h 137 | @-rm -f $(H_DIR)/$(Tgt)_local.h 138 | @-rm -f $(C_DIR)/$(Tgt).so 139 | @-rm -f $(S_DIR)/lib$(Tgt).so 140 | @-rm -fr $(L_DIR)/$(Tgt) 141 | @-rm -f $(C_DIR)/$(Tgt).dll 142 | 143 | build: clean $(Tgt) 144 | 145 | symbols: build 146 | @objdump -T $(Tgt).so > $(Tgt).symbols 147 | 148 | $(Tgt): $(Objs) 149 | ifdef MACOS 150 | @-$(CC) -shared -o $(Tgt).$(DLL_EXT) $(Objs) $(LIBDIR) $(LIBS) 151 | endif 152 | ifdef LINUX 153 | @-$(CC) -shared -o $(Tgt).so $(Objs) $(LIBDIR) $(LIBS) 154 | endif 155 | ifdef MINGW 156 | @-$(CC) -shared -o $(Tgt).dll $(Objs) $(LIBDIR) $(LIBS) 157 | endif 158 | @-rm -f $(Objs) 159 | @echo 160 | 161 | -------------------------------------------------------------------------------- /src/_make: -------------------------------------------------------------------------------- 1 | make LUAVER=5.4 D=$1 && sudo make LUAVER=5.4 install 2 | -------------------------------------------------------------------------------- /src/box.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2016 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | /*------------------------------------------------------------------------------* 29 | | Check and push | 30 | *------------------------------------------------------------------------------*/ 31 | 32 | int testbox(lua_State *L, int arg, box_t b, size_t *dim) 33 | /* Tests if the element at arg is a box and sets b and *dim accordingly 34 | * (unless they are passed as 0). 35 | */ 36 | { 37 | size_t i; 38 | size_t dim_; 39 | if(!testmetatable(L, arg, BOX_MT)) return 0; 40 | 41 | lua_getfield(L, arg, "dimensions"); 42 | dim_ = luaL_checkinteger(L, -1); 43 | lua_pop(L, 1); 44 | checkboxdim(L, dim_); 45 | 46 | if(dim != NULL) *dim = dim_; 47 | if(b != NULL) 48 | { 49 | box_clear(b); 50 | for(i=0; i < 2*dim_; i++) 51 | { 52 | lua_geti(L, arg, i+1); 53 | b[i] = luaL_checknumber(L, -1); 54 | lua_pop(L, 1); 55 | } 56 | } 57 | return 1; 58 | } 59 | 60 | int checkbox(lua_State *L, int arg, box_t b, size_t *dim) 61 | /* Same as testbox(), but raises a error if the test fails. 62 | */ 63 | { 64 | if(!testbox(L, arg, b, dim)) 65 | return luaL_argerror(L, arg, lua_pushfstring(L, "%s expected", BOX_MT)); 66 | return 1; 67 | } 68 | 69 | 70 | int pushbox(lua_State *L, box_t b, size_t dim) 71 | /* dim = 2 or 3 72 | */ 73 | { 74 | size_t i; 75 | checkboxdim(L, dim); 76 | lua_newtable(L); 77 | setmetatable(L, BOX_MT); 78 | for(i=0; i<2*dim; i++) 79 | { 80 | lua_pushnumber(L, b[i]); 81 | lua_seti(L, -2, i+1); 82 | } 83 | lua_pushinteger(L, dim); 84 | lua_setfield(L, -2, "dimensions"); 85 | return 1; 86 | } 87 | 88 | /*------------------------------------------------------------------------------* 89 | | Box | 90 | *------------------------------------------------------------------------------*/ 91 | 92 | static int Box(lua_State *L, size_t dim) 93 | /* creates a box of dimensions 'dim', from a box or a list of values 94 | * the size is adapted by discarding exceeding values or adding zeros 95 | * in lieu of missing values. 96 | * boxN(b) 97 | * boxN([x1 ,[x2,...[,x2N]]]) 98 | */ 99 | { 100 | box_t b; 101 | size_t bdim, i, arg; 102 | arg = 1; 103 | if(testbox(L, arg, b, &bdim)) 104 | return pushbox(L, b, bdim); 105 | checkboxdim(L, dim); 106 | for(i = 0; i < 2*dim; i++) 107 | b[i] = luaL_optnumber(L, arg++, 0); 108 | return pushbox(L, b, dim); 109 | } 110 | 111 | static int Box2(lua_State *L) { return Box(L, 2); } 112 | static int Box3(lua_State *L) { return Box(L, 3); } 113 | 114 | static int IsBox(lua_State *L, size_t dim) 115 | { 116 | size_t bdim; 117 | if(!testbox(L, 1, NULL, &bdim)) 118 | lua_pushboolean(L, 0); 119 | else 120 | lua_pushboolean(L, (bdim==dim)); 121 | return 1; 122 | } 123 | 124 | static int IsBox2(lua_State *L) { return IsBox(L, 2); } 125 | static int IsBox3(lua_State *L) { return IsBox(L, 3); } 126 | 127 | /*------------------------------------------------------------------------------* 128 | | ToString | 129 | *------------------------------------------------------------------------------*/ 130 | 131 | static int ToString_(lua_State *L, box_t b, size_t dim) 132 | /* With snprintf because lua_pushfstring does not support the %g conversion specifier */ 133 | { 134 | #define SZ 512 135 | #define space (SZ-p) 136 | char str[SZ]; 137 | int p=0; 138 | switch(dim) 139 | { 140 | case 2: p = snprintf(str, space, "[ "FMT", "FMT", "FMT", "FMT" ]", 141 | b[0], b[1], b[2], b[3]); break; 142 | case 3: p = snprintf(str, space, "[ "FMT", "FMT", "FMT", "FMT", "FMT", "FMT" ]", 143 | b[0], b[1], b[2], b[3], b[4], b[5]); break; 144 | default: 145 | return luaL_error(L, UNEXPECTED_ERROR); 146 | } 147 | if(space<0) 148 | { 149 | /* truncate */ 150 | p = SZ - 5; 151 | p+=snprintf(str+p, space, " ..."); 152 | lua_pushlstring(L, str, p); 153 | return 1; 154 | } 155 | lua_pushlstring(L, str, p); 156 | return 1; 157 | #undef space 158 | #undef SZ 159 | } 160 | 161 | static int ToString(lua_State *L) 162 | { 163 | box_t b; 164 | size_t dim; 165 | checkbox(L, 1, b, &dim); 166 | return ToString_(L, b, dim); 167 | } 168 | 169 | 170 | static int Concat(lua_State *L) 171 | { 172 | box_t b; 173 | size_t dim; 174 | if(testbox(L, 1, b, &dim)) 175 | { 176 | ToString_(L, b, dim); 177 | lua_pushvalue(L, 2); 178 | } 179 | else if(testbox(L, 2, b, &dim)) 180 | { 181 | lua_pushvalue(L, 1); 182 | ToString_(L, b, dim); 183 | } 184 | else 185 | return unexpected(L); 186 | lua_concat(L, 2); 187 | return 1; 188 | } 189 | 190 | 191 | /*------------------------------------------------------------------------------* 192 | | Non-Lua functions (for internal use) | 193 | *------------------------------------------------------------------------------*/ 194 | 195 | //@@TBD 196 | 197 | /*------------------------------------------------------------------------------* 198 | | Metamethods | 199 | *------------------------------------------------------------------------------*/ 200 | 201 | static const struct luaL_Reg Metamethods[] = 202 | { 203 | { "__tostring", ToString }, 204 | { "__concat", Concat }, 205 | { NULL, NULL } /* sentinel */ 206 | }; 207 | 208 | static const struct luaL_Reg Methods[] = 209 | { 210 | { NULL, NULL } /* sentinel */ 211 | }; 212 | 213 | 214 | /*------------------------------------------------------------------------------* 215 | | Registration | 216 | *------------------------------------------------------------------------------*/ 217 | 218 | static const struct luaL_Reg Functions[] = 219 | { 220 | { "box2", Box2 }, 221 | { "box3", Box3 }, 222 | { "isbox2", IsBox2 }, 223 | { "isbox3", IsBox3 }, 224 | { NULL, NULL } /* sentinel */ 225 | }; 226 | 227 | void moonglmath_open_box(lua_State *L) 228 | { 229 | newmetatable(L, BOX_MT); 230 | metatable_setfuncs(L, BOX_MT, Metamethods, Methods); 231 | luaL_setfuncs(L, Functions, 0); 232 | } 233 | 234 | -------------------------------------------------------------------------------- /src/complex.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2018 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | /*------------------------------------------------------------------------------* 29 | | Check and push | 30 | *------------------------------------------------------------------------------*/ 31 | 32 | int testcomplex(lua_State *L, int arg, complex_t *z) 33 | /* Tests if the element at arg is a complex number and sets z accordingly 34 | * (unless it is passed as 0). 35 | * Accepts also a real number x, in which case z = x+I*0; 36 | */ 37 | { 38 | double x, y; 39 | if(lua_isnumber(L, arg)) 40 | { 41 | if(z != NULL) 42 | *z = lua_tonumber(L, arg); 43 | return 1; 44 | } 45 | 46 | if(!testmetatable(L, arg, COMPLEX_MT)) return 0; 47 | 48 | if(z != NULL) 49 | { 50 | lua_geti(L, arg, 1); 51 | x = luaL_checknumber(L, -1); 52 | lua_pop(L, 1); 53 | lua_geti(L, arg, 2); 54 | y = luaL_checknumber(L, -1); 55 | lua_pop(L, 1); 56 | *z = x + I*y; 57 | } 58 | return 1; 59 | } 60 | 61 | int checkcomplex(lua_State *L, int arg, complex_t *z) 62 | /* Same as testcomplex(), but raises an error if the test fails. 63 | */ 64 | { 65 | if(!testcomplex(L, arg, z)) 66 | return luaL_argerror(L, arg, lua_pushfstring(L, "%s expected", COMPLEX_MT)); 67 | return 1; 68 | } 69 | 70 | 71 | int pushcomplex(lua_State *L, complex_t z) 72 | { 73 | lua_newtable(L); 74 | setmetatable(L, COMPLEX_MT); 75 | lua_pushnumber(L, creal(z)); 76 | lua_seti(L, -2, 1); 77 | lua_pushnumber(L, cimag(z)); 78 | lua_seti(L, -2, 2); 79 | return 1; 80 | } 81 | 82 | /*------------------------------------------------------------------------------* 83 | | | 84 | *------------------------------------------------------------------------------*/ 85 | 86 | static int ComplexArray(lua_State *L) 87 | { 88 | double x, y; 89 | int i, j, tbl; 90 | int n = luaL_len(L, 1); 91 | lua_newtable(L); 92 | tbl = lua_gettop(L); 93 | j = 0; 94 | for(i=0; i < n; ) 95 | { 96 | lua_rawgeti(L, 1, ++i); 97 | x = luaL_optnumber(L, -1, 0); 98 | lua_rawgeti(L, 1, ++i); 99 | y = luaL_optnumber(L, -1, 0); 100 | lua_pop(L, 2); 101 | pushcomplex(L, x + I*y); 102 | lua_rawseti(L, tbl, ++j); 103 | } 104 | return 1; 105 | } 106 | 107 | static int Complex(lua_State *L) 108 | /* creates a complex number from another on or from its real and imag parts 109 | * complex() --> 0+0i 110 | * complex(x, y) --> x+yi 111 | * complex(z) --> z 112 | * complex({x1, y1, x2, y2, ...}) --> {z1, z2, ...} 113 | */ 114 | { 115 | complex_t z; 116 | double x, y; 117 | int t = lua_type(L, 1); 118 | 119 | if((t == LUA_TNONE)||(t == LUA_TNIL)||(t == LUA_TNUMBER)) 120 | { 121 | x = luaL_optnumber(L, 1, 0); 122 | y = luaL_optnumber(L, 2, 0); 123 | z = x + I*y; 124 | } 125 | else if(t == LUA_TTABLE && !testmetatable(L, 1, COMPLEX_MT)) 126 | return ComplexArray(L); 127 | else 128 | checkcomplex(L, 1, &z); 129 | return pushcomplex(L, z); 130 | } 131 | 132 | static int IsComplex(lua_State *L) 133 | { 134 | if(!testcomplex(L, 1, NULL)) 135 | lua_pushboolean(L, 0); 136 | else 137 | lua_pushboolean(L, 1); 138 | return 1; 139 | } 140 | 141 | /*------------------------------------------------------------------------------* 142 | | ToString | 143 | *------------------------------------------------------------------------------*/ 144 | 145 | static int ToString_(lua_State *L, complex_t z) 146 | /* With snprintf because lua_pushfstring does not support the %g conversion specifier */ 147 | { 148 | #define SZ 512 149 | #define space (SZ-p) 150 | char str[SZ]; 151 | int p=0; 152 | if(cimag(z)>=0) 153 | p = snprintf(str, space, ""FMT"+"FMT"i", creal(z), cimag(z)); 154 | else 155 | p = snprintf(str, space, ""FMT""FMT"i", creal(z), cimag(z)); 156 | lua_pushlstring(L, str, p); 157 | return 1; 158 | #undef space 159 | #undef SZ 160 | } 161 | 162 | static int ToString(lua_State *L) 163 | { 164 | complex_t z; 165 | checkcomplex(L, 1, &z); 166 | return ToString_(L, z); 167 | } 168 | 169 | 170 | static int Concat(lua_State *L) 171 | { 172 | complex_t z; 173 | if(testcomplex(L, 1, &z)) 174 | { 175 | ToString_(L, z); 176 | lua_pushvalue(L, 2); 177 | } 178 | else if(testcomplex(L, 2, &z)) 179 | { 180 | lua_pushvalue(L, 1); 181 | ToString_(L, z); 182 | } 183 | else 184 | return unexpected(L); 185 | lua_concat(L, 2); 186 | return 1; 187 | } 188 | 189 | /*------------------------------------------------------------------------------* 190 | | C99 complex.h functions | 191 | *------------------------------------------------------------------------------*/ 192 | 193 | #define FUNC(Func, what) \ 194 | static int Func(lua_State *L) \ 195 | { \ 196 | complex_t z; \ 197 | checkcomplex(L, 1, &z); \ 198 | lua_pushnumber(L, what(z)); \ 199 | return 1; \ 200 | } 201 | 202 | FUNC(Carg, carg) 203 | FUNC(Cimag, cimag) 204 | FUNC(Creal, creal) 205 | 206 | #undef FUNC 207 | 208 | #define FUNC(Func, what) \ 209 | static int Func(lua_State *L) \ 210 | { \ 211 | complex_t z; \ 212 | checkcomplex(L, 1, &z); \ 213 | return pushcomplex(L, what(z)); \ 214 | } 215 | 216 | FUNC(Csin, csin) 217 | FUNC(Ccos, ccos) 218 | FUNC(Ctan, ctan) 219 | FUNC(Casin, casin) 220 | FUNC(Cacos, cacos) 221 | FUNC(Catan, catan) 222 | FUNC(Csinh, csinh) 223 | FUNC(Ccosh, ccosh) 224 | FUNC(Ctanh, ctanh) 225 | FUNC(Casinh, casinh) 226 | FUNC(Cacosh, cacosh) 227 | FUNC(Catanh, catanh) 228 | FUNC(Cproj, cproj) 229 | FUNC(Clog, clog) 230 | FUNC(Cexp, cexp) 231 | FUNC(Csqrt, csqrt) 232 | 233 | #undef FUNC 234 | 235 | /*------------------------------------------------------------------------------* 236 | | Metamethods | 237 | *------------------------------------------------------------------------------*/ 238 | 239 | static int Unm(lua_State *L) 240 | { 241 | complex_t z; 242 | checkcomplex(L, 1, &z); 243 | return pushcomplex(L, -z); 244 | } 245 | 246 | #define FUNC(Func, what) \ 247 | static int Func(lua_State *L) \ 248 | { \ 249 | complex_t z, z1; \ 250 | checkcomplex(L, 1, &z); \ 251 | checkcomplex(L, 2, &z1); \ 252 | return pushcomplex(L, z what z1); \ 253 | } 254 | 255 | FUNC(Add, +) 256 | FUNC(Sub, -) 257 | FUNC(Mul, *) 258 | FUNC(Div, /) 259 | 260 | #undef FUNC 261 | 262 | static int Pow(lua_State *L) 263 | { 264 | complex_t z, z1; 265 | checkcomplex(L, 1, &z); 266 | checkcomplex(L, 2, &z1); 267 | return pushcomplex(L, cpow(z, z1)); 268 | } 269 | 270 | 271 | int complex_Norm(lua_State *L) 272 | { 273 | complex_t z; 274 | checkcomplex(L, 1, &z); 275 | lua_pushnumber(L, cabs(z)); 276 | return 1; 277 | } 278 | 279 | int complex_Norm2(lua_State *L) 280 | { 281 | complex_t z; 282 | double r; 283 | checkcomplex(L, 1, &z); 284 | r = cabs(z); 285 | lua_pushnumber(L, r*r); 286 | return 1; 287 | } 288 | 289 | int complex_Normalize(lua_State *L) 290 | { 291 | complex_t z; 292 | checkcomplex(L, 1, &z); 293 | return pushcomplex(L, z/cabs(z)); 294 | } 295 | 296 | int complex_Inv(lua_State *L) 297 | { 298 | complex_t z; 299 | checkcomplex(L, 1, &z); 300 | return pushcomplex(L, 1/z); 301 | } 302 | 303 | int complex_Parts(lua_State *L) 304 | { 305 | complex_t z; 306 | checkcomplex(L, 1, &z); 307 | lua_pushnumber(L, creal(z)); 308 | lua_pushnumber(L, cimag(z)); 309 | return 2; 310 | } 311 | 312 | int complex_Conj(lua_State *L) 313 | { 314 | complex_t z; 315 | checkcomplex(L, 1, &z); 316 | return pushcomplex(L, conj(z)); 317 | } 318 | 319 | static const struct luaL_Reg Metamethods[] = 320 | { 321 | { "__tostring", ToString }, 322 | { "__concat", Concat }, 323 | { "__unm", Unm }, 324 | { "__add", Add }, 325 | { "__sub", Sub }, 326 | { "__mul", Mul }, 327 | { "__div", Div }, 328 | { "__pow", Pow }, 329 | { NULL, NULL } /* sentinel */ 330 | }; 331 | 332 | static const struct luaL_Reg Methods[] = 333 | { 334 | { "parts", complex_Parts }, 335 | { "conj", complex_Conj }, 336 | { "norm", complex_Norm }, 337 | { "norm2", complex_Norm2 }, 338 | { "normalize", complex_Normalize }, 339 | { "inv", complex_Inv }, 340 | { "cabs", complex_Norm }, 341 | { "cpow", Pow }, 342 | { "carg", Carg }, 343 | { "cimag", Cimag }, 344 | { "creal", Creal }, 345 | { "csin", Csin }, 346 | { "ccos", Ccos }, 347 | { "ctan", Ctan }, 348 | { "casin", Casin }, 349 | { "cacos", Cacos }, 350 | { "catan", Catan }, 351 | { "csinh", Csinh }, 352 | { "ccosh", Ccosh }, 353 | { "ctanh", Ctanh }, 354 | { "casinh", Casinh }, 355 | { "cacosh", Cacosh }, 356 | { "catanh", Catanh }, 357 | { "cproj", Cproj }, 358 | { "clog", Clog }, 359 | { "cexp", Cexp }, 360 | { "csqrt", Csqrt }, 361 | { NULL, NULL } /* sentinel */ 362 | }; 363 | 364 | 365 | 366 | /*------------------------------------------------------------------------------* 367 | | Registration | 368 | *------------------------------------------------------------------------------*/ 369 | 370 | static const struct luaL_Reg Functions[] = 371 | { 372 | { "complex", Complex }, 373 | { "iscomplex", IsComplex }, 374 | // { "conj", complex_Conj }, --> in funcs.c 375 | { "cabs", complex_Norm }, 376 | { "cpow", Pow }, 377 | { "carg", Carg }, 378 | { "cimag", Cimag }, 379 | { "creal", Creal }, 380 | { "csin", Csin }, 381 | { "ccos", Ccos }, 382 | { "ctan", Ctan }, 383 | { "casin", Casin }, 384 | { "cacos", Cacos }, 385 | { "catan", Catan }, 386 | { "csinh", Csinh }, 387 | { "ccosh", Ccosh }, 388 | { "ctanh", Ctanh }, 389 | { "casinh", Casinh }, 390 | { "cacosh", Cacosh }, 391 | { "catanh", Catanh }, 392 | { "cproj", Cproj }, 393 | { "clog", Clog }, 394 | { "cexp", Cexp }, 395 | { "csqrt", Csqrt }, 396 | { NULL, NULL } /* sentinel */ 397 | }; 398 | 399 | void moonglmath_open_complex(lua_State *L) 400 | { 401 | newmetatable(L, COMPLEX_MT); 402 | metatable_setfuncs(L, COMPLEX_MT, Metamethods, Methods); 403 | luaL_setfuncs(L, Functions, 0); 404 | } 405 | 406 | -------------------------------------------------------------------------------- /src/datahandling.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2018 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | /* @@TODO: what if host and device have different endianness? 29 | */ 30 | 31 | size_t sizeoftype(int type) 32 | { 33 | switch(type) 34 | { 35 | case MOONGLMATH_TYPE_CHAR: return sizeof(int8_t); 36 | case MOONGLMATH_TYPE_UCHAR: return sizeof(uint8_t); 37 | case MOONGLMATH_TYPE_SHORT: return sizeof(int16_t); 38 | case MOONGLMATH_TYPE_USHORT: return sizeof(uint16_t); 39 | case MOONGLMATH_TYPE_INT: return sizeof(int32_t); 40 | case MOONGLMATH_TYPE_UINT: return sizeof(uint32_t); 41 | case MOONGLMATH_TYPE_LONG: return sizeof(int64_t); 42 | case MOONGLMATH_TYPE_ULONG: return sizeof(uint64_t); 43 | case MOONGLMATH_TYPE_FLOAT: return sizeof(float); 44 | case MOONGLMATH_TYPE_DOUBLE: return sizeof(double); 45 | default: 46 | return 0; 47 | } 48 | return 0; 49 | } 50 | 51 | static int Sizeof(lua_State *L) 52 | /* size = sizeof(type) */ 53 | { 54 | int type = checktype(L, 1); 55 | lua_pushinteger(L, sizeoftype(type)); 56 | return 1; 57 | } 58 | 59 | static int Flatten1_(lua_State *L, int table_index, int cur_index, int arg) 60 | { 61 | int len, i, top, m, n=0; 62 | 63 | if(lua_type(L, arg) != LUA_TTABLE) 64 | return luaL_error(L, "table expected"); 65 | 66 | lua_len(L, arg); 67 | len = lua_tointeger(L, -1); 68 | lua_pop(L, 1); 69 | 70 | if(len==0) return n; 71 | 72 | for(i=1; i<=len; i++) 73 | { 74 | lua_geti(L, arg, i); 75 | top = lua_gettop(L); 76 | if(lua_type(L, top) == LUA_TTABLE) 77 | { 78 | m = Flatten1_(L, table_index, cur_index, top); 79 | n += m; 80 | cur_index += m; 81 | lua_remove(L, top); 82 | } 83 | else 84 | { 85 | n++; 86 | cur_index++; 87 | lua_rawseti(L, table_index, cur_index); 88 | } 89 | } 90 | return n; 91 | } 92 | 93 | int toflattable(lua_State *L, int arg) 94 | /* Creates a flat table with all the arguments starting from arg, and leaves 95 | * it on top of the stack. 96 | */ 97 | { 98 | int table_index, last_arg, i, n; 99 | if(lua_type(L, arg) == LUA_TTABLE) 100 | { 101 | lua_newtable(L); 102 | n = Flatten1_(L, lua_gettop(L), 0, arg); 103 | } 104 | else 105 | { 106 | /* create a table with all the arguments, and flatten it */ 107 | last_arg = lua_gettop(L); 108 | lua_newtable(L); 109 | table_index = lua_gettop(L); 110 | for(i=arg; i <= last_arg; i++) 111 | { 112 | lua_pushvalue(L, i); 113 | lua_rawseti(L, table_index, i-arg+1); 114 | } 115 | lua_newtable(L); 116 | n = Flatten1_(L, lua_gettop(L), 0, table_index); 117 | } 118 | return n; 119 | } 120 | 121 | static int Flatten(lua_State *L) 122 | { 123 | int n, i, table_index; 124 | n = toflattable(L, 1); 125 | table_index = lua_gettop(L); 126 | luaL_checkstack(L, n, "too many elements, cannot grow Lua stack"); 127 | for(i = 0; i < n; i++) 128 | lua_rawgeti(L, table_index, i+1); 129 | return n; 130 | } 131 | 132 | static int FlattenTable(lua_State *L) 133 | { 134 | toflattable(L, 1); 135 | return 1; 136 | } 137 | 138 | /*-----------------------------------------------------------------------------*/ 139 | 140 | #define PACK(T, what) /* what= number or integer */ \ 141 | static int Pack##T(lua_State *L, size_t n, void *dst, size_t dstsize, int *faulty_element) \ 142 | { \ 143 | int isnum; \ 144 | size_t i; \ 145 | T *data = (T*)dst; \ 146 | if(faulty_element) *faulty_element = 0; \ 147 | if(dstsize < (n * sizeof(T))) \ 148 | return ERR_LENGTH; \ 149 | for(i = 0; i < n; i++) \ 150 | { \ 151 | lua_rawgeti(L, -1, i+1); \ 152 | data[i] = lua_to##what##x(L, -1, &isnum); \ 153 | if(!isnum) \ 154 | { \ 155 | if(faulty_element) *faulty_element = i+1; \ 156 | return ERR_TYPE; /* element i+1 is not a #what */ \ 157 | } \ 158 | lua_pop(L, 1); \ 159 | } \ 160 | return 0; \ 161 | } 162 | 163 | #define PACK_NUMBERS(T) PACK(T, number) 164 | #define PACK_INTEGERS(T) PACK(T, integer) 165 | 166 | PACK_NUMBERS(float) 167 | PACK_NUMBERS(double) 168 | PACK_INTEGERS(int8_t) 169 | PACK_INTEGERS(uint8_t) 170 | PACK_INTEGERS(int16_t) 171 | PACK_INTEGERS(uint16_t) 172 | PACK_INTEGERS(int32_t) 173 | PACK_INTEGERS(uint32_t) 174 | PACK_INTEGERS(int64_t) 175 | PACK_INTEGERS(uint64_t) 176 | 177 | static int Pack(lua_State *L) 178 | { 179 | int err = 0; 180 | void *dst = NULL; 181 | size_t dstsize = 0; 182 | int type = checktype(L, 1); 183 | size_t n = toflattable(L, 2); 184 | switch(type) 185 | { 186 | #define P(T) do { dstsize = n * sizeof(T); \ 187 | dst = Malloc(L, dstsize); \ 188 | err = Pack##T(L, n, dst, dstsize, NULL); } while(0) 189 | 190 | case MOONGLMATH_TYPE_CHAR: P(int8_t); break; 191 | case MOONGLMATH_TYPE_UCHAR: P(uint8_t); break; 192 | case MOONGLMATH_TYPE_SHORT: P(int16_t); break; 193 | case MOONGLMATH_TYPE_USHORT: P(uint16_t); break; 194 | case MOONGLMATH_TYPE_INT: P(int32_t); break; 195 | case MOONGLMATH_TYPE_UINT: P(uint32_t); break; 196 | case MOONGLMATH_TYPE_LONG: P(int64_t); break; 197 | case MOONGLMATH_TYPE_ULONG: P(uint64_t); break; 198 | case MOONGLMATH_TYPE_FLOAT: P(float); break; 199 | case MOONGLMATH_TYPE_DOUBLE: P(double); break; 200 | default: 201 | return unexpected(L); 202 | #undef P 203 | } 204 | if(err) 205 | { 206 | Free(L, dst); 207 | return luaL_argerror(L, 2, errstring(err)); 208 | } 209 | lua_pushlstring(L, (char*)dst, dstsize); 210 | Free(L, dst); 211 | return 1; 212 | } 213 | 214 | /*-----------------------------------------------------------------------------*/ 215 | 216 | #define UNPACK(T, what) /* what= number or integer */ \ 217 | static int Unpack##T(lua_State *L, const void* data, size_t len) \ 218 | { \ 219 | size_t n; \ 220 | size_t i=0; \ 221 | if((len < sizeof(T)) || (len % sizeof(T)) != 0) \ 222 | return ERR_LENGTH; \ 223 | n = len / sizeof(T); \ 224 | lua_newtable(L); \ 225 | for(i = 0; i < n; i++) \ 226 | { \ 227 | lua_push##what(L, ((T*)data)[i]); \ 228 | lua_rawseti(L, -2, i+1); \ 229 | } \ 230 | return 0; \ 231 | } 232 | 233 | #define UNPACK_NUMBERS(T) UNPACK(T, number) 234 | #define UNPACK_INTEGERS(T) UNPACK(T, integer) 235 | 236 | 237 | UNPACK_NUMBERS(float) 238 | UNPACK_NUMBERS(double) 239 | UNPACK_INTEGERS(int8_t) 240 | UNPACK_INTEGERS(uint8_t) 241 | UNPACK_INTEGERS(int16_t) 242 | UNPACK_INTEGERS(uint16_t) 243 | UNPACK_INTEGERS(int32_t) 244 | UNPACK_INTEGERS(uint32_t) 245 | UNPACK_INTEGERS(int64_t) 246 | UNPACK_INTEGERS(uint64_t) 247 | 248 | static int Unpack_(lua_State *L, int type, const void *data, size_t len) 249 | { 250 | int err = 0; 251 | switch(type) 252 | { 253 | case MOONGLMATH_TYPE_CHAR: err = Unpackint8_t(L, data, len); break; 254 | case MOONGLMATH_TYPE_UCHAR: err = Unpackuint8_t(L, data, len); break; 255 | case MOONGLMATH_TYPE_SHORT: err = Unpackint16_t(L, data, len); break; 256 | case MOONGLMATH_TYPE_USHORT: err = Unpackuint16_t(L, data, len); break; 257 | case MOONGLMATH_TYPE_INT: err = Unpackint32_t(L, data, len); break; 258 | case MOONGLMATH_TYPE_UINT: err = Unpackuint32_t(L, data, len); break; 259 | case MOONGLMATH_TYPE_LONG: err = Unpackint64_t(L, data, len); break; 260 | case MOONGLMATH_TYPE_ULONG: err = Unpackuint64_t(L, data, len); break; 261 | case MOONGLMATH_TYPE_FLOAT: err = Unpackfloat(L, data, len); break; 262 | case MOONGLMATH_TYPE_DOUBLE: err = Unpackdouble(L, data, len); break; 263 | default: 264 | return unexpected(L); 265 | } 266 | if(err) 267 | return luaL_error(L, errstring(err)); 268 | return 1; 269 | } 270 | 271 | 272 | static int Unpack(lua_State *L) 273 | { 274 | size_t len; 275 | int type = checktype(L, 1); 276 | const void *data = luaL_checklstring(L, 2, &len); 277 | return Unpack_(L, type, data, len); 278 | } 279 | 280 | /*-----------------------------------------------------------------------------*/ 281 | 282 | 283 | int testdata(lua_State *L, int type, size_t n, void *dst, size_t dstsize) 284 | /* expects, on top of the stack, a flat table containing n elements of the given type 285 | * dst must point to at least n * sizeoftype(type) bytes of memory, where 286 | * the data will be packed according to the given type 287 | */ 288 | { 289 | int err = 0; 290 | switch(type) 291 | { 292 | #define P(T) do { err = Pack##T(L, n, dst, dstsize, NULL); } while(0) 293 | case MOONGLMATH_TYPE_CHAR: P(int8_t); break; 294 | case MOONGLMATH_TYPE_UCHAR: P(uint8_t); break; 295 | case MOONGLMATH_TYPE_SHORT: P(int16_t); break; 296 | case MOONGLMATH_TYPE_USHORT: P(uint16_t); break; 297 | case MOONGLMATH_TYPE_INT: P(int32_t); break; 298 | case MOONGLMATH_TYPE_UINT: P(uint32_t); break; 299 | case MOONGLMATH_TYPE_LONG: P(int64_t); break; 300 | case MOONGLMATH_TYPE_ULONG: P(uint64_t); break; 301 | case MOONGLMATH_TYPE_FLOAT: P(float); break; 302 | case MOONGLMATH_TYPE_DOUBLE: P(double); break; 303 | default: 304 | return unexpected(L); 305 | #undef P 306 | } 307 | return err; 308 | } 309 | 310 | int checkdata(lua_State *L, int arg, int type, void *dst, size_t dstsize) 311 | { 312 | size_t n = toflattable(L, arg); 313 | int err = testdata(L, type, n, dst, dstsize); 314 | if(err) 315 | { 316 | lua_pop(L, 1); /* flat table */ 317 | return luaL_argerror(L, arg, errstring(err)); 318 | } 319 | return 0; 320 | } 321 | 322 | 323 | int pushdata(lua_State *L, int type, void *data, size_t datalen) 324 | { 325 | return Unpack_(L, type, data, datalen); 326 | } 327 | 328 | 329 | static const struct luaL_Reg Functions[] = 330 | { 331 | { "flatten", Flatten }, 332 | { "flatten_table", FlattenTable }, 333 | { "sizeof", Sizeof }, 334 | { "pack", Pack }, 335 | { "unpack", Unpack }, 336 | { NULL, NULL } /* sentinel */ 337 | }; 338 | 339 | void moonglmath_open_datahandling(lua_State *L) 340 | { 341 | luaL_setfuncs(L, Functions, 0); 342 | } 343 | 344 | -------------------------------------------------------------------------------- /src/enums.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2018 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | /*------------------------------------------------------------------------------* 29 | | Code<->string map for enumerations | 30 | *------------------------------------------------------------------------------*/ 31 | 32 | 33 | /* code <-> string record */ 34 | #define rec_t struct rec_s 35 | struct rec_s { 36 | RB_ENTRY(rec_s) CodeEntry; 37 | RB_ENTRY(rec_s) StringEntry; 38 | uint32_t domain; 39 | uint32_t code; /* (domain, code) = search key in code tree */ 40 | char *str; /* (domain, str) = search key in string tree */ 41 | }; 42 | 43 | /* compare functions */ 44 | static int cmp_code(rec_t *rec1, rec_t *rec2) 45 | { 46 | if(rec1->domain != rec2->domain) 47 | return (rec1->domain < rec2->domain ? -1 : rec1->domain > rec2->domain); 48 | return (rec1->code < rec2->code ? -1 : rec1->code > rec2->code); 49 | } 50 | 51 | static int cmp_str(rec_t *rec1, rec_t *rec2) 52 | { 53 | if(rec1->domain != rec2->domain) 54 | return (rec1->domain < rec2->domain ? -1 : rec1->domain > rec2->domain); 55 | return strcmp(rec1->str, rec2->str); 56 | } 57 | 58 | static RB_HEAD(CodeTree, rec_s) CodeHead = RB_INITIALIZER(&CodeHead); 59 | RB_PROTOTYPE_STATIC(CodeTree, rec_s, CodeEntry, cmp_code) 60 | RB_GENERATE_STATIC(CodeTree, rec_s, CodeEntry, cmp_code) 61 | 62 | static RB_HEAD(StringTree, rec_s) StringHead = RB_INITIALIZER(&StringHead); 63 | RB_PROTOTYPE_STATIC(StringTree, rec_s, StringEntry, cmp_str) 64 | RB_GENERATE_STATIC(StringTree, rec_s, StringEntry, cmp_str) 65 | 66 | static rec_t *code_remove(rec_t *rec) 67 | { return RB_REMOVE(CodeTree, &CodeHead, rec); } 68 | static rec_t *code_insert(rec_t *rec) 69 | { return RB_INSERT(CodeTree, &CodeHead, rec); } 70 | static rec_t *code_search(uint32_t domain, uint32_t code) 71 | { rec_t tmp; tmp.domain = domain; tmp.code = code; return RB_FIND(CodeTree, &CodeHead, &tmp); } 72 | static rec_t *code_first(uint32_t domain, uint32_t code) 73 | { rec_t tmp; tmp.domain = domain; tmp.code = code; return RB_NFIND(CodeTree, &CodeHead, &tmp); } 74 | static rec_t *code_next(rec_t *rec) 75 | { return RB_NEXT(CodeTree, &CodeHead, rec); } 76 | #if 0 77 | static rec_t *code_prev(rec_t *rec) 78 | { return RB_PREV(CodeTree, &CodeHead, rec); } 79 | static rec_t *code_min(void) 80 | { return RB_MIN(CodeTree, &CodeHead); } 81 | static rec_t *code_max(void) 82 | { return RB_MAX(CodeTree, &CodeHead); } 83 | static rec_t *code_root(void) 84 | { return RB_ROOT(&CodeHead); } 85 | #endif 86 | 87 | static rec_t *str_remove(rec_t *rec) 88 | { return RB_REMOVE(StringTree, &StringHead, rec); } 89 | static rec_t *str_insert(rec_t *rec) 90 | { return RB_INSERT(StringTree, &StringHead, rec); } 91 | static rec_t *str_search(uint32_t domain, const char* str) 92 | { rec_t tmp; tmp.domain = domain; tmp.str = (char*)str; return RB_FIND(StringTree, &StringHead, &tmp); } 93 | #if 0 94 | static rec_t *str_first(uint32_t domain, const char* str ) 95 | { rec_t tmp; tmp.domain = domain; tmp.str = str; return RB_NFIND(StringTree, &StringHead, &tmp); } 96 | static rec_t *str_next(rec_t *rec) 97 | { return RB_NEXT(StringTree, &StringHead, rec); } 98 | static rec_t *str_prev(rec_t *rec) 99 | { return RB_PREV(StringTree, &StringHead, rec); } 100 | static rec_t *str_min(void) 101 | { return RB_MIN(StringTree, &StringHead); } 102 | static rec_t *str_max(void) 103 | { return RB_MAX(StringTree, &StringHead); } 104 | static rec_t *str_root(void) 105 | { return RB_ROOT(&StringHead); } 106 | #endif 107 | 108 | 109 | static int enums_new(lua_State *L, uint32_t domain, uint32_t code, const char *str) 110 | { 111 | rec_t *rec; 112 | if((rec = (rec_t*)Malloc(L, sizeof(rec_t))) == NULL) 113 | return luaL_error(L, errstring(ERR_MEMORY)); 114 | 115 | memset(rec, 0, sizeof(rec_t)); 116 | rec->domain = domain; 117 | rec->code = code; 118 | rec->str = Strdup(L, str); 119 | if(code_search(domain, code) || str_search(domain, str)) 120 | { 121 | Free(L, rec->str); 122 | Free(L, rec); 123 | return unexpected(L); /* duplicate value */ 124 | } 125 | code_insert(rec); 126 | str_insert(rec); 127 | return 0; 128 | } 129 | 130 | static void enums_free(lua_State *L, rec_t* rec) 131 | { 132 | if(code_search(rec->domain, rec->code) == rec) 133 | code_remove(rec); 134 | if(str_search(rec->domain, rec->str) == rec) 135 | str_remove(rec); 136 | Free(L, rec->str); 137 | Free(L, rec); 138 | } 139 | 140 | void enums_free_all(lua_State *L) 141 | { 142 | rec_t *rec; 143 | while((rec = code_first(0, 0))) 144 | enums_free(L, rec); 145 | } 146 | 147 | #if 0 148 | uint32_t enums_code(uint32_t domain, const char *str, int* found) 149 | { 150 | rec_t *rec = str_search(domain, str); 151 | if(!rec) 152 | { *found = 0; return 0; } 153 | *found = 1; 154 | return rec->code; 155 | } 156 | 157 | const char* enums_string(uint32_t domain, uint32_t code) 158 | { 159 | rec_t *rec = code_search(domain, code); 160 | if(!rec) 161 | return NULL; 162 | return rec->str; 163 | } 164 | 165 | #endif 166 | 167 | 168 | uint32_t enums_test(lua_State *L, uint32_t domain, int arg, int *err) 169 | { 170 | rec_t *rec; 171 | const char *s = luaL_optstring(L, arg, NULL); 172 | 173 | if(!s) 174 | { *err = ERR_NOTPRESENT; return 0; } 175 | 176 | rec = str_search(domain, s); 177 | if(!rec) 178 | { *err = ERR_VALUE; return 0; } 179 | 180 | *err = ERR_SUCCESS; 181 | return rec->code; 182 | } 183 | 184 | uint32_t enums_check(lua_State *L, uint32_t domain, int arg) 185 | { 186 | rec_t *rec; 187 | const char *s = luaL_checkstring(L, arg); 188 | 189 | rec = str_search(domain, s); 190 | if(!rec) 191 | return luaL_argerror(L, arg, badvalue(L, s)); 192 | 193 | return rec->code; 194 | } 195 | 196 | int enums_push(lua_State *L, uint32_t domain, uint32_t code) 197 | { 198 | rec_t *rec = code_search(domain, code); 199 | 200 | if(!rec) 201 | return unexpected(L); 202 | 203 | lua_pushstring(L, rec->str); 204 | return 1; 205 | } 206 | 207 | int enums_values(lua_State *L, uint32_t domain) 208 | { 209 | int i; 210 | rec_t *rec; 211 | 212 | lua_newtable(L); 213 | i = 1; 214 | rec = code_first(domain, 0); 215 | while(rec) 216 | { 217 | if(rec->domain == domain) 218 | { 219 | lua_pushstring(L, rec->str); 220 | lua_rawseti(L, -2, i++); 221 | } 222 | rec = code_next(rec); 223 | } 224 | 225 | return 1; 226 | } 227 | 228 | 229 | uint32_t* enums_checklist(lua_State *L, uint32_t domain, int arg, uint32_t *count, int *err) 230 | { 231 | uint32_t* list; 232 | uint32_t i; 233 | 234 | *count = 0; 235 | *err = 0; 236 | if(lua_isnoneornil(L, arg)) 237 | { *err = ERR_NOTPRESENT; return NULL; } 238 | if(lua_type(L, arg) != LUA_TTABLE) 239 | { *err = ERR_TABLE; return NULL; } 240 | 241 | *count = luaL_len(L, arg); 242 | if(*count == 0) 243 | { *err = ERR_NOTPRESENT; return NULL; } 244 | 245 | list = (uint32_t*)MallocNoErr(L, sizeof(uint32_t) * (*count)); 246 | if(!list) 247 | { *count = 0; *err = ERR_MEMORY; return NULL; } 248 | 249 | for(i=0; i<*count; i++) 250 | { 251 | lua_rawgeti(L, arg, i+1); 252 | list[i] = enums_test(L, domain, -1, err); 253 | lua_pop(L, 1); 254 | if(*err) 255 | { Free(L, list); *count = 0; return NULL; } 256 | } 257 | return list; 258 | } 259 | 260 | void enums_freelist(lua_State *L, uint32_t *list) 261 | { 262 | if(!list) 263 | return; 264 | Free(L, list); 265 | } 266 | 267 | /*------------------------------------------------------------------------------* 268 | | | 269 | *------------------------------------------------------------------------------*/ 270 | 271 | static int Enum(lua_State *L) 272 | /* { strings } = glmath.enum('type') lists all the values for a given enum type */ 273 | { 274 | const char *s = luaL_checkstring(L, 1); 275 | #define CASE(xxx) if(strcmp(s, ""#xxx) == 0) return values##xxx(L) 276 | CASE(isrow); 277 | CASE(type); 278 | #undef CASE 279 | return 0; 280 | } 281 | 282 | static const struct luaL_Reg Functions[] = 283 | { 284 | { "enum", Enum }, 285 | { NULL, NULL } /* sentinel */ 286 | }; 287 | 288 | 289 | void moonglmath_open_enums(lua_State *L) 290 | { 291 | uint32_t domain; 292 | 293 | luaL_setfuncs(L, Functions, 0); 294 | 295 | /* Add all the code<->string mappings */ 296 | #define ADD(what, s) do { enums_new(L, domain, MOONGLMATH_##what, s); } while(0) 297 | domain = DOMAIN_ISROW; 298 | ADD(COLUMN, "column"); 299 | ADD(ROW, "row"); 300 | 301 | domain = DOMAIN_TYPE; 302 | ADD(TYPE_CHAR, "char"); 303 | ADD(TYPE_UCHAR, "uchar"); 304 | ADD(TYPE_SHORT, "short"); 305 | ADD(TYPE_USHORT, "ushort"); 306 | ADD(TYPE_INT, "int"); 307 | ADD(TYPE_UINT, "uint"); 308 | ADD(TYPE_LONG, "long"); 309 | ADD(TYPE_ULONG, "ulong"); 310 | ADD(TYPE_FLOAT, "float"); 311 | ADD(TYPE_DOUBLE, "double"); 312 | #undef ADD 313 | } 314 | 315 | -------------------------------------------------------------------------------- /src/enums.h: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2018 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef enumsDEFINED 27 | #define enumsDEFINED 28 | 29 | /* enums.c */ 30 | #define enums_free_all moonglmath_enums_free_all 31 | void enums_free_all(lua_State *L); 32 | #define enums_test moonglmath_enums_test 33 | uint32_t enums_test(lua_State *L, uint32_t domain, int arg, int *err); 34 | #define enums_check moonglmath_enums_check 35 | uint32_t enums_check(lua_State *L, uint32_t domain, int arg); 36 | #define enums_push moonglmath_enums_push 37 | int enums_push(lua_State *L, uint32_t domain, uint32_t code); 38 | #define enums_values moonglmath_enums_values 39 | int enums_values(lua_State *L, uint32_t domain); 40 | #define enums_checklist moonglmath_enums_checklist 41 | uint32_t* enums_checklist(lua_State *L, uint32_t domain, int arg, uint32_t *count, int *err); 42 | #define enums_freelist moonglmath_enums_freelist 43 | void enums_freelist(lua_State *L, uint32_t *list); 44 | 45 | 46 | /* Enum domains */ 47 | #define DOMAIN_ISROW 0 48 | #define DOMAIN_TYPE 1 49 | 50 | /* DOMAIN_ISROW values (vector type) */ 51 | #define MOONGLMATH_COLUMN 0 52 | #define MOONGLMATH_ROW 1 53 | 54 | /* Types for glmath.sizeof() & friends */ 55 | #define MOONGLMATH_TYPE_CHAR 1 56 | #define MOONGLMATH_TYPE_UCHAR 2 57 | #define MOONGLMATH_TYPE_SHORT 3 58 | #define MOONGLMATH_TYPE_USHORT 4 59 | #define MOONGLMATH_TYPE_INT 5 60 | #define MOONGLMATH_TYPE_UINT 6 61 | #define MOONGLMATH_TYPE_LONG 7 62 | #define MOONGLMATH_TYPE_ULONG 8 63 | #define MOONGLMATH_TYPE_FLOAT 9 64 | #define MOONGLMATH_TYPE_DOUBLE 10 65 | 66 | #define testisrow(L, arg, err) (uint32_t)enums_test((L), DOMAIN_ISROW, (arg), (err)) 67 | #define checkisrow(L, arg) (uint32_t)enums_check((L), DOMAIN_ISROW, (arg)) 68 | #define pushisrow(L, val) enums_push((L), DOMAIN_ISROW, (uint32_t)(val)) 69 | #define valuesisrow(L) enums_values((L), DOMAIN_ISROW) 70 | 71 | #define testtype(L, arg, err) (uint32_t)enums_test((L), DOMAIN_TYPE, (arg), (err)) 72 | #define checktype(L, arg) (uint32_t)enums_check((L), DOMAIN_TYPE, (arg)) 73 | #define pushtype(L, val) enums_push((L), DOMAIN_TYPE, (uint32_t)(val)) 74 | #define valuestype(L) enums_values((L), DOMAIN_TYPE) 75 | 76 | #if 0 /* scaffolding 6yy */ 77 | #define testxxx(L, arg, err) (uint32_t)enums_test((L), DOMAIN_XXX, (arg), (err)) 78 | #define checkxxx(L, arg) (uint32_t)enums_check((L), DOMAIN_XXX, (arg)) 79 | #define pushxxx(L, val) enums_push((L), DOMAIN_XXX, (uint32_t)(val)) 80 | #define valuesxxx(L) enums_values((L), DOMAIN_XXX) 81 | CASE(xxx); 82 | 83 | #endif 84 | 85 | #endif /* enumsDEFINED */ 86 | 87 | 88 | -------------------------------------------------------------------------------- /src/funcs.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2016 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | /*------------------------------------------------------------------------------* 29 | | glmath functions | 30 | *------------------------------------------------------------------------------*/ 31 | 32 | #define badarg(L, arg) luaL_argerror((L), (arg), "invalid argument type") 33 | 34 | static int Det(lua_State *L) 35 | { 36 | if(ismat(L,1)) return mat_Det(L); 37 | return badarg(L, 1); 38 | } 39 | 40 | static int Adj(lua_State *L) 41 | { 42 | if(ismat(L,1)) return mat_Adj(L); 43 | return badarg(L, 1); 44 | } 45 | 46 | static int Inv(lua_State *L) 47 | { 48 | if(ismat(L,1)) return mat_Inv(L); 49 | if(isquat(L,1)) return quat_Inv(L); 50 | if(iscomplex(L,1)) return complex_Inv(L); 51 | return badarg(L, 1); 52 | } 53 | 54 | 55 | static int Norm(lua_State *L) 56 | { 57 | if(isvec(L,1)) return vec_Norm(L); 58 | if(isquat(L,1)) return quat_Norm(L); 59 | if(iscomplex(L,1)) return complex_Norm(L); 60 | return badarg(L, 1); 61 | } 62 | 63 | static int Norm2(lua_State *L) 64 | { 65 | if(isvec(L,1)) return vec_Norm2(L); 66 | if(isquat(L,1)) return quat_Norm2(L); 67 | if(iscomplex(L,1)) return complex_Norm2(L); 68 | return badarg(L, 1); 69 | } 70 | 71 | static int Conj(lua_State *L) 72 | { 73 | if(isquat(L,1)) return quat_Conj(L); 74 | if(iscomplex(L,1)) return complex_Conj(L); 75 | return badarg(L, 1); 76 | } 77 | 78 | static int Parts(lua_State *L) 79 | { 80 | if(isquat(L,1)) return quat_Parts(L); 81 | if(iscomplex(L,1)) return complex_Parts(L); 82 | return badarg(L, 1); 83 | } 84 | 85 | static int Normalize(lua_State *L) 86 | { 87 | if(isvec(L,1)) return vec_Normalize(L); 88 | if(isquat(L,1)) return quat_Normalize(L); 89 | if(iscomplex(L,1)) return complex_Normalize(L); 90 | return badarg(L, 1); 91 | } 92 | 93 | 94 | static int Trace(lua_State *L) 95 | { 96 | if(ismat(L,1)) return mat_Trace(L); 97 | return badarg(L, 1); 98 | } 99 | 100 | static int Transpose(lua_State *L) 101 | { 102 | if(isvec(L,1)) return vec_Transpose(L); 103 | if(ismat(L,1)) return mat_Transpose(L); 104 | return badarg(L, 1); 105 | } 106 | 107 | static int Row(lua_State *L) 108 | { 109 | if(ismat(L,1)) return mat_Row(L); 110 | return badarg(L, 1); 111 | } 112 | 113 | static int Column(lua_State *L) 114 | { 115 | if(ismat(L,1)) return mat_Column(L); 116 | return badarg(L, 1); 117 | } 118 | 119 | static int Clamp(lua_State *L) 120 | { 121 | if(lua_isnumber(L,1)) return num_Clamp(L); 122 | if(isvec(L,1)) return vec_Clamp(L); 123 | if(ismat(L,1)) return mat_Clamp(L); 124 | return badarg(L, 1); 125 | } 126 | 127 | static int Mix(lua_State *L) 128 | { 129 | if(lua_isnumber(L,1)) return num_Mix(L); 130 | if(isvec(L,1)) return vec_Mix(L); 131 | if(ismat(L,1)) return mat_Mix(L); 132 | if(isquat(L,1)) return quat_Mix(L); 133 | return badarg(L, 1); 134 | } 135 | 136 | static int Slerp(lua_State *L) 137 | { 138 | if(isquat(L,1)) return quat_Slerp(L); 139 | return badarg(L, 1); 140 | } 141 | 142 | static int Step(lua_State *L) 143 | { 144 | if(lua_isnumber(L,1)) return num_Step(L); 145 | if(isvec(L,1)) return vec_Step(L); 146 | if(ismat(L,1)) return mat_Step(L); 147 | return badarg(L, 1); 148 | } 149 | 150 | static int Smoothstep(lua_State *L) 151 | { 152 | if(lua_isnumber(L,1)) return num_Smoothstep(L); 153 | if(isvec(L,1)) return vec_Smoothstep(L); 154 | if(ismat(L,1)) return mat_Smoothstep(L); 155 | return badarg(L, 1); 156 | } 157 | 158 | static int Fade(lua_State *L) 159 | { 160 | if(lua_isnumber(L,1)) return num_Fade(L); 161 | if(isvec(L,1)) return vec_Fade(L); 162 | if(ismat(L,1)) return mat_Fade(L); 163 | return badarg(L, 1); 164 | } 165 | 166 | /*------------------------------------------------------------------------------* 167 | | Registration | 168 | *------------------------------------------------------------------------------*/ 169 | 170 | static const struct luaL_Reg Functions[] = 171 | { 172 | { "adj", Adj }, 173 | { "det", Det }, 174 | { "inv", Inv }, 175 | { "norm", Norm }, 176 | { "norm2", Norm2 }, 177 | { "conj", Conj }, 178 | { "parts", Parts }, 179 | { "normalize", Normalize }, 180 | { "trace", Trace }, 181 | { "transpose", Transpose }, 182 | { "row", Row }, 183 | { "column", Column }, 184 | { "clamp", Clamp }, 185 | { "mix", Mix }, 186 | { "slerp", Slerp }, 187 | { "step", Step }, 188 | { "smoothstep", Smoothstep }, 189 | { "fade", Fade }, 190 | { NULL, NULL } /* sentinel */ 191 | }; 192 | 193 | void moonglmath_open_funcs(lua_State *L) 194 | { 195 | luaL_setfuncs(L, Functions, 0); 196 | } 197 | 198 | -------------------------------------------------------------------------------- /src/hostmem.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2018 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | 27 | #include "internal.h" 28 | 29 | #if defined(LINUX) 30 | #define AlignedAlloc aligned_alloc 31 | #define AlignedFree free 32 | #elif defined(MINGW) 33 | #define AlignedAlloc _aligned_malloc 34 | #define AlignedFree _aligned_free 35 | #elif defined(MACOS) 36 | #define AlignedAlloc(alignment, size) NULL /*@@TODO*/ 37 | #define AlignedFree free 38 | #else 39 | #error "Cannot determine platform" 40 | #endif 41 | 42 | static int freehostmem(lua_State *L, ud_t *ud) 43 | { 44 | hostmem_t* hostmem = (hostmem_t*)ud->handle; 45 | int allocated = IsAllocated(ud); 46 | if(!freeuserdata(L, ud, "hostmem")) return 0; 47 | if(allocated) 48 | AlignedFree(hostmem->ptr); 49 | Free(L, hostmem); 50 | return 0; 51 | } 52 | 53 | static ud_t *newhostmem(lua_State *L, hostmem_t* hostmem) 54 | { 55 | ud_t *ud; 56 | ud = newuserdata(L, hostmem, HOSTMEM_MT, "hostmem"); 57 | ud->destructor = freehostmem; 58 | return ud; 59 | } 60 | 61 | static int CreateAllocated(lua_State *L, char *ptr, size_t size) 62 | { 63 | ud_t *ud; 64 | hostmem_t* hostmem; 65 | hostmem = (hostmem_t*)MallocNoErr(L, sizeof(hostmem_t)); 66 | if(!hostmem) 67 | { 68 | free(ptr); 69 | return luaL_error(L, errstring(ERR_MEMORY)); 70 | } 71 | hostmem->ptr = ptr; 72 | hostmem->size = size; 73 | ud = newhostmem(L, hostmem); 74 | MarkAllocated(ud); 75 | return 1; 76 | } 77 | 78 | static int CreatePack(lua_State *L, int arg, size_t alignment) 79 | { 80 | int err; 81 | char *ptr; 82 | int type = checktype(L, arg); 83 | size_t n = toflattable(L, arg+1); 84 | size_t size = n * sizeoftype(type); 85 | (void)alignment; 86 | 87 | if(size == 0) 88 | return luaL_argerror(L, arg+1, errstring(ERR_LENGTH)); 89 | #if defined(MACOS) /* @@TODO */ 90 | ptr = (char*)Malloc(L, size); 91 | #else 92 | ptr = (char*)AlignedAlloc(alignment, size); 93 | #endif 94 | if(!ptr) 95 | return luaL_error(L, "failed to allocate page aligned memory"); 96 | 97 | err = testdata(L, type, n, ptr, size); 98 | if(err) 99 | { 100 | free(ptr); 101 | return luaL_argerror(L, arg+1, errstring(err)); 102 | } 103 | 104 | CreateAllocated(L, ptr, size); 105 | return 1; 106 | } 107 | 108 | 109 | static int Create(lua_State *L, int arg, size_t alignment) 110 | { 111 | const char *data = NULL; 112 | char *ptr; 113 | size_t size; 114 | (void)alignment; 115 | 116 | if(lua_type(L, arg) == LUA_TSTRING) 117 | { 118 | if(!lua_isnoneornil(L, arg+1)) 119 | return CreatePack(L, arg, alignment); 120 | 121 | data = luaL_checklstring(L, arg, &size); 122 | if(size == 0) 123 | return luaL_argerror(L, arg, errstring(ERR_LENGTH)); 124 | } 125 | else 126 | { 127 | size = luaL_checkinteger(L, arg); 128 | if(size == 0) 129 | return luaL_argerror(L, arg, errstring(ERR_VALUE)); 130 | } 131 | #if defined(MACOS) /* @@TODO */ 132 | ptr = (char*)Malloc(L, size); 133 | #else 134 | ptr = (char*)AlignedAlloc(alignment, size); 135 | #endif 136 | if(!ptr) 137 | return luaL_error(L, "failed to allocate page aligned memory"); 138 | 139 | if(data) 140 | memcpy(ptr, data, size); 141 | else 142 | memset(ptr, 0, size); 143 | 144 | CreateAllocated(L, ptr, size); 145 | return 1; 146 | } 147 | 148 | static int CreateAlignedAlloc(lua_State *L) 149 | { 150 | size_t alignment = luaL_checkinteger(L, 1); 151 | return Create(L, 2, alignment); 152 | } 153 | 154 | static int CreateMalloc(lua_State *L) 155 | { 156 | return Create(L, 1, 8); 157 | } 158 | 159 | 160 | static int CreateHostmem(lua_State *L) 161 | { 162 | size_t size; 163 | const char *ptr; 164 | hostmem_t* hostmem; 165 | 166 | if(lua_type(L, 1) == LUA_TSTRING) 167 | { 168 | ptr = lua_tolstring(L, 1, &size); 169 | } 170 | else 171 | { 172 | size = luaL_checkinteger(L, 1); 173 | ptr = (char*)checklightuserdata(L, 2); 174 | } 175 | 176 | if(size == 0) 177 | return luaL_argerror(L, 1, errstring(ERR_LENGTH)); 178 | 179 | hostmem = (hostmem_t*)MallocNoErr(L, sizeof(hostmem_t)); 180 | if(!hostmem) 181 | { 182 | Free(L, hostmem); 183 | return luaL_error(L, errstring(ERR_MEMORY)); 184 | } 185 | 186 | hostmem->ptr = (char*)ptr; 187 | hostmem->size = size; 188 | newhostmem(L, hostmem); 189 | return 1; 190 | } 191 | 192 | 193 | static int WriteData(lua_State *L) 194 | { 195 | size_t size; 196 | hostmem_t* hostmem = checkhostmem(L, 1, NULL); 197 | size_t offset = luaL_checkinteger(L, 2); 198 | /* arg 3 should be nil */ 199 | const char *data = luaL_checklstring(L, 4, &size); 200 | if(size == 0) 201 | return 0; 202 | if((offset >= hostmem->size) || (size > hostmem->size - offset)) 203 | return luaL_error(L, errstring(ERR_BOUNDARIES)); 204 | memcpy(hostmem->ptr + offset, data, size); 205 | return 0; 206 | } 207 | 208 | static int CopyPtr(lua_State *L) 209 | { 210 | hostmem_t* hostmem = checkhostmem(L, 1, NULL); 211 | size_t offset = luaL_checkinteger(L, 2); 212 | size_t size = luaL_checkinteger(L, 3); 213 | void *ptr = checklightuserdata(L, 4); 214 | if(size == 0) 215 | return 0; 216 | if((offset >= hostmem->size) || (size > hostmem->size - offset)) 217 | return luaL_error(L, errstring(ERR_BOUNDARIES)); 218 | memcpy(hostmem->ptr + offset, ptr, size); 219 | return 0; 220 | } 221 | 222 | static int CopyHostmem(lua_State *L) 223 | { 224 | hostmem_t* hostmem = checkhostmem(L, 1, NULL); 225 | size_t offset = luaL_checkinteger(L, 2); 226 | size_t size = luaL_checkinteger(L, 3); 227 | hostmem_t* srchostmem = checkhostmem(L, 4, NULL); 228 | size_t srcoffset = luaL_checkinteger(L, 5); 229 | if(hostmem == srchostmem) 230 | return luaL_argerror(L, 4, "source and destination hostmem are the same"); 231 | if(size == 0) 232 | return 0; 233 | if((offset >= hostmem->size) || (size > hostmem->size - offset)) 234 | return luaL_error(L, errstring(ERR_BOUNDARIES)); 235 | if((srcoffset >= srchostmem->size) || (size > srchostmem->size - srcoffset)) 236 | return luaL_error(L, errstring(ERR_BOUNDARIES)); 237 | memcpy(hostmem->ptr + offset, srchostmem->ptr + srcoffset, size); 238 | return 0; 239 | } 240 | 241 | 242 | static int WritePack(lua_State *L) 243 | { 244 | hostmem_t* hostmem = checkhostmem(L, 1, NULL); 245 | size_t offset = luaL_checkinteger(L, 2); 246 | int type = checktype(L, 3); 247 | size_t size = hostmem->size - offset; 248 | if(offset >= hostmem->size) 249 | return luaL_error(L, errstring(ERR_BOUNDARIES)); 250 | checkdata(L, 4, type, hostmem->ptr + offset, size); 251 | return 0; 252 | } 253 | 254 | static int Write(lua_State *L) 255 | { 256 | int t = lua_type(L, 3); 257 | if(t == LUA_TSTRING) return WritePack(L); 258 | if(t == LUA_TNIL) return WriteData(L); 259 | return luaL_argerror(L, 3, errstring(ERR_TYPE)); 260 | } 261 | 262 | static int Copy(lua_State *L) 263 | { 264 | int t = lua_type(L, 4); 265 | if(t == LUA_TLIGHTUSERDATA) return CopyPtr(L); 266 | if(t == LUA_TUSERDATA) return CopyHostmem(L); 267 | return luaL_argerror(L, 4, errstring(ERR_TYPE)); 268 | } 269 | 270 | static int Clear(lua_State *L) 271 | /* clear(offset, size, c) 272 | */ 273 | { 274 | size_t len; 275 | const char *s; 276 | char c; 277 | hostmem_t* hostmem = checkhostmem(L, 1, NULL); 278 | size_t offset = luaL_checkinteger(L, 2); 279 | size_t size = luaL_checkinteger(L, 3); 280 | 281 | if(lua_type(L, 4) == LUA_TSTRING) 282 | { 283 | s = luaL_checklstring(L, 4, &len); 284 | if(len != 1) 285 | return luaL_argerror(L, 4, "invalid length"); /* must be 1 */ 286 | c = s[0]; 287 | } 288 | else 289 | c = luaL_optinteger(L, 4, 0); 290 | 291 | if((offset >= hostmem->size) || (size > hostmem->size - offset)) 292 | return luaL_error(L, errstring(ERR_BOUNDARIES)); 293 | if(size == 0) 294 | return 0; 295 | memset(hostmem->ptr + offset, c, size); 296 | return 0; 297 | } 298 | 299 | static int Read(lua_State *L) 300 | { 301 | int type; 302 | hostmem_t* hostmem = checkhostmem(L, 1, NULL); 303 | size_t offset = luaL_optinteger(L, 2, 0); 304 | size_t size = luaL_optinteger(L, 3, hostmem->size - offset); 305 | if((offset >= hostmem->size) || (size > hostmem->size - offset)) 306 | return luaL_error(L, errstring(ERR_BOUNDARIES)); 307 | if(lua_type(L, 4) == LUA_TSTRING) /* unpack according to 'type' */ 308 | { 309 | type = checktype(L, 4); 310 | if(size == 0) 311 | { lua_newtable(L); return 1; } 312 | return pushdata(L, type, hostmem->ptr + offset, size); 313 | } 314 | if(size == 0) 315 | lua_pushstring(L, ""); 316 | else 317 | lua_pushlstring(L, hostmem->ptr + offset, size); 318 | return 1; 319 | } 320 | 321 | static int Ptr(lua_State *L) 322 | { 323 | hostmem_t* hostmem = checkhostmem(L, 1, NULL); 324 | size_t offset = luaL_optinteger(L, 2, 0); 325 | size_t size = luaL_optinteger(L, 3, 0); 326 | if((offset >= hostmem->size) || (size > hostmem->size - offset)) 327 | return luaL_error(L, errstring(ERR_BOUNDARIES)); 328 | lua_pushlightuserdata(L, hostmem->ptr + offset); 329 | return 1; 330 | } 331 | 332 | 333 | static int Size(lua_State *L) 334 | { 335 | size_t offset; 336 | char *ptr; 337 | hostmem_t* hostmem = checkhostmem(L, 1, NULL); 338 | if(lua_isnoneornil(L, 2)) 339 | lua_pushinteger(L, hostmem->size); 340 | else if(lua_isinteger(L, 2)) 341 | { 342 | offset = luaL_checkinteger(L, 2); 343 | if(offset >= hostmem->size) 344 | lua_pushinteger(L, 0); 345 | else 346 | lua_pushinteger(L, hostmem->size - offset); 347 | } 348 | else 349 | { 350 | ptr = (char*)checklightuserdata(L, 2); 351 | if((ptr < hostmem->ptr) || (ptr > (hostmem->ptr + hostmem->size))) 352 | lua_pushinteger(L, 0); 353 | else 354 | lua_pushinteger(L, hostmem->ptr + hostmem->size - ptr); 355 | } 356 | return 1; 357 | } 358 | 359 | 360 | RAW_FUNC(hostmem) 361 | TYPE_FUNC(hostmem) 362 | DELETE_FUNC(hostmem) 363 | 364 | static const struct luaL_Reg Methods[] = 365 | { 366 | { "raw", Raw }, 367 | { "type", Type }, 368 | { "free", Delete }, 369 | { "write", Write }, 370 | { "copy", Copy }, 371 | { "clear", Clear }, 372 | { "read", Read }, 373 | { "ptr", Ptr }, 374 | { "size", Size }, 375 | { NULL, NULL } /* sentinel */ 376 | }; 377 | 378 | 379 | static const struct luaL_Reg MetaMethods[] = 380 | { 381 | { "__gc", Delete }, 382 | { NULL, NULL } /* sentinel */ 383 | }; 384 | 385 | 386 | static const struct luaL_Reg Functions[] = 387 | { 388 | { "malloc", CreateMalloc }, 389 | { "aligned_alloc", CreateAlignedAlloc }, 390 | { "hostmem", CreateHostmem }, 391 | { "free", Delete }, 392 | { NULL, NULL } /* sentinel */ 393 | }; 394 | 395 | 396 | void moonglmath_open_hostmem(lua_State *L) 397 | { 398 | udata_define(L, HOSTMEM_MT, Methods, MetaMethods); 399 | luaL_setfuncs(L, Functions, 0); 400 | } 401 | 402 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2016 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | static lua_State *moonglmath_L = NULL; 29 | 30 | static void AtExit(void) 31 | { 32 | if(moonglmath_L) 33 | { 34 | enums_free_all(moonglmath_L); 35 | moonglmath_L = NULL; 36 | } 37 | } 38 | 39 | static int AddVersions(lua_State *L) 40 | /* Add version strings to the gl table */ 41 | { 42 | lua_pushstring(L, "_VERSION"); 43 | lua_pushstring(L, "MoonGLMATH "MOONGLMATH_VERSION); 44 | lua_settable(L, -3); 45 | return 0; 46 | } 47 | 48 | int luaopen_moonglmath(lua_State *L) 49 | /* Lua calls this function to load the module */ 50 | { 51 | moonglmath_L = L; 52 | moonglmath_utils_init(L); 53 | atexit(AtExit); 54 | 55 | lua_newtable(L); /* the gl table */ 56 | AddVersions(L); 57 | 58 | /* add glmath functions: */ 59 | moonglmath_open_enums(L); 60 | moonglmath_open_datahandling(L); 61 | moonglmath_open_tracing(L); 62 | moonglmath_open_vec(L); 63 | moonglmath_open_box(L); 64 | moonglmath_open_rect(L); 65 | moonglmath_open_mat(L); 66 | moonglmath_open_quat(L); 67 | moonglmath_open_complex(L); 68 | moonglmath_open_funcs(L); 69 | moonglmath_open_transform(L); 70 | moonglmath_open_viewing(L); 71 | moonglmath_open_hostmem(L); 72 | 73 | /* Add functions implemented in Lua */ 74 | lua_pushvalue(L, -1); lua_setglobal(L, "moonglmath"); 75 | if(luaL_dostring(L, "require('moonglmath.vecsugar')") != 0) lua_error(L); 76 | if(luaL_dostring(L, "require('moonglmath.boxsugar')") != 0) lua_error(L); 77 | if(luaL_dostring(L, "require('moonglmath.rectsugar')") != 0) lua_error(L); 78 | if(luaL_dostring(L, "require('moonglmath.matsugar')") != 0) lua_error(L); 79 | if(luaL_dostring(L, "require('moonglmath.quatsugar')") != 0) lua_error(L); 80 | if(luaL_dostring(L, "require('moonglmath.complexsugar')") != 0) lua_error(L); 81 | if(luaL_dostring(L, "require('moonglmath.utils')") != 0) lua_error(L); 82 | lua_pushnil(L); lua_setglobal(L, "moonglmath"); 83 | 84 | return 1; 85 | } 86 | 87 | -------------------------------------------------------------------------------- /src/moonglmath_local.h: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2016 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | /**************************************************************************** 27 | * MoonGLMATH library - C API redefinitions * 28 | **************************************************************************** 29 | * 30 | * Redefines the C API functions and types without the 'moonglmath_' prefix. 31 | */ 32 | 33 | #ifndef moonglmath_localDEFINED 34 | #define moonglmath_localDEFINED 35 | 36 | #include "moonglmath.h" 37 | 38 | #define vec_t moonglmath_vec_t 39 | #define box_t moonglmath_box_t 40 | #define rect_t moonglmath_rect_t 41 | #define mat_t moonglmath_mat_t 42 | #define quat_t moonglmath_quat_t 43 | #define complex_t moonglmath_complex_t 44 | 45 | #define VEC_MT MOONGLMATH_VEC_MT 46 | #define BOX_MT MOONGLMATH_BOX_MT 47 | #define RECT_MT MOONGLMATH_RECT_MT 48 | #define MAT_MT MOONGLMATH_MAT_MT 49 | #define QUAT_MT MOONGLMATH_QUAT_MT 50 | #define COMPLEX_MT MOONGLMATH_COMPLEX_MT 51 | 52 | #define testmetatable moonglmath_testmetatable 53 | #define checkmetatable moonglmath_checkmetatable 54 | 55 | #define isvec moonglmath_isvec 56 | #define testvec moonglmath_testvec 57 | #define checkvec moonglmath_checkvec 58 | #define pushvec moonglmath_pushvec 59 | 60 | #define isbox moonglmath_isbox 61 | #define testbox moonglmath_testbox 62 | #define checkbox moonglmath_checkbox 63 | #define pushbox moonglmath_pushbox 64 | 65 | #define isrect moonglmath_isrect 66 | #define testrect moonglmath_testrect 67 | #define checkrect moonglmath_checkrect 68 | #define pushrect moonglmath_pushrect 69 | 70 | #define ismat moonglmath_ismat 71 | #define testmat moonglmath_testmat 72 | #define checkmat moonglmath_checkmat 73 | #define pushmat moonglmath_pushmat 74 | 75 | #define isquat moonglmath_isquat 76 | #define testquat moonglmath_testquat 77 | #define checkquat moonglmath_checkquat 78 | #define pushquat moonglmath_pushquat 79 | 80 | #define iscomplex moonglmath_iscomplex 81 | #define testcomplex moonglmath_testcomplex 82 | #define checkcomplex moonglmath_checkcomplex 83 | #define pushcomplex moonglmath_pushcomplex 84 | 85 | #define vec_clear moonglmath_vec_clear 86 | #define vec_copy moonglmath_vec_copy 87 | #define vec_unm moonglmath_vec_unm 88 | #define vec_add moonglmath_vec_add 89 | #define vec_sub moonglmath_vec_sub 90 | #define vec_norm moonglmath_vec_norm 91 | #define vec_norm2 moonglmath_vec_norm2 92 | #define vec_normalize moonglmath_vec_normalize 93 | #define vec_div moonglmath_vec_div 94 | #define vec_dot moonglmath_vec_dot 95 | #define vec_vxs moonglmath_vec_vxs 96 | #define vec_vxv moonglmath_vec_vxv 97 | #define vec_cross moonglmath_vec_cross 98 | #define vec_clamp moonglmath_vec_clamp 99 | #define vec_mix moonglmath_vec_mix 100 | #define vec_step moonglmath_vec_step 101 | #define vec_smoothstep moonglmath_vec_smoothstep 102 | #define vec_fade moonglmath_vec_fade 103 | 104 | #define box_clear moonglmath_box_clear 105 | #define box_copy moonglmath_box_copy 106 | 107 | #define rect_clear moonglmath_rect_clear 108 | #define rect_copy moonglmath_rect_copy 109 | 110 | #define mat_clear moonglmath_mat_clear 111 | #define mat_copy moonglmath_mat_copy 112 | #define mat_unm moonglmath_mat_unm 113 | #define mat_transpose moonglmath_mat_transpose 114 | #define mat_add moonglmath_mat_add 115 | #define mat_sub moonglmath_mat_sub 116 | #define mat_div moonglmath_mat_div 117 | #define mat_mul moonglmath_mat_mul 118 | #define mat_mulby moonglmath_mat_mulby 119 | #define mat_mxs moonglmath_mat_mxs 120 | #define mat_mxv moonglmath_mat_mxv 121 | #define mat_vxm moonglmath_mat_vxm 122 | #define mat_det2 moonglmath_mat_det2 123 | #define mat_det3 moonglmath_mat_det3 124 | #define mat_det4 moonglmath_mat_det4 125 | #define mat_adj moonglmath_mat_adj 126 | #define mat_inv moonglmath_mat_inv 127 | #define mat_clamp moonglmath_mat_clamp 128 | #define mat_mix moonglmath_mat_mix 129 | #define mat_step moonglmath_mat_step 130 | #define mat_smoothstep moonglmath_mat_smoothstep 131 | #define mat_fade moonglmath_mat_fade 132 | 133 | #define quat_clear moonglmath_quat_clear 134 | #define quat_copy moonglmath_quat_copy 135 | #define quat_unm moonglmath_quat_unm 136 | #define quat_add moonglmath_quat_add 137 | #define quat_sub moonglmath_quat_sub 138 | #define quat_norm moonglmath_quat_norm 139 | #define quat_norm2 moonglmath_quat_norm2 140 | #define quat_normalize moonglmath_quat_normalize 141 | #define quat_conj moonglmath_quat_conj 142 | #define quat_inv moonglmath_quat_inv 143 | #define quat_div moonglmath_quat_div 144 | #define quat_mul moonglmath_quat_mul 145 | #define quat_qxs moonglmath_quat_qxs 146 | #define quat_mix moonglmath_quat_mix 147 | #define quat_slerp moonglmath_quat_slerp 148 | 149 | #define clamp moonglmath_clamp 150 | #define mix moonglmath_mix 151 | #define step moonglmath_step 152 | #define smoothstep moonglmath_smoothstep 153 | #define fade moonglmath_fade 154 | 155 | #define now moonglmath_now 156 | 157 | #define translate moonglmath_translate 158 | #define scale moonglmath_scale 159 | #define rotate_x moonglmath_rotate_x 160 | #define rotate_y moonglmath_rotate_y 161 | #define rotate_z moonglmath_rotate_z 162 | 163 | 164 | #define look_at moonglmath_look_at 165 | #define ortho moonglmath_ortho 166 | #define frustum moonglmath_frustum 167 | #define perspective moonglmath_perspective 168 | 169 | #endif /* moonglmath_localDEFINED */ 170 | 171 | -------------------------------------------------------------------------------- /src/num.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2016 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | /*------------------------------------------------------------------------------* 29 | | Functions acting on plain numbers (double) | 30 | *------------------------------------------------------------------------------*/ 31 | 32 | double clamp(double x, double minval, double maxval) 33 | { 34 | if(x < minval) return minval; 35 | if(x > maxval) return maxval; 36 | return x; 37 | } 38 | 39 | int num_Clamp(lua_State *L) 40 | { 41 | double x = luaL_checknumber(L, 1); 42 | double minval = luaL_checknumber(L, 2); 43 | double maxval = luaL_checknumber(L, 3); 44 | lua_pushnumber(L, clamp(x, minval, maxval)); 45 | return 1; 46 | } 47 | 48 | double mix(double x, double y, double k) 49 | { 50 | return x*(1.0-k) + y*k; 51 | } 52 | 53 | int num_Mix(lua_State *L) 54 | { 55 | double x = luaL_checknumber(L, 1); 56 | double y = luaL_checknumber(L, 2); 57 | double k = luaL_checknumber(L, 3); 58 | lua_pushnumber(L, mix(x, y, k)); 59 | return 1; 60 | } 61 | 62 | double step(double x, double edge) 63 | { 64 | return x<=edge ? 0.0 : 1.0; 65 | } 66 | 67 | int num_Step(lua_State *L) 68 | { 69 | double x = luaL_checknumber(L, 1); 70 | double edge = luaL_checknumber(L, 2); 71 | lua_pushnumber(L, step(x, edge)); 72 | return 1; 73 | } 74 | 75 | double smoothstep(double x, double edge0, double edge1) 76 | { 77 | double t = clamp((x-edge0)/(edge1-edge0), 0, 1); 78 | return t*t*(3-2*t); 79 | } 80 | 81 | int num_Smoothstep(lua_State *L) 82 | { 83 | double x = luaL_checknumber(L, 1); 84 | double edge0 = luaL_checknumber(L, 2); 85 | double edge1 = luaL_checknumber(L, 3); 86 | lua_pushnumber(L, smoothstep(x, edge0, edge1)); 87 | return 1; 88 | } 89 | 90 | double fade(double x, double edge0, double edge1) 91 | { 92 | double t = clamp((x-edge0)/(edge1-edge0), 0, 1); 93 | return t*t*t*(t*(t*6-15)+10); // 6t^5 - 15t^4 + 10t^3 (Perlin's improved smoothstep) 94 | } 95 | 96 | int num_Fade(lua_State *L) 97 | { 98 | double x = luaL_checknumber(L, 1); 99 | double edge0 = luaL_checknumber(L, 2); 100 | double edge1 = luaL_checknumber(L, 3); 101 | lua_pushnumber(L, fade(x, edge0, edge1)); 102 | return 1; 103 | } 104 | 105 | -------------------------------------------------------------------------------- /src/objects.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2018 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | ud_t *newuserdata(lua_State *L, void *handle, const char *mt, const char *tracename) 29 | { 30 | ud_t *ud; 31 | /* we use handle as search key */ 32 | ud = (ud_t*)udata_new(L, sizeof(ud_t), (uint64_t)(uintptr_t)handle, mt); 33 | memset(ud, 0, sizeof(ud_t)); 34 | ud->handle = handle; 35 | MarkValid(ud); 36 | if(trace_objects) 37 | printf("create %s %p (%p)\n", tracename, (void*)ud, handle); 38 | return ud; 39 | } 40 | 41 | int freeuserdata(lua_State *L, ud_t *ud, const char *tracename) 42 | { 43 | /* The 'Valid' mark prevents double calls when an object is explicitly destroyed, 44 | * and subsequently deleted also by the GC (the ud sticks around until the GC 45 | * collects it, so we mark it as invalid when the object is explicitly destroyed 46 | * by the script, or implicitly destroyed because child of a destroyed object). */ 47 | if(!IsValid(ud)) return 0; 48 | CancelValid(ud); 49 | if(ud->info) 50 | Free(L, ud->info); 51 | if(trace_objects) 52 | printf("delete %s %p (%p)\n", tracename, (void*)ud, ud->handle); 53 | udata_free(L, (uint64_t)(uintptr_t)ud->handle); 54 | return 1; 55 | } 56 | 57 | 58 | static int freeifchild(lua_State *L, const void *mem, const char *mt, const void *parent_ud) 59 | /* callback for udata_scan */ 60 | { 61 | ud_t *ud = (ud_t*)mem; 62 | (void)mt; 63 | if(IsValid(ud) && (ud->parent_ud == parent_ud)) 64 | ud->destructor(L, ud); 65 | return 0; 66 | } 67 | 68 | int freechildren(lua_State *L, const char *mt, ud_t *parent_ud) 69 | /* calls the self destructor for all 'mt' objects that are children of the given parent_ud */ 70 | { 71 | return udata_scan(L, mt, parent_ud, freeifchild); 72 | } 73 | 74 | int pushuserdata(lua_State *L, ud_t *ud) 75 | { 76 | if(!IsValid(ud)) return unexpected(L); 77 | return udata_push(L, (uint64_t)(uintptr_t)ud->handle); 78 | } 79 | 80 | ud_t *userdata(void *handle) 81 | { 82 | ud_t *ud = (ud_t*)udata_mem((uint64_t)(uintptr_t)handle); 83 | if(ud && IsValid(ud)) return ud; 84 | return NULL; 85 | } 86 | 87 | void *testxxx(lua_State *L, int arg, ud_t **udp, const char *mt) 88 | { 89 | ud_t *ud = (ud_t*)udata_test(L, arg, mt); 90 | if(ud && IsValid(ud)) { if(udp) *udp=ud; return ud->handle; } 91 | if(udp) *udp = NULL; 92 | return 0; 93 | } 94 | 95 | #if 0 96 | void *testoneofxxx(lua_State *L, int arg, ud_t **udp, char **mtp) 97 | { 98 | void *handle = NULL; 99 | int i = 0; 100 | char *mt = NULL; 101 | while((mt = mtp[i++]) != NULL) 102 | { 103 | handle = testxxx(L, arg, udp, mt); 104 | if(handle) return handle; 105 | } 106 | if(udp) *udp = NULL; 107 | return 0; 108 | } 109 | #endif 110 | 111 | 112 | void *checkxxx(lua_State *L, int arg, ud_t **udp, const char *mt) 113 | { 114 | ud_t *ud = (ud_t*)udata_test(L, arg, mt); 115 | if(ud && IsValid(ud)) 116 | { if(udp) *udp = ud; return ud->handle; } 117 | lua_pushfstring(L, "not a %s", mt); 118 | luaL_argerror(L, arg, lua_tostring(L, -1)); 119 | return 0; 120 | } 121 | 122 | int pushxxx(lua_State *L, void *handle) 123 | { return udata_push(L, (uint64_t)(uintptr_t)handle); } 124 | 125 | 126 | void** checkxxxlist(lua_State *L, int arg, uint32_t *count, int *err, const char *mt) 127 | /* xxx_t* checkxxxlist(lua_State *L, int arg, uint32_t *count, int *err) 128 | * Checks if the variable at arg on the Lua stack is a list of xxx_t objects. 129 | * On success, returns an array of xxx_t handles and sets its length in *count. 130 | * The array s Malloc'd and must be released by the caller using Free(L, ...). 131 | * On error, sets *err to ERR_XXX, *count to 0, and returns NULL. 132 | */ 133 | { 134 | void** list; 135 | uint32_t i; 136 | 137 | *count = 0; 138 | *err = 0; 139 | if(lua_isnoneornil(L, arg)) 140 | { *err = ERR_NOTPRESENT; return NULL; } 141 | if(lua_type(L, arg) != LUA_TTABLE) 142 | { *err = ERR_TABLE; return NULL; } 143 | *count = luaL_len(L, arg); 144 | if(*count == 0) 145 | { *err = ERR_EMPTY; return NULL; } 146 | list = (void**)MallocNoErr(L, sizeof(void*) * (*count)); 147 | 148 | if(!list) 149 | { *count = 0; *err = ERR_MEMORY; return NULL; } 150 | 151 | for(i=0; i<*count; i++) 152 | { 153 | lua_rawgeti(L, arg, i+1); 154 | list[i] = (void*)(uintptr_t)testxxx(L, -1, NULL, mt); 155 | if(!list[i]) 156 | { Free(L, list); *count = 0; *err = ERR_TYPE; return NULL; } 157 | lua_pop(L, 1); 158 | } 159 | return list; 160 | } 161 | 162 | -------------------------------------------------------------------------------- /src/objects.h: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2018 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #ifndef objectsDEFINED 27 | #define objectsDEFINED 28 | 29 | #include "tree.h" 30 | #include "udata.h" 31 | 32 | /* host accessible memory: */ 33 | typedef struct { 34 | char *ptr; 35 | size_t size; 36 | } hostmem_t; 37 | 38 | /*------------------------------------------------------*/ 39 | 40 | /* Objects' metatable names */ 41 | #define HOSTMEM_MT "moonglmath_hostmem" 42 | 43 | /* Userdata memory associated with objects */ 44 | #define ud_t moonglmath_ud_t 45 | typedef struct moonglmath_ud_s ud_t; 46 | 47 | struct moonglmath_ud_s { 48 | void *handle; /* the object handle bound to this userdata */ 49 | int (*destructor)(lua_State *L, ud_t *ud); /* self destructor */ 50 | ud_t *parent_ud; /* the ud of the parent object */ 51 | uint32_t marks; 52 | void *info; /* object specific info (ud_info_t, subject to Free() at destruction, if not NULL) */ 53 | }; 54 | 55 | /* Marks. m_ = marks word (uint32_t) , i_ = bit number (0 .. 31) */ 56 | #define MarkGet(m_,i_) (((m_) & ((uint32_t)1<<(i_))) == ((uint32_t)1<<(i_))) 57 | #define MarkSet(m_,i_) do { (m_) = ((m_) | ((uint32_t)1<<(i_))); } while(0) 58 | #define MarkReset(m_,i_) do { (m_) = ((m_) & (~((uint32_t)1<<(i_)))); } while(0) 59 | 60 | #define IsValid(ud) MarkGet((ud)->marks, 0) 61 | #define MarkValid(ud) MarkSet((ud)->marks, 0) 62 | #define CancelValid(ud) MarkReset((ud)->marks, 0) 63 | 64 | #define IsAllocated(ud) MarkGet((ud)->marks, 1) 65 | #define MarkAllocated(ud) MarkSet((ud)->marks, 1) 66 | #define CancelAllocated(ud) MarkReset((ud)->marks, 1) 67 | 68 | #if 0 69 | /* .c */ 70 | #define moonglmath_ 71 | #endif 72 | 73 | #define newuserdata moonglmath_newuserdata 74 | ud_t *newuserdata(lua_State *L, void *handle, const char *mt, const char *tracename); 75 | #define freeuserdata moonglmath_freeuserdata 76 | int freeuserdata(lua_State *L, ud_t *ud, const char *tracename); 77 | #define pushuserdata moonglmath_pushuserdata 78 | int pushuserdata(lua_State *L, ud_t *ud); 79 | 80 | #define userdata_unref(L, handle) udata_unref((L),(handle)) 81 | 82 | #define UD(handle) userdata((handle)) /* dispatchable objects only */ 83 | #define userdata moonglmath_userdata 84 | ud_t *userdata(void *handle); 85 | #define testxxx moonglmath_testxxx 86 | void *testxxx(lua_State *L, int arg, ud_t **udp, const char *mt); 87 | #define checkxxx moonglmath_checkxxx 88 | void *checkxxx(lua_State *L, int arg, ud_t **udp, const char *mt); 89 | #define pushxxx moonglmath_pushxxx 90 | int pushxxx(lua_State *L, void *handle); 91 | #define checkxxxlist moonglmath_checkxxxlist 92 | void** checkxxxlist(lua_State *L, int arg, uint32_t *count, int *err, const char *mt); 93 | 94 | #define freechildren moonglmath_freechildren 95 | int freechildren(lua_State *L, const char *mt, ud_t *parent_ud); 96 | 97 | /* hostmem.c */ 98 | #define checkhostmem(L, arg, udp) (hostmem_t*)checkxxx((L), (arg), (udp), HOSTMEM_MT) 99 | #define testhostmem(L, arg, udp) (hostmem_t*)testxxx((L), (arg), (udp), HOSTMEM_MT) 100 | #define pushhostmem(L, handle) pushxxx((L), (handle)) 101 | #define checkhostmemlist(L, arg, count, err) (hostmem_t*)checkxxxlist((L), (arg), (count), (err), HOSTMEM_MT) 102 | 103 | /* used in main.c */ 104 | void moonglmath_open_hostmem(lua_State *L); 105 | 106 | #define RAW_FUNC(xxx) \ 107 | static int Raw(lua_State *L) \ 108 | { \ 109 | lua_pushinteger(L, (uintptr_t)check##xxx(L, 1, NULL)); \ 110 | return 1; \ 111 | } 112 | 113 | #define TYPE_FUNC(xxx) \ 114 | static int Type(lua_State *L) \ 115 | { \ 116 | (void)check##xxx(L, 1, NULL); \ 117 | lua_pushstring(L, ""#xxx); \ 118 | return 1; \ 119 | } 120 | 121 | #define DELETE_FUNC(xxx) \ 122 | static int Delete(lua_State *L) \ 123 | { \ 124 | ud_t *ud; \ 125 | (void)test##xxx(L, 1, &ud); \ 126 | if(!ud) return 0; /* already deleted */ \ 127 | return ud->destructor(L, ud); \ 128 | } 129 | 130 | #endif /* objectsDEFINED */ 131 | -------------------------------------------------------------------------------- /src/rect.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2016 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | /*------------------------------------------------------------------------------* 29 | | Check and push | 30 | *------------------------------------------------------------------------------*/ 31 | 32 | int testrect(lua_State *L, int arg, rect_t r) 33 | /* Tests if the element at arg is a rect and sets r accordingly */ 34 | { 35 | size_t i; 36 | if(!testmetatable(L, arg, RECT_MT)) return 0; 37 | 38 | if(r != NULL) 39 | { 40 | rect_clear(r); 41 | for(i=0; i < 4; i++) 42 | { 43 | lua_geti(L, arg, i+1); 44 | r[i] = luaL_checknumber(L, -1); 45 | lua_pop(L, 1); 46 | } 47 | } 48 | return 1; 49 | } 50 | 51 | int checkrect(lua_State *L, int arg, rect_t r) 52 | /* Same as testrect(), but raises a error if the test fails. 53 | */ 54 | { 55 | if(!testrect(L, arg, r)) 56 | return luaL_argerror(L, arg, lua_pushfstring(L, "%s expected", RECT_MT)); 57 | return 1; 58 | } 59 | 60 | int pushrect(lua_State *L, rect_t r) 61 | { 62 | size_t i; 63 | lua_newtable(L); 64 | setmetatable(L, RECT_MT); 65 | for(i=0; i<4; i++) 66 | { 67 | lua_pushnumber(L, r[i]); 68 | lua_seti(L, -2, i+1); 69 | } 70 | return 1; 71 | } 72 | 73 | /*------------------------------------------------------------------------------* 74 | | Rect | 75 | *------------------------------------------------------------------------------*/ 76 | 77 | static int Rect(lua_State *L) 78 | /* creates a rect from another rect or a list of values 79 | * the size is adapted by discarding exceeding values or adding zeros 80 | * in lieu of missing values. 81 | */ 82 | { 83 | rect_t r; 84 | size_t i, arg; 85 | arg = 1; 86 | if(testrect(L, arg, r)) 87 | return pushrect(L, r); 88 | for(i = 0; i < 4; i++) 89 | r[i] = luaL_optnumber(L, arg++, 0); 90 | return pushrect(L, r); 91 | } 92 | 93 | static int IsRect(lua_State *L) 94 | { 95 | lua_pushboolean(L, testrect(L, 1, NULL)); 96 | return 1; 97 | } 98 | 99 | /*------------------------------------------------------------------------------* 100 | | ToString | 101 | *------------------------------------------------------------------------------*/ 102 | 103 | static int ToString_(lua_State *L, rect_t r) 104 | /* With snprintf because lua_pushfstring does not support the %g conversion specifier */ 105 | { 106 | #define SZ 512 107 | #define space (SZ-p) 108 | char str[SZ]; 109 | int p=0; 110 | p = snprintf(str, space, "[ "FMT", "FMT", "FMT", "FMT" ]", r[0], r[1], r[2], r[3]); 111 | if(space<0) 112 | { 113 | /* truncate */ 114 | p = SZ - 5; 115 | p+=snprintf(str+p, space, " ..."); 116 | lua_pushlstring(L, str, p); 117 | return 1; 118 | } 119 | lua_pushlstring(L, str, p); 120 | return 1; 121 | #undef space 122 | #undef SZ 123 | } 124 | 125 | static int ToString(lua_State *L) 126 | { 127 | rect_t r; 128 | checkrect(L, 1, r); 129 | return ToString_(L, r); 130 | } 131 | 132 | 133 | static int Concat(lua_State *L) 134 | { 135 | rect_t r; 136 | if(testrect(L, 1, r)) 137 | { 138 | ToString_(L, r); 139 | lua_pushvalue(L, 2); 140 | } 141 | else if(testrect(L, 2, r)) 142 | { 143 | lua_pushvalue(L, 1); 144 | ToString_(L, r); 145 | } 146 | else 147 | return unexpected(L); 148 | lua_concat(L, 2); 149 | return 1; 150 | } 151 | 152 | 153 | /*------------------------------------------------------------------------------* 154 | | Non-Lua functions (for internal use) | 155 | *------------------------------------------------------------------------------*/ 156 | 157 | //@@TBD 158 | 159 | /*------------------------------------------------------------------------------* 160 | | Metamethods | 161 | *------------------------------------------------------------------------------*/ 162 | 163 | static const struct luaL_Reg Metamethods[] = 164 | { 165 | { "__tostring", ToString }, 166 | { "__concat", Concat }, 167 | { NULL, NULL } /* sentinel */ 168 | }; 169 | 170 | static const struct luaL_Reg Methods[] = 171 | { 172 | { NULL, NULL } /* sentinel */ 173 | }; 174 | 175 | 176 | /*------------------------------------------------------------------------------* 177 | | Registration | 178 | *------------------------------------------------------------------------------*/ 179 | 180 | static const struct luaL_Reg Functions[] = 181 | { 182 | { "rect", Rect }, 183 | { "isrect", IsRect }, 184 | { NULL, NULL } /* sentinel */ 185 | }; 186 | 187 | void moonglmath_open_rect(lua_State *L) 188 | { 189 | newmetatable(L, RECT_MT); 190 | metatable_setfuncs(L, RECT_MT, Metamethods, Methods); 191 | luaL_setfuncs(L, Functions, 0); 192 | } 193 | 194 | -------------------------------------------------------------------------------- /src/tracing.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2018 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | static int Type(lua_State *L) 29 | { 30 | #define TRY(xxx) do { if(test##xxx(L, 1, NULL) != 0) { lua_pushstring(L, ""#xxx); return 1; } } while(0) 31 | TRY(hostmem); 32 | return 0; 33 | #undef TRY 34 | } 35 | 36 | int trace_objects = 0; 37 | 38 | static int TraceObjects(lua_State *L) 39 | { 40 | trace_objects = checkboolean(L, 1); 41 | return 0; 42 | } 43 | 44 | static int Now(lua_State *L) 45 | { 46 | lua_pushnumber(L, now()); 47 | return 1; 48 | } 49 | 50 | static int Since(lua_State *L) 51 | { 52 | double t = luaL_checknumber(L, 1); 53 | lua_pushnumber(L, since(t)); 54 | return 1; 55 | } 56 | 57 | /* ----------------------------------------------------------------------- */ 58 | 59 | static const struct luaL_Reg Functions[] = 60 | { 61 | { "type", Type }, 62 | { "trace_objects", TraceObjects }, 63 | { "now", Now }, 64 | { "since", Since }, 65 | { NULL, NULL } /* sentinel */ 66 | }; 67 | 68 | void moonglmath_open_tracing(lua_State *L) 69 | { 70 | luaL_setfuncs(L, Functions, 0); 71 | } 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/transform.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2016 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | /*------------------------------------------------------------------------------* 29 | | Elementary transforms | 30 | *------------------------------------------------------------------------------*/ 31 | 32 | void translate(mat_t m, double x, double y, double z) 33 | /* 1 0 0 x 34 | * 0 1 0 y 35 | * 0 0 1 z 36 | * 0 0 0 1 37 | * 38 | * T^-1(x,y,z) = T(-x, -y, -z) 39 | */ 40 | { 41 | mat_clear(m); 42 | m[0][3] = x; 43 | m[1][3] = y; 44 | m[2][3] = z; 45 | m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0; 46 | } 47 | 48 | void scale(mat_t m, double x, double y, double z) 49 | /* x 0 0 0 50 | * 0 y 0 0 51 | * 0 0 z 0 52 | * 0 0 0 1 53 | */ 54 | { 55 | mat_clear(m); 56 | m[0][0] = x; 57 | m[1][1] = y; 58 | m[2][2] = z; 59 | m[3][3] = 1.0; 60 | } 61 | 62 | static void rotate(mat_t m, double x, double y, double z, double rad) 63 | /* c+(1-c)x^2 (1-c)xy-sz (1-c)xz+sy 0 64 | * (1-c)xy+sz c+(1-c)y^2 (1-c)yz-sx 0 65 | * (1-c)xz-sy (1-c)yz+sx c+(1-c)z^2 0 66 | * 0 0 0 1 67 | * 68 | * c=cos(rad) s=sin(rad) 69 | */ 70 | { 71 | double s, c, c1, a, b; 72 | c = cos(rad); 73 | s = sin(rad); 74 | c1 = 1.0 - c; 75 | mat_clear(m); 76 | m[0][0] = c + c1 * x*x; 77 | m[1][1] = c + c1 * y*y; 78 | m[2][2] = c + c1 * z*z; 79 | m[3][3] = 1; 80 | a = c1*x*y; b = s*z; 81 | m[0][1] = a - b; 82 | m[1][0] = a + b; 83 | a = c1*x*z; b = s*y; 84 | m[0][2] = a + b; 85 | m[2][0] = a - b; 86 | a = c1*y*z; b = s*x; 87 | m[1][2] = a - b; 88 | m[2][1] = a + b; 89 | } 90 | 91 | 92 | void rotate_x(mat_t m, double rad) 93 | /* 1 0 0 0 94 | * 0 c -s 0 95 | * 0 s c 0 96 | * 0 0 0 1 97 | */ 98 | { 99 | double c = cos(rad); 100 | double s = sin(rad); 101 | mat_clear(m); 102 | m[0][0] = m[3][3] = 1; 103 | m[1][1] = m[2][2] = c; 104 | m[1][2] = -s; 105 | m[2][1] = s; 106 | } 107 | 108 | void rotate_y(mat_t m, double rad) 109 | /* c 0 s 0 110 | * 0 1 0 0 111 | * -s 0 c 0 112 | * 0 0 0 1 113 | */ 114 | { 115 | double c = cos(rad); 116 | double s = sin(rad); 117 | mat_clear(m); 118 | m[1][1] = m[3][3] = 1; 119 | m[0][0] = m[2][2] = c; 120 | m[2][0] = -s; 121 | m[0][2] = s; 122 | } 123 | 124 | void rotate_z(mat_t m, double rad) 125 | /* c -s 0 0 126 | * s c 0 0 127 | * 0 0 1 0 128 | * 0 0 0 1 129 | */ 130 | { 131 | double c = cos(rad); 132 | double s = sin(rad); 133 | mat_clear(m); 134 | m[0][0] = m[1][1] = c; 135 | m[2][2] = m[3][3] = 1; 136 | m[0][1] = -s; 137 | m[1][0] = s; 138 | } 139 | 140 | 141 | static int Translate(lua_State *L) 142 | { 143 | vec_t v; 144 | mat_t m; 145 | if(!testvec(L, 1, v, NULL, NULL)) 146 | { 147 | v[0] = luaL_checknumber(L, 1); 148 | v[1] = luaL_checknumber(L, 2); 149 | v[2] = luaL_checknumber(L, 3); 150 | } 151 | translate(m, v[0], v[1], v[2]); 152 | return pushmat(L, m, 4, 4, 4, 4); 153 | } 154 | 155 | static int Scale(lua_State *L) 156 | { 157 | vec_t v; 158 | mat_t m; 159 | if(!testvec(L, 1, v, NULL, NULL)) 160 | { 161 | v[0] = luaL_checknumber(L, 1); 162 | if(lua_isnoneornil(L, 2) && lua_isnoneornil(L, 3)) 163 | v[1] = v[2] = v[0]; 164 | else 165 | { 166 | v[1] = luaL_checknumber(L, 2); 167 | v[2] = luaL_checknumber(L, 3); 168 | } 169 | } 170 | scale(m, v[0], v[1], v[2]); 171 | return pushmat(L, m, 4, 4, 4, 4); 172 | } 173 | 174 | 175 | static int Rotate(lua_State *L) 176 | { 177 | vec_t v; 178 | mat_t m; 179 | double rad = luaL_checknumber(L, 1); 180 | if(!testvec(L, 2, v, NULL, NULL)) 181 | { 182 | v[0] = luaL_checknumber(L, 2); 183 | v[1] = luaL_checknumber(L, 3); 184 | v[2] = luaL_checknumber(L, 4); 185 | } 186 | rotate(m, v[0], v[1], v[2], rad); 187 | return pushmat(L, m, 4, 4, 4, 4); 188 | } 189 | 190 | 191 | static int RotateX(lua_State *L) 192 | { 193 | mat_t m; 194 | double rad = luaL_checknumber(L, 1); 195 | rotate_x(m, rad); 196 | return pushmat(L, m, 4, 4, 4, 4); 197 | } 198 | 199 | static int RotateY(lua_State *L) 200 | { 201 | mat_t m; 202 | double rad = luaL_checknumber(L, 1); 203 | rotate_y(m, rad); 204 | return pushmat(L, m, 4, 4, 4, 4); 205 | } 206 | 207 | static int RotateZ(lua_State *L) 208 | { 209 | mat_t m; 210 | double rad = luaL_checknumber(L, 1); 211 | rotate_z(m, rad); 212 | return pushmat(L, m, 4, 4, 4, 4); 213 | } 214 | 215 | /*------------------------------------------------------------------------------* 216 | | Registration | 217 | *------------------------------------------------------------------------------*/ 218 | 219 | static const struct luaL_Reg Functions[] = 220 | { 221 | { "translate", Translate }, 222 | { "scale", Scale }, 223 | { "rotate", Rotate }, 224 | { "rotate_x", RotateX }, 225 | { "rotate_y", RotateY }, 226 | { "rotate_z", RotateZ }, 227 | { NULL, NULL } /* sentinel */ 228 | }; 229 | 230 | void moonglmath_open_transform(lua_State *L) 231 | { 232 | luaL_setfuncs(L, Functions, 0); 233 | } 234 | 235 | -------------------------------------------------------------------------------- /src/udata.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2018 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include "tree.h" 29 | #include "udata.h" 30 | #include "lua.h" 31 | #include "lauxlib.h" 32 | #include "lualib.h" 33 | #include "compat-5.3.h" 34 | 35 | struct moonglmath_udata_s { 36 | RB_ENTRY(moonglmath_udata_s) entry; 37 | uint64_t id; /* object id (search key) */ 38 | /* references on the Lua registry */ 39 | int ref; /* the correspoding userdata */ 40 | void *mem; /* userdata memory area allocated and released by Lua */ 41 | const char *mt; 42 | }; 43 | 44 | #define UNEXPECTED_ERROR "unexpected error (%s, %d)", __FILE__, __LINE__ 45 | 46 | static int cmp(udata_t *udata1, udata_t *udata2) /* the compare function */ 47 | { return (udata1->id < udata2->id ? -1 : udata1->id > udata2->id); } 48 | 49 | static RB_HEAD(udatatree_s, udata_s) Head = RB_INITIALIZER(&Head); 50 | 51 | RB_PROTOTYPE_STATIC(udatatree_s, udata_s, entry, cmp) 52 | RB_GENERATE_STATIC(udatatree_s, udata_s, entry, cmp) 53 | 54 | static udata_t *udata_remove(udata_t *udata) 55 | { return RB_REMOVE(udatatree_s, &Head, udata); } 56 | static udata_t *udata_insert(udata_t *udata) 57 | { return RB_INSERT(udatatree_s, &Head, udata); } 58 | static udata_t *udata_search(uint64_t id) 59 | { udata_t tmp; tmp.id = id; return RB_FIND(udatatree_s, &Head, &tmp); } 60 | static udata_t *udata_first(uint64_t id) 61 | { udata_t tmp; tmp.id = id; return RB_NFIND(udatatree_s, &Head, &tmp); } 62 | #if 0 63 | static udata_t *udata_next(udata_t *udata) 64 | { return RB_NEXT(udatatree_s, &Head, udata); } 65 | static udata_t *udata_prev(udata_t *udata) 66 | { return RB_PREV(udatatree_s, &Head, udata); } 67 | static udata_t *udata_min(void) 68 | { return RB_MIN(udatatree_s, &Head); } 69 | static udata_t *udata_max(void) 70 | { return RB_MAX(udatatree_s, &Head); } 71 | static udata_t *udata_root(void) 72 | { return RB_ROOT(&Head); } 73 | #endif 74 | 75 | void *udata_new(lua_State *L, size_t size, uint64_t id_, const char *mt) 76 | /* Creates a new Lua userdata, optionally sets its metatable to mt (if != NULL), 77 | * associates the userdata with the passed id and pushes the userdata on the stack. 78 | * 79 | * The userdata can be subsquently pushed on the Lua stack with udata_push(L, id). 80 | * (This is useful to bind C/C++ objects to Lua userdata). 81 | * 82 | * If id=0, the pointer to the memory area allocated by Lua is used as identifier 83 | * (this function returnes it). 84 | */ 85 | { 86 | udata_t *udata; 87 | if((udata = (udata_t*)Malloc(L, sizeof(udata_t))) == NULL) 88 | { luaL_error(L, "cannot allocate memory"); return NULL; } 89 | memset(udata, 0, sizeof(udata_t)); 90 | udata->mem = lua_newuserdata(L, size); 91 | if(!udata->mem) 92 | { 93 | Free(L, udata); 94 | luaL_error(L, "lua_newuserdata error"); 95 | return NULL; 96 | } 97 | udata->id = id_ != 0 ? id_ : (uint64_t)(uintptr_t)(udata->mem); 98 | if(udata_search(udata->id)) 99 | { 100 | Free(L, udata); 101 | luaL_error(L, "duplicated object %I", id_); 102 | return NULL; 103 | } 104 | /* create a reference for later push's */ 105 | lua_pushvalue(L, -1); /* the newly created userdata */ 106 | udata->ref = luaL_ref(L, LUA_REGISTRYINDEX); 107 | udata_insert(udata); 108 | if(mt) 109 | { 110 | udata->mt = mt; 111 | luaL_getmetatable(L, mt); 112 | lua_setmetatable(L, -2); 113 | } 114 | return udata->mem; 115 | } 116 | 117 | void *udata_mem(uint64_t id) 118 | { 119 | udata_t *udata = udata_search(id); 120 | return udata ? udata->mem : NULL; 121 | } 122 | 123 | int udata_unref(lua_State *L, uint64_t id) 124 | /* unreference udata so that it will be garbage collected */ 125 | { 126 | // printf("unref object %lu\n", id); 127 | udata_t *udata = udata_search(id); 128 | if(!udata) 129 | return luaL_error(L, "invalid object identifier %I", id); 130 | if(udata->ref != LUA_NOREF) 131 | { 132 | luaL_unref(L, LUA_REGISTRYINDEX, udata->ref); 133 | udata->ref = LUA_NOREF; 134 | } 135 | return 0; 136 | } 137 | 138 | int udata_free(lua_State *L, uint64_t id) 139 | /* this should be called in the __gc metamethod 140 | */ 141 | { 142 | udata_t *udata = udata_search(id); 143 | // printf("free object %lu\n", id); 144 | if(!udata) 145 | return luaL_error(L, "invalid object identifier %I", id); 146 | /* release all references */ 147 | if(udata->ref != LUA_NOREF) 148 | luaL_unref(L, LUA_REGISTRYINDEX, udata->ref); 149 | udata_remove(udata); 150 | Free(L, udata); 151 | /* mem is released by Lua at garbage collection */ 152 | return 0; 153 | } 154 | 155 | 156 | int udata_push(lua_State *L, uint64_t id) 157 | { 158 | udata_t *udata = udata_search(id); 159 | if(!udata) 160 | return luaL_error(L, "invalid object identifier %I", id); 161 | if(udata->ref == LUA_NOREF) 162 | return luaL_error(L, "unreferenced object"); 163 | if(lua_rawgeti(L, LUA_REGISTRYINDEX, udata->ref) != LUA_TUSERDATA) 164 | return luaL_error(L, UNEXPECTED_ERROR); 165 | return 1; /* one value pushed */ 166 | } 167 | 168 | void udata_free_all(lua_State *L) 169 | /* free all without unreferencing (for atexit()) */ 170 | { 171 | udata_t *udata; 172 | while((udata = udata_first(0))) 173 | { 174 | udata_remove(udata); 175 | Free(L, udata); 176 | } 177 | } 178 | 179 | int udata_scan(lua_State *L, const char *mt, 180 | void *info, int (*func)(lua_State *L, const void *mem, const char* mt, const void *info)) 181 | /* scans the udata database, and calls the func callback for every 'mt' object found 182 | * (the object may be deleted in the callback). 183 | * func must return 0 to continue the scan, !=0 to interrupt it. 184 | * returns 1 if interrupted, 0 otherwise 185 | */ 186 | { 187 | int stop = 0; 188 | uint64_t id = 0; 189 | udata_t *udata; 190 | while((udata = udata_first(id))) 191 | { 192 | id = udata->id + 1; 193 | if(mt == udata->mt) 194 | { 195 | stop = func(L, (const void*)(udata->mem), mt, info); 196 | if(stop) return 1; 197 | } 198 | } 199 | return 0; 200 | } 201 | 202 | 203 | static int is_subclass(lua_State *L, int arg, int mt_index) 204 | { 205 | int ok; 206 | if(luaL_getmetafield(L, arg, "__index") == LUA_TNIL) 207 | return 0; 208 | if(lua_rawequal(L, mt_index, lua_gettop(L))) 209 | { 210 | lua_pop(L, 1); 211 | return 1; 212 | } 213 | ok = is_subclass(L, lua_gettop(L), mt_index); 214 | lua_pop(L, 1); 215 | return ok; 216 | } 217 | 218 | void *udata_test(lua_State *L, int arg, const char *mt) 219 | /* same as luaL_testudata(), but succeeds also if the userdata has not 220 | * mt as metatable but as ancestor 221 | */ 222 | { 223 | void *mem; 224 | int ok; 225 | if((mem = luaL_testudata(L, arg, mt))) 226 | return mem; 227 | 228 | if((mem = lua_touserdata(L, arg)) == NULL) 229 | return NULL; 230 | 231 | if(luaL_getmetatable(L, mt)!=LUA_TTABLE) 232 | { luaL_error(L, "cannot find metatable '%s'", mt); return NULL; } 233 | ok = is_subclass(L, arg, lua_gettop(L)); 234 | lua_pop(L, 1); 235 | return ok ? mem : NULL; 236 | } 237 | 238 | /*------------------------------------------------------------------------------* 239 | | newmetatable for 'class' userdata | 240 | *------------------------------------------------------------------------------*/ 241 | 242 | int udata_define(lua_State *L, const char* mt, const luaL_Reg* methods, const luaL_Reg* metamethods) 243 | { 244 | /* create the metatable */ 245 | if(!luaL_newmetatable(L, mt)) 246 | return luaL_error(L, "cannot create metatable '%s'", mt); 247 | lua_pushvalue(L, -1); 248 | lua_setfield(L, -2, "__index"); 249 | if(metamethods) 250 | /* add metamethods */ 251 | luaL_setfuncs(L, metamethods, 0); 252 | if(methods) 253 | { 254 | /* add methods */ 255 | luaL_getsubtable(L, -1, "__index"); 256 | luaL_setfuncs(L, methods, 0); 257 | lua_pop(L, 1); 258 | } 259 | lua_pop(L, 1); 260 | return 0; 261 | } 262 | 263 | int udata_inherit(lua_State *L, const char *sub, const char *super) 264 | /* Sets metatable(sub).__index = metatable(super) 265 | * 266 | * This way, if one accesses a field/method of a 'sub' object which is not defined in 267 | * the 'sub' metatable, Lua searches for it in the 'super' metatable (i.e., the 'sub' 268 | * type inherits from 'super'). 269 | */ 270 | { 271 | if(luaL_getmetatable(L, sub)!=LUA_TTABLE) 272 | return luaL_error(L, "cannot find metatable '%s'", sub); 273 | luaL_getsubtable(L, -1, "__index"); 274 | if(luaL_getmetatable(L, super)!=LUA_TTABLE) 275 | return luaL_error(L, "cannot find metatable '%s'", super); 276 | lua_setmetatable(L, -2); 277 | lua_pop(L, 2); 278 | return 0; 279 | } 280 | 281 | int udata_addmethods(lua_State *L, const char* mt, const luaL_Reg* methods) 282 | /* Adds methods to the metatable mt */ 283 | { 284 | if(luaL_getmetatable(L, mt)!=LUA_TTABLE) 285 | return luaL_error(L, "cannot find metatable '%s'", mt); 286 | if(methods) 287 | { 288 | /* add methods */ 289 | luaL_getsubtable(L, -1, "__index"); 290 | luaL_setfuncs(L, methods, 0); 291 | lua_pop(L, 1); 292 | } 293 | lua_pop(L, 1); 294 | return 0; 295 | } 296 | 297 | -------------------------------------------------------------------------------- /src/udata.h: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2018 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #include 32 | #include "lua.h" 33 | #include "lauxlib.h" 34 | 35 | #ifndef Malloc 36 | #define Malloc moonglmath_Malloc 37 | void *Malloc(lua_State *L, size_t size); 38 | #define Free moonglmath_Free 39 | void Free(lua_State *L, void *ptr); 40 | #endif 41 | 42 | #define udata_t moonglmath_udata_t 43 | #define udata_s moonglmath_udata_s 44 | #define moonglmath_udata_t struct moonglmath_udata_s 45 | 46 | #define udata_new moonglmath_udata_new 47 | void *udata_new(lua_State*, size_t, uint64_t, const char*); 48 | #define udata_unref moonglmath_udata_unref 49 | int udata_unref(lua_State *L, uint64_t); 50 | #define udata_free moonglmath_udata_free 51 | int udata_free(lua_State*, uint64_t); 52 | #define udata_mem moonglmath_udata_mem 53 | void *udata_mem(uint64_t); 54 | #define udata_push moonglmath_udata_push 55 | int udata_push(lua_State*, uint64_t); 56 | #define udata_free_all moonglmath_udata_free_all 57 | void udata_free_all(lua_State *L); 58 | #define udata_scan moonglmath_udata_scan 59 | int udata_scan(lua_State *L, const char *mt, 60 | void *info, int (*func)(lua_State *L, const void *mem, const char* mt, const void *info)); 61 | #define udata_define moonglmath_udata_define 62 | int udata_define(lua_State*, const char*, const luaL_Reg*, const luaL_Reg*); 63 | #define udata_inherit moonglmath_udata_inherit 64 | int udata_inherit(lua_State*, const char*, const char*); 65 | #define udata_test moonglmath_udata_test 66 | void *udata_test(lua_State*, int, const char*); 67 | #define udata_addmethods moonglmath_udata_addmethods 68 | int udata_addmethods(lua_State*, const char*, const luaL_Reg*); 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | 74 | -------------------------------------------------------------------------------- /src/utils.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2016 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | /*------------------------------------------------------------------------------* 29 | | Misc utilities | 30 | *------------------------------------------------------------------------------*/ 31 | 32 | int noprintf(const char *fmt, ...) 33 | { (void)fmt; return 0; } 34 | 35 | int notavailable(lua_State *L, ...) 36 | { NOT_AVAILABLE; } 37 | 38 | /*------------------------------------------------------------------------------* 39 | | Malloc | 40 | *------------------------------------------------------------------------------*/ 41 | 42 | /* We do not use malloc(), free() etc directly. Instead, we inherit the memory 43 | * allocator from the main Lua state instead (see lua_getallocf in the Lua manual) 44 | * and use that. 45 | * 46 | * By doing so, we can use an alternative malloc() implementation without recompiling 47 | * this library (we have needs to recompile lua only, or execute it with LD_PRELOAD 48 | * set to the path to the malloc library we want to use). 49 | */ 50 | static lua_Alloc Alloc = NULL; 51 | static void* AllocUd = NULL; 52 | 53 | static void malloc_init(lua_State *L) 54 | { 55 | if(Alloc) unexpected(L); 56 | Alloc = lua_getallocf(L, &AllocUd); 57 | } 58 | 59 | static void* Malloc_(size_t size) 60 | { return Alloc ? Alloc(AllocUd, NULL, 0, size) : NULL; } 61 | 62 | static void Free_(void *ptr) 63 | { if(Alloc) Alloc(AllocUd, ptr, 0, 0); } 64 | 65 | void *Malloc(lua_State *L, size_t size) 66 | { 67 | void *ptr; 68 | if(size == 0) 69 | { luaL_error(L, errstring(ERR_MALLOC_ZERO)); return NULL; } 70 | ptr = Malloc_(size); 71 | if(ptr==NULL) 72 | { luaL_error(L, errstring(ERR_MEMORY)); return NULL; } 73 | memset(ptr, 0, size); 74 | //DBG("Malloc %p\n", ptr); 75 | return ptr; 76 | } 77 | 78 | void *MallocNoErr(lua_State *L, size_t size) /* do not raise errors (check the retval) */ 79 | { 80 | void *ptr = Malloc_(size); 81 | (void)L; 82 | if(ptr==NULL) 83 | return NULL; 84 | memset(ptr, 0, size); 85 | //DBG("MallocNoErr %p\n", ptr); 86 | return ptr; 87 | } 88 | 89 | char *Strdup(lua_State *L, const char *s) 90 | { 91 | size_t len = strnlen(s, 256); 92 | char *ptr = (char*)Malloc(L, len + 1); 93 | if(len>0) 94 | memcpy(ptr, s, len); 95 | ptr[len]='\0'; 96 | return ptr; 97 | } 98 | 99 | 100 | void Free(lua_State *L, void *ptr) 101 | { 102 | (void)L; 103 | //DBG("Free %p\n", ptr); 104 | if(ptr) Free_(ptr); 105 | } 106 | 107 | 108 | /*------------------------------------------------------------------------------* 109 | | Time utilities | 110 | *------------------------------------------------------------------------------*/ 111 | 112 | #if defined(LINUX) || defined(MACOS) 113 | #include /* for usleep */ 114 | 115 | #if 0 116 | static double tstosec(const struct timespec *ts) 117 | { 118 | return ts->tv_sec*1.0+ts->tv_nsec*1.0e-9; 119 | } 120 | #endif 121 | 122 | static void sectots(struct timespec *ts, double seconds) 123 | { 124 | ts->tv_sec=(time_t)seconds; 125 | ts->tv_nsec=(long)((seconds-((double)ts->tv_sec))*1.0e9); 126 | } 127 | 128 | double now(void) 129 | { 130 | #if _POSIX_C_SOURCE >= 199309L 131 | struct timespec ts; 132 | if(clock_gettime(CLOCK_MONOTONIC,&ts)!=0) 133 | { printf("clock_gettime error\n"); return -1; } 134 | return ts.tv_sec + ts.tv_nsec*1.0e-9; 135 | #else 136 | struct timeval tv; 137 | if(gettimeofday(&tv, NULL) != 0) 138 | { printf("gettimeofday error\n"); return -1; } 139 | return tv.tv_sec + tv.tv_usec*1.0e-6; 140 | #endif 141 | } 142 | 143 | void sleeep(double seconds) 144 | { 145 | #if _POSIX_C_SOURCE >= 199309L 146 | struct timespec ts, ts1; 147 | struct timespec *req, *rem, *tmp; 148 | sectots(&ts, seconds); 149 | req = &ts; 150 | rem = &ts1; 151 | while(1) 152 | { 153 | if(nanosleep(req, rem) == 0) 154 | return; 155 | tmp = req; 156 | req = rem; 157 | rem = tmp; 158 | } 159 | #else 160 | usleep((useconds_t)(seconds*1.0e6)); 161 | #endif 162 | } 163 | 164 | #define time_init(L) do { (void)L; /* do nothing */ } while(0) 165 | 166 | #elif defined(MINGW) 167 | 168 | #include 169 | 170 | static LARGE_INTEGER Frequency; 171 | double now(void) 172 | { 173 | LARGE_INTEGER ts; 174 | QueryPerformanceCounter(&ts); 175 | return ((double)(ts.QuadPart))/Frequency.QuadPart; 176 | } 177 | 178 | void sleeep(double seconds) 179 | { 180 | DWORD msec = (DWORD)seconds * 1000; 181 | //if(msec < 0) return; DWORD seems to be unsigned 182 | Sleep(msec); 183 | } 184 | 185 | static void time_init(lua_State *L) 186 | { 187 | (void)L; 188 | QueryPerformanceFrequency(&Frequency); 189 | } 190 | 191 | #endif 192 | 193 | 194 | /*------------------------------------------------------------------------------* 195 | | Metatables handling | 196 | *------------------------------------------------------------------------------*/ 197 | 198 | int newmetatable(lua_State *L, const char *metatable) 199 | { 200 | luaL_newmetatable(L, metatable); 201 | lua_pushvalue(L, -1); 202 | lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ 203 | lua_pop(L, 1); 204 | return 0; 205 | } 206 | 207 | int setmetatable(lua_State *L, const char *metatable) 208 | /* Sets the metatable of the table on top of the stack */ 209 | { 210 | luaL_getmetatable(L, metatable); 211 | lua_setmetatable(L, -2); 212 | return 0; 213 | } 214 | 215 | int testmetatable(lua_State *L, int arg, const char *metatable) 216 | /* Tests the metatable of the table at index arg */ 217 | { 218 | int ok = 0; 219 | if(lua_getmetatable(L, arg) == 0) return 0; 220 | luaL_getmetatable(L, metatable); 221 | ok = lua_compare(L, -1, -2, LUA_OPEQ); 222 | lua_pop(L, 2); 223 | return ok; 224 | } 225 | 226 | int checkmetatable(lua_State *L, int arg, const char *metatable) 227 | /* Tests the metatable of the table at index arg */ 228 | { 229 | if(!testmetatable(L, arg, metatable)) 230 | return luaL_argerror(L, arg, lua_pushfstring(L, "%s expected", metatable)); 231 | return 1; 232 | } 233 | 234 | int metatable_setfuncs(lua_State *L, const char *metatable, const luaL_Reg *metamethods, 235 | const luaL_Reg *methods) 236 | { 237 | luaL_getmetatable(L, metatable); 238 | if(metamethods) 239 | luaL_setfuncs(L, metamethods, 0); 240 | if(methods) 241 | { 242 | luaL_getsubtable(L, -1, "__index"); 243 | luaL_setfuncs(L, methods, 0); 244 | lua_pop(L, 1); 245 | } 246 | lua_pop(L, 1); 247 | return 0; 248 | } 249 | 250 | int checkboolean(lua_State *L, int arg) 251 | { 252 | if(!lua_isboolean(L, arg)) 253 | return (int)luaL_argerror(L, arg, "boolean expected"); 254 | return lua_toboolean(L, arg) ? 1 : 0; 255 | } 256 | 257 | int checkoption_hint(lua_State *L, int arg, const char *def, const char *const lst[]) 258 | /* Variant of luaL_checkoption(), with an added hint in the error message */ 259 | { 260 | const char *hint = NULL; 261 | const char *name = (def) ? luaL_optstring(L, arg, def) : luaL_checkstring(L, arg); 262 | int i; 263 | for (i=0; lst[i]; i++) 264 | if (strcmp(lst[i], name) == 0) return i; 265 | 266 | if(lua_checkstack(L, i*2)) 267 | { 268 | for(i=0; lst[i]; i++) 269 | { 270 | lua_pushfstring(L, "'%s'", lst[i]); 271 | lua_pushstring(L, "|"); 272 | } 273 | i = i*2; 274 | if(i>0) 275 | { 276 | lua_pop(L, 1); /* the last separator */ 277 | lua_concat(L, i-1); 278 | hint = lua_tostring(L, -1); 279 | } 280 | } 281 | if(hint) 282 | return luaL_argerror(L, arg, lua_pushfstring(L, 283 | "invalid option '%s', valid options are: %s", name, hint)); 284 | return luaL_argerror(L, arg, lua_pushfstring(L, "invalid option '%s'", name)); 285 | } 286 | 287 | int isoption(lua_State *L, int arg, const char *const lst[]) 288 | /* Variant of luaL_checkoption(), checks only and returns a boolean */ 289 | { 290 | int i; 291 | const char *name; 292 | 293 | if(!lua_isstring(L, arg)) return 0; 294 | name = lua_tostring(L, arg); 295 | for (i=0; lst[i]; i++) 296 | if (strcmp(lst[i], name) == 0) return 1; 297 | return 0; 298 | } 299 | 300 | 301 | /*------------------------------------------------------------------------------* 302 | | Light userdata | 303 | *------------------------------------------------------------------------------*/ 304 | 305 | void *checklightuserdata(lua_State *L, int arg) 306 | { 307 | if(lua_type(L, arg) != LUA_TLIGHTUSERDATA) 308 | { luaL_argerror(L, arg, "expected lightuserdata"); return NULL; } 309 | return lua_touserdata(L, arg); 310 | } 311 | 312 | void *optlightuserdata(lua_State *L, int arg) 313 | { 314 | if(lua_isnoneornil(L, arg)) 315 | return NULL; 316 | return checklightuserdata(L, arg); 317 | } 318 | 319 | void *checklightuserdataorzero(lua_State *L, int arg) 320 | { 321 | int val, isnum; 322 | val = lua_tointegerx(L, arg, &isnum); 323 | if(!isnum) 324 | return checklightuserdata(L, arg); 325 | if(val != 0) 326 | luaL_argerror(L, arg, "expected lightuserdata or 0"); 327 | return NULL; 328 | } 329 | 330 | 331 | /*------------------------------------------------------------------------------* 332 | | Internal error codes | 333 | *------------------------------------------------------------------------------*/ 334 | 335 | const char* errstring(int err) 336 | { 337 | switch(err) 338 | { 339 | case 0: return "success"; 340 | case ERR_GENERIC: return "generic error"; 341 | case ERR_TABLE: return "not a table"; 342 | case ERR_EMPTY: return "empty list"; 343 | case ERR_TYPE: return "invalid type"; 344 | case ERR_VALUE: return "invalid value"; 345 | case ERR_NOTPRESENT: return "missing"; 346 | case ERR_MEMORY: return "out of memory"; 347 | case ERR_MALLOC_ZERO: return "zero bytes malloc"; 348 | case ERR_LENGTH: return "invalid length"; 349 | case ERR_POOL: return "elements are not from the same pool"; 350 | case ERR_BOUNDARIES: return "invalid boundaries"; 351 | case ERR_UNKNOWN: return "unknown field name"; 352 | default: 353 | return "???"; 354 | } 355 | return NULL; /* unreachable */ 356 | } 357 | 358 | /*------------------------------------------------------------------------------* 359 | | Inits | 360 | *------------------------------------------------------------------------------*/ 361 | 362 | void moonglmath_utils_init(lua_State *L) 363 | { 364 | malloc_init(L); 365 | time_init(L); 366 | } 367 | 368 | -------------------------------------------------------------------------------- /src/viewing.c: -------------------------------------------------------------------------------- 1 | /* The MIT License (MIT) 2 | * 3 | * Copyright (c) 2016 Stefano Trettel 4 | * 5 | * Software repository: MoonGLMATH, https://github.com/stetre/moonglmath 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | 26 | #include "internal.h" 27 | 28 | /*------------------------------------------------------------------------------* 29 | | Camera positioning (view matrix) | 30 | *------------------------------------------------------------------------------*/ 31 | 32 | int look_at(mat_t dst, vec_t eye, vec_t at, vec_t up) 33 | /* look_at(eye, at, up) 34 | * 35 | * eye = camera position = (e1, e2, e3) 36 | * at = target position 37 | * up = camera 'up' direction 38 | * 39 | * NOTE: 'up' is the direction from the camera to a point above the target, 40 | * on the vertical. 41 | * 42 | * d = (at - eye) : direction vector 43 | * n = (eye - at) = z : normal to the projection plane, oriented towards the camera 44 | * x = d % up = up % n : points to the right of the camera 45 | * y = z % x = n % x : points up fro the camera 46 | * 47 | * M = |x1 x2 x3 0| |1 0 0 -e1| 48 | * |y1 y2 y3 0|·|0 1 0 -e2| 49 | * |z1 z2 z3 0| |0 0 1 -e3| 50 | * |0 0 0 1| |0 0 0 1| 51 | * | | 52 | * orient translate 53 | */ 54 | { 55 | 56 | size_t i; 57 | vec_t z, x, y; 58 | mat_t c, te; 59 | 60 | vec_sub(z, eye, at, 4); /* z = eye - at (normal vector = - direction vector) */ 61 | vec_normalize(z, 4); 62 | 63 | vec_cross(x, up, z); /* x = up % z (right vector) */ 64 | vec_normalize(x, 4); 65 | 66 | vec_cross(y, z, x); /* y = z % x (up vector) */ 67 | vec_normalize(y, 4); 68 | 69 | mat_clear(c); 70 | /* c = x1 x2 x3 0 71 | * y1 y2 y3 0 72 | * z1 z2 z3 0 73 | * 0 0 0 1 74 | */ 75 | for(i = 0; i< 4; i ++) 76 | { 77 | c[0][i] = x[i]; 78 | c[1][i] = y[i]; 79 | c[2][i] = z[i]; 80 | } 81 | c[3][3] = 1; 82 | 83 | /* dst = c * translate(-eye) */ 84 | translate(te, -eye[0], -eye[1], -eye[2]); 85 | mat_mul(dst, c, te, 4, 4, 4); 86 | 87 | return 0; 88 | } 89 | 90 | static int LookAt(lua_State *L) 91 | { 92 | mat_t m; 93 | vec_t eye, at, up; 94 | checkvec(L, 1, eye, NULL, NULL); 95 | checkvec(L, 2, at, NULL, NULL); 96 | checkvec(L, 3, up, NULL, NULL); 97 | look_at(m, eye, at, up); 98 | return pushmat(L, m, 4, 4, 4, 4); 99 | } 100 | 101 | 102 | /*------------------------------------------------------------------------------* 103 | | Projections | 104 | *------------------------------------------------------------------------------*/ 105 | 106 | int ortho(mat_t dst, double l, double r, double b, double t, double near, double far) 107 | /* ortho(left, right, bottom, top, near, far) 108 | * near=-1 and far=1 give a 2D projection 109 | * 110 | * Rfr. RTR3/4.6.1 111 | * 112 | * The viewing parallelepiped is: 113 | * x: left .. right 114 | * y: bottom .. up 115 | * z: -near .. -far 116 | * 117 | * The camera is positioned at the origin, pointing to the -z axis (x=right, y=up) 118 | * and the projection plane is the x-y plane (or, equivalently, any plane parallel 119 | * to x-y, since the projectors are parallel to the z axis). 120 | * 121 | * M = |2/(r-l) 0 0 0| |1 0 0 -(l+r)/2| = |2/(r-l) 0 0 -(r+l)/(r-l)| 122 | * | 0 2/(t-b) 0 0|*|0 1 0 -(t+b)/2| | 0 2/(t-b) 0 -(t+b)/(t-b)| 123 | * | 0 0 2/(f-n) 0| |0 0 1 -(f+n)/2| | 0 0 2/(f-n) -(f+n)/(f-n)| 124 | * | 0 0 0 1| |0 0 0 1 | | 0 0 0 1 | 125 | * scaling translation 126 | */ 127 | { 128 | double n, f; 129 | n = -near; 130 | f = -far; 131 | mat_clear(dst); 132 | dst[0][0] = 2.0/(r-l); 133 | dst[0][3] = -(r+l)/(r-l); 134 | dst[1][1] = 2.0/(t-b); 135 | dst[1][3] = -(t+b)/(t-b); 136 | dst[2][2] = 2.0/(f-n); 137 | dst[2][3] = -(f+n)/(f-n); 138 | dst[3][3] = 1.0; 139 | return 0; 140 | } 141 | 142 | int frustum(mat_t dst, double l, double r, double b, double t, double n, double f) 143 | { 144 | mat_clear(dst); 145 | dst[0][0] = 2.0*n/(r-l); 146 | dst[0][2] = (r+l)/(r-l); 147 | dst[1][1] = 2.0*n/(t-b); 148 | dst[1][2] = (t+b)/(t-b); 149 | dst[2][2] = -(f+n)/(f-n); 150 | dst[2][3] = -2.0*f*n/(f-n); 151 | dst[3][2] = -1.0; 152 | return 0; 153 | } 154 | 155 | int perspective(mat_t dst, double fovy, double aspect, double n, double f) 156 | { 157 | double t = tan(fovy/2) * n; /* top */ 158 | double r = t * aspect; /* right */ 159 | mat_clear(dst); 160 | dst[0][0] = n/r; 161 | dst[1][1] = n/t; 162 | dst[2][2] = -(f+n)/(f-n); 163 | dst[2][3] = -2.0*f*n/(f-n); 164 | dst[3][2] = -1.0; 165 | return 0; 166 | } 167 | 168 | 169 | static int Ortho(lua_State *L) 170 | { 171 | mat_t m; 172 | double l = luaL_checknumber(L, 1); /* left */ 173 | double r = luaL_checknumber(L, 2); /* right */ 174 | double b = luaL_checknumber(L, 3); /* bottom */ 175 | double t = luaL_checknumber(L, 4); /* top */ 176 | double n = luaL_optnumber(L, 5, -1.0); /* near */ 177 | double f = luaL_optnumber(L, 6, 1.0); /* far */ 178 | ortho(m, l, r, b, t, n, f); 179 | return pushmat(L, m, 4, 4, 4, 4); 180 | } 181 | 182 | static int Frustum(lua_State *L) 183 | { 184 | mat_t m; 185 | double l = luaL_checknumber(L, 1); /* left */ 186 | double r = luaL_checknumber(L, 2); /* right */ 187 | double b = luaL_checknumber(L, 3); /* bottom */ 188 | double t = luaL_checknumber(L, 4); /* top */ 189 | double n = luaL_checknumber(L, 5); /* near */ 190 | double f = luaL_checknumber(L, 6); /* far */ 191 | frustum(m, l, r, b, t, n, f); 192 | return pushmat(L, m, 4, 4, 4, 4); 193 | } 194 | 195 | static int Perspective(lua_State *L) 196 | /* perspective(fovy, aspect, near, far) 197 | */ 198 | { 199 | mat_t m; 200 | double fovy = luaL_checknumber(L, 1); /* radians */ 201 | double aspect = luaL_checknumber(L, 2); 202 | double n = luaL_checknumber(L, 3); /* near */ 203 | double f = luaL_checknumber(L, 4); /* far */ 204 | perspective(m, fovy, aspect, n, f); 205 | return pushmat(L, m, 4, 4, 4, 4); 206 | } 207 | 208 | 209 | /*------------------------------------------------------------------------------* 210 | | Registration | 211 | *------------------------------------------------------------------------------*/ 212 | 213 | static const struct luaL_Reg Functions[] = 214 | { 215 | { "look_at", LookAt }, 216 | { "ortho", Ortho }, 217 | { "frustum", Frustum }, 218 | { "perspective", Perspective }, 219 | { NULL, NULL } /* sentinel */ 220 | }; 221 | 222 | void moonglmath_open_viewing(lua_State *L) 223 | { 224 | luaL_setfuncs(L, Functions, 0); 225 | } 226 | 227 | -------------------------------------------------------------------------------- /thirdparty/asciidoctor-styles-license: -------------------------------------------------------------------------------- 1 | The CSS used for the Reference Manual is taken from the 2 | Asciidoctor styles project 3 | (https://github.com/asciidoctor/asciidoctor-stylesheet-factory ). 4 | 5 | Below is a copy of the Asciidoctor styles copyright notice. 6 | 7 | Stefano Trettel 8 | 9 | ======================================================================== 10 | 11 | Asciidoctor styles 12 | ------------------ 13 | 14 | Copyright (c) 2013 Dan Allen 15 | 16 | MIT License 17 | 18 | Permission is hereby granted, free of charge, to any person obtaining 19 | a copy of this software and associated documentation files (the 20 | "Software"), to deal in the Software without restriction, including 21 | without limitation the rights to use, copy, modify, merge, publish, 22 | distribute, sublicense, and/or sell copies of the Software, and to 23 | permit persons to whom the Software is furnished to do so, subject to 24 | the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be 27 | included in all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 30 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 31 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 32 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 33 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 34 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 35 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 36 | 37 | 38 | Other licensed work 39 | ------------------- 40 | 41 | - Foundation 4 by Zurb, on which the themes are built, is licensed under the 42 | Apache License, v2.0: 43 | 44 | http://apache.org/licenses/LICENSE-2.0 45 | http://foundation.zurb.com 46 | 47 | - The riak theme is derived from the Riak documentation theme by Basho, 48 | licensed under the Creative Commons Attribution 3.0 Unported License: 49 | 50 | http://creativecommons.org/licenses/by/3.0/us 51 | http://docs.basho.org 52 | 53 | - The iconic theme is inspired by O'Reilly typography and Atlas manual. 54 | 55 | http://oreilly.com 56 | -------------------------------------------------------------------------------- /thirdparty/lua-compat-5.3-license: -------------------------------------------------------------------------------- 1 | The src/compat-5.3.h and src/compat-5.3.c files are taken from: 2 | https://github.com/keplerproject/lua-compat-5.3 3 | 4 | Below is a copy of the original copyright notice, from the same source. 5 | 6 | Stefano Trettel 7 | 8 | =========================================================================== 9 | 10 | The MIT License (MIT) 11 | 12 | Copyright (c) 2015 Kepler Project. 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy of 15 | this software and associated documentation files (the "Software"), to deal in 16 | the Software without restriction, including without limitation the rights to 17 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 18 | the Software, and to permit persons to whom the Software is furnished to do so, 19 | subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 26 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 27 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 28 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | -------------------------------------------------------------------------------- /thirdparty/openbsd-tree-license: -------------------------------------------------------------------------------- 1 | The src/tree.h module is taken from: 2 | http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/sys/tree.h 3 | 4 | Below is a copy of the copyright notice included in the module. 5 | 6 | Stefano Trettel 7 | 8 | =========================================================================== 9 | /* 10 | * Copyright 2002 Niels Provos 11 | * All rights reserved. 12 | * 13 | * Redistribution and use in source and binary forms, with or without 14 | * modification, are permitted provided that the following conditions 15 | * are met: 16 | * 1. Redistributions of source code must retain the above copyright 17 | * notice, this list of conditions and the following disclaimer. 18 | * 2. Redistributions in binary form must reproduce the above copyright 19 | * notice, this list of conditions and the following disclaimer in the 20 | * documentation and/or other materials provided with the distribution. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | -------------------------------------------------------------------------------- /thirdparty/powered-by-lua-license: -------------------------------------------------------------------------------- 1 | The 'powered by Lua' logo (doc/powered-by-lua.gif ) is taken from: 2 | http://www.lua.org/images . 3 | 4 | Below is a copy of the copyright notice from the same web-page. 5 | 6 | Stefano Trettel 7 | 8 | =========================================================================== 9 | Copyright © 1998 Lua.org. Graphic design by Alexandre Nakonechnyj. 10 | 11 | Permission is hereby granted, without written agreement and without license 12 | or royalty fees, to use, copy, and distribute this logo for any purpose, 13 | including commercial applications, subject to the following conditions: 14 | 15 | - The origin of this logo must not be misrepresented; you must not claim that 16 | you drew the original logo. 17 | - The only modification you can make is to adapt the orbiting text to your 18 | product name. 19 | - The logo can be used in any scale as long as the relative proportions of its 20 | elements are maintained. 21 | --------------------------------------------------------------------------------