cglm 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: da66e89ef19c691d7411dfb2ced1dd6d840767d85b0d886f21e291c9082f454a
4
+ data.tar.gz: 621578f7a74416574e6b39265780eeefe4913bb1e396e8382646cf1f1fc99cf6
5
+ SHA512:
6
+ metadata.gz: 7a9ef4ac1b5d70e37009cc916fe0e29d63d6a41fc7cb62d60786f54996202a5449f46dfb4604b737f6ff5676ba12ec4ea734a15de0f0134eeccfe6512aacaeaf
7
+ data.tar.gz: cd4dc6182bdb554f06a44d4a4448a06e56945c31b81f79a4219c8fcb4a08d7eb59a00b6f6760501736ebf1f480d55f4b9fbe8a31ab032aa8e259490fd62bd483
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ *.bundle
10
+ *.so
11
+ *.o
12
+ *.a
13
+ mkmf.log
14
+ /ext/cglm/cglm-*
15
+ /ext/cglm/cglm-*.tar.gz
16
+ .DS_Store
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.6.0
7
+ before_install: gem install bundler -v 1.17.1
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --markup=markdown
2
+ --markup-provider=redcarpet
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in cglm.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,39 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cglm (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ docile (1.3.1)
10
+ github-markup (3.0.1)
11
+ json (2.1.0)
12
+ minitest (5.11.3)
13
+ rake (10.5.0)
14
+ rake-compiler (1.0.5)
15
+ rake
16
+ redcarpet (3.4.0)
17
+ simplecov (0.16.1)
18
+ docile (~> 1.1)
19
+ json (>= 1.8, < 3)
20
+ simplecov-html (~> 0.10.0)
21
+ simplecov-html (0.10.2)
22
+ yard (0.9.16)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ bundler (~> 1.17)
29
+ cglm!
30
+ github-markup
31
+ minitest (~> 5.0)
32
+ rake (~> 10.0)
33
+ rake-compiler
34
+ redcarpet
35
+ simplecov
36
+ yard (~> 0.9)
37
+
38
+ BUNDLED WITH
39
+ 1.17.1
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Colin MacKenzie IV
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # CGLM
2
+
3
+ Ruby bindings for [CGLM](https://github.com/recp/cglm), a high performance math library for OpenGL.
4
+
5
+ [CGLM](https://github.com/recp/cglm) provides support for SIMD on CPUs that support it in order to deliver better performance. This requires the variables to be aligned to 8-, 16- and 32-byte boundaries, but this gem automatically handles this requirement so you don't have to think about that.
6
+
7
+ [CGLM](https://github.com/recp/cglm) sports the following features:
8
+
9
+ * general purpose matrix operations (mat4, mat3)
10
+ * general purpose vector operations (cross, dot, rotate, proj, angle...)
11
+ * affine transforms
12
+ * matrix decomposition (extract rotation, scaling factor)
13
+ * optimized affine transform matrices (mul, rigid-body inverse)
14
+ * camera (lookat)
15
+ * projections (ortho, perspective)
16
+ * quaternions
17
+ * euler angles / yaw-pitch-roll to matrix
18
+ * extract euler angles
19
+ * frustum (extract view frustum planes, corners...)
20
+ * bounding box (AABB in Frustum (culling), crop, merge...)
21
+ * project, unproject
22
+
23
+ (Note: A few other features are available in the original C library, such as optional in-lining of all functions, which don't really translate to Ruby gems -- although such features are used by the code for the gem itself.)
24
+
25
+ ## Installation
26
+
27
+ Add this line to your application's Gemfile:
28
+
29
+ ```ruby
30
+ gem 'cglm'
31
+ ```
32
+
33
+ And then execute:
34
+
35
+ $ bundle
36
+
37
+ Or install it yourself as:
38
+
39
+ $ gem install cglm
40
+
41
+ ## Usage
42
+
43
+ Include the `CGLM` module, or use the classes it defines directly:
44
+
45
+ ```ruby
46
+ include CGLM
47
+
48
+ a = Vec3.new
49
+ b = Vec3.new([1, 0, 0])
50
+
51
+ proj = Mat4.perspective(fovy: Math::PI / 4, aspect: 640.0 / 480.0)
52
+ view = Mat4.rotate(Vec3.new([0, 1, 0], PI_4)
53
+ model = Mat4.translate(Vec3.new([34, 57, 36]))
54
+
55
+ mvp = proj * view * model
56
+ ```
57
+
58
+ This gem provides two basic variants for almost every operation. Let's use `Vec3#add` as an example. You can use the intuitive syntax:
59
+
60
+ ```ruby
61
+ result = a + b
62
+ ```
63
+
64
+ This will work just fine, returning a new `Vec3`. Or, in performance-critical situations, you may wish to directly specify a destination to place the result in:
65
+
66
+ ```ruby
67
+ result = Vec3.new
68
+ loop do
69
+ # avoid allocating a new Vec3 by reusing result
70
+ a.add(b, result)
71
+ end
72
+ ```
73
+
74
+ The second syntax is perhaps a little less intuitive, but avoids creation of extra objects (because you specify them yourself), so you can more easily control your memory and garbage collection costs.
75
+
76
+ There are too many methods to list here, so you are encouraged to check out the [project documentation](https://www.rubydoc.info/github/sinisterchipmunk/cglm-ruby).
77
+
78
+
79
+ ## Development
80
+
81
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
82
+
83
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
84
+
85
+ ## Contributing
86
+
87
+ Bug reports and pull requests are welcome on GitHub at https://github.com/sinisterchipmunk/cglm-ruby.
88
+
89
+ ## License
90
+
91
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ require "rake/extensiontask"
11
+
12
+ task :build => :compile
13
+
14
+ Rake::ExtensionTask.new("cglm") do |ext|
15
+ ext.lib_dir = "lib/cglm"
16
+ end
17
+
18
+ task :default => [:clobber, :compile, :test]
19
+
20
+ require 'yard'
21
+ desc 'generate documentation'
22
+ YARD::Rake::YardocTask.new(:doc)
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "cglm"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/cglm.gemspec ADDED
@@ -0,0 +1,46 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "cglm/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "cglm"
8
+ spec.version = CGLM::VERSION
9
+ spec.authors = ["Colin MacKenzie IV"]
10
+ spec.email = ["sinisterchipmunk@gmail.com"]
11
+
12
+ spec.summary = %q{CGLM bindings for Ruby}
13
+ spec.homepage = "https://github.com/sinisterchipmunk/cglm-ruby"
14
+ spec.license = "MIT"
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
20
+
21
+ spec.metadata["homepage_uri"] = spec.homepage
22
+ spec.metadata["source_code_uri"] = "https://github.com/sinisterchipmunk/cglm-ruby"
23
+ else
24
+ raise "RubyGems 2.0 or newer is required to protect against " \
25
+ "public gem pushes."
26
+ end
27
+
28
+ # Specify which files should be added to the gem when it is released.
29
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
30
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
31
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
32
+ end
33
+ spec.bindir = "exe"
34
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
35
+ spec.require_paths = ["lib"]
36
+ spec.extensions = ["ext/cglm/extconf.rb"]
37
+
38
+ spec.add_development_dependency "bundler", "~> 1.17"
39
+ spec.add_development_dependency "rake", "~> 10.0"
40
+ spec.add_development_dependency "rake-compiler"
41
+ spec.add_development_dependency "minitest", "~> 5.0"
42
+ spec.add_development_dependency "yard", "~> 0.9"
43
+ spec.add_development_dependency 'redcarpet'
44
+ spec.add_development_dependency 'github-markup'
45
+ spec.add_development_dependency 'simplecov'
46
+ end
@@ -0,0 +1,50 @@
1
+ require "mkmf"
2
+ require 'fileutils'
3
+ require 'rubygems/package'
4
+ require 'zlib'
5
+
6
+ #CGLM_VERSION = '0.5.0'
7
+ CGLM_VERSION = '89f64f079477b1af15f47e6b96db52c767acb057'
8
+ cglm_source_url = "https://github.com/recp/cglm/archive/#{CGLM_VERSION}.tar.gz"
9
+ cglm_tar_gz = File.expand_path("cglm-#{CGLM_VERSION}.tar.gz", __dir__)
10
+ cglm_dir = File.expand_path("cglm-#{CGLM_VERSION}", __dir__)
11
+
12
+ # fetch cglm unless it's already on the file system
13
+ unless File.exist?(cglm_dir)
14
+ require 'open-uri'
15
+ # save tarfile
16
+ open(cglm_tar_gz, 'wb') do |file|
17
+ file << open(cglm_source_url, 'rb').read
18
+ end
19
+
20
+ # extract tarfile
21
+ FileUtils.rm_rf cglm_dir if File.directory?(cglm_dir)
22
+ FileUtils.mkdir_p cglm_dir
23
+ tar_extract = Gem::Package::TarReader.new(Zlib::GzipReader.open(cglm_tar_gz))
24
+ tar_extract.rewind # The extract has to be rewinded after every iteration
25
+ tar_extract.each do |entry|
26
+ full_path = File.expand_path(entry.full_name, __dir__)
27
+ if entry.directory?
28
+ FileUtils.mkdir_p full_path
29
+ else
30
+ FileUtils.mkdir_p File.dirname(full_path)
31
+ File.open(full_path, 'wb') { |file| file << entry.read }
32
+ end
33
+ end
34
+ tar_extract.close
35
+ end
36
+
37
+ $INCFLAGS << " -I#{cglm_dir}/include"
38
+
39
+ require 'fiddle'
40
+ %w(
41
+ SIZEOF_VOIDP SIZEOF_CHAR SIZEOF_SHORT SIZEOF_INT SIZEOF_LONG SIZEOF_LONG_LONG
42
+ SIZEOF_FLOAT SIZEOF_DOUBLE SIZEOF_SIZE_T SIZEOF_SSIZE_T SIZEOF_PTRDIFF_T
43
+ SIZEOF_INTPTR_T SIZEOF_UINTPTR_T
44
+ ).each do |const_name|
45
+ if Fiddle.constants.include?(const_name.to_sym)
46
+ $CFLAGS << " -DHAVE_#{const_name}=1 -D#{const_name}=#{Fiddle.const_get(const_name.to_sym)}"
47
+ end
48
+ end
49
+
50
+ create_makefile("cglm/cglm")
@@ -0,0 +1,79 @@
1
+ #include "rb_cglm.h"
2
+
3
+ VALUE rb_cFiddle = Qnil,
4
+ rb_cPointer = Qnil,
5
+ rb_mCGLM = Qnil,
6
+ rb_cCGLMBase = Qnil,
7
+ rb_cVectorType = Qnil,
8
+ rb_cMat3 = Qnil,
9
+ rb_cMat4 = Qnil,
10
+ rb_cVec3 = Qnil,
11
+ rb_cVec4 = Qnil,
12
+ rb_cAABB = Qnil,
13
+ rb_mEuler = Qnil,
14
+ rb_cQuat = Qnil,
15
+ rb_cFrustum = Qnil,
16
+ rb_cSphere = Qnil,
17
+ rb_cPlane = Qnil;
18
+
19
+ VALUE rb_cglm_alloc_type(VALUE self, VALUE klass) {
20
+ VALUE rsize = rb_funcall(klass, rb_intern("size"), 0);
21
+ VALUE ralign = rb_funcall(klass, rb_intern("alignment"), 0);
22
+ size_t size = NUM2SIZET(rsize);
23
+ size_t align = NUM2SIZET(ralign);
24
+ void *addr = ALIGNED_ALLOC(align, size);
25
+ if (!addr)
26
+ rb_raise(rb_eRuntimeError, "could not allocate %zu bytes with %zu alignment", size, align);
27
+ return rb_funcall(rb_cPointer, rb_intern("new"), 2, PTR2NUM(addr), rsize);
28
+ }
29
+
30
+ void Init_cglm(void) {
31
+ rb_cFiddle = rb_const_get(rb_cObject, rb_intern("Fiddle"));
32
+ rb_cPointer = rb_const_get(rb_cFiddle, rb_intern("Pointer"));
33
+ rb_mCGLM = rb_define_module("CGLM");
34
+ rb_mEuler = rb_define_module_under(rb_mCGLM, "Euler");
35
+ rb_cCGLMBase = rb_define_class_under(rb_mCGLM, "Base", rb_cObject);
36
+ rb_cMat3 = rb_define_class_under(rb_mCGLM, "Mat3", rb_cCGLMBase);
37
+ rb_cMat4 = rb_define_class_under(rb_mCGLM, "Mat4", rb_cCGLMBase);
38
+ rb_cCGLMBase = rb_define_class_under(rb_mCGLM, "Base", rb_cObject);
39
+ rb_cVectorType = rb_define_class_under(rb_mCGLM, "VectorType", rb_cCGLMBase);
40
+ rb_cAABB = rb_define_class_under(rb_mCGLM, "AABB", rb_cCGLMBase);
41
+ rb_cVec3 = rb_define_class_under(rb_mCGLM, "Vec3", rb_cVectorType);
42
+ rb_cVec4 = rb_define_class_under(rb_mCGLM, "Vec4", rb_cVectorType);
43
+ rb_cFrustum = rb_define_class_under(rb_mCGLM, "Frustum", rb_cObject);
44
+ rb_cSphere = rb_define_class_under(rb_mCGLM, "Sphere", rb_cVec4);
45
+ rb_cQuat = rb_define_class_under(rb_mCGLM, "Quat", rb_cVec4);
46
+ rb_cPlane = rb_define_class_under(rb_mCGLM, "Plane", rb_cVec4);
47
+
48
+ rb_define_const(rb_mCGLM, "E" , DBL2NUM(GLM_E));
49
+ rb_define_const(rb_mCGLM, "LOG2E", DBL2NUM(GLM_LOG2E));
50
+ rb_define_const(rb_mCGLM, "LOG10E", DBL2NUM(GLM_LOG10E));
51
+ rb_define_const(rb_mCGLM, "LN2", DBL2NUM(GLM_LN2));
52
+ rb_define_const(rb_mCGLM, "LN10", DBL2NUM(GLM_LN10));
53
+ rb_define_const(rb_mCGLM, "PI", DBL2NUM(GLM_PI));
54
+ rb_define_const(rb_mCGLM, "PI_2", DBL2NUM(GLM_PI_2));
55
+ rb_define_const(rb_mCGLM, "PI_4", DBL2NUM(GLM_PI_4));
56
+ rb_define_const(rb_mCGLM, "ONE_OVER_PI", DBL2NUM(GLM_1_PI));
57
+ rb_define_const(rb_mCGLM, "TWO_OVER_PI", DBL2NUM(GLM_2_PI));
58
+ rb_define_const(rb_mCGLM, "TWO_OVER_SQRTPI", DBL2NUM(GLM_2_SQRTPI));
59
+ rb_define_const(rb_mCGLM, "SQRT2", DBL2NUM(GLM_SQRT2));
60
+ rb_define_const(rb_mCGLM, "SQRT1_2", DBL2NUM(GLM_SQRT1_2));
61
+
62
+ rb_define_singleton_method(rb_mCGLM, "alloc", rb_cglm_alloc_type, 1);
63
+
64
+ Init_cglm_affine();
65
+ Init_cglm_box();
66
+ Init_cglm_cam();
67
+ Init_cglm_color();
68
+ Init_cglm_ease();
69
+ Init_cglm_euler();
70
+ Init_cglm_frustum();
71
+ Init_cglm_mat3();
72
+ Init_cglm_mat4();
73
+ Init_cglm_plane();
74
+ Init_cglm_project();
75
+ Init_cglm_quat();
76
+ Init_cglm_sphere();
77
+ Init_cglm_vec3();
78
+ Init_cglm_vec4();
79
+ }
@@ -0,0 +1,169 @@
1
+ #ifndef RB_CGLM_H
2
+ #define RB_CGLM_H 1
3
+
4
+ #include "ruby.h"
5
+ #include <errno.h>
6
+
7
+ // Based on unit test results I think the FLT_EPSILON that is used for fuzzy
8
+ // equality by CGLM may be too strict. This HACK works around the issue.
9
+ #include <float.h>
10
+ #undef FLT_EPSILON
11
+ #define FLT_EPSILON 0.00001
12
+
13
+ #include "cglm/cglm.h"
14
+
15
+ #ifdef __MINGW32__
16
+ #include <stdlib.h>
17
+ #include <intrin.h>
18
+ #include <malloc.h>
19
+ #include <winsock2.h>
20
+ #include <windows.h>
21
+ #define drand48() (((double)rand()) / RAND_MAX)
22
+ #endif // __MINGW32__
23
+ #undef GLM_VEC3_ONE_INIT
24
+ #undef GLM_VEC3_ZERO_INIT
25
+ #undef GLM_VEC3_ONE
26
+ #undef GLM_VEC3_ZERO
27
+ #undef GLM_YUP
28
+ #undef GLM_ZUP
29
+ #undef GLM_XUP
30
+ #undef GLM_VEC4_ONE
31
+ #undef GLM_VEC4_BLACK
32
+ #undef GLM_VEC4_ZERO
33
+ #define GLM_VEC3_ONE_INIT {1.0f, 1.0f, 1.0f}
34
+ #define GLM_VEC3_ZERO_INIT {0.0f, 0.0f, 0.0f}
35
+ #define GLM_VEC3_ONE GLM_VEC3_ONE_INIT
36
+ #define GLM_VEC3_ZERO GLM_VEC3_ZERO_INIT
37
+ #define GLM_YUP {0.0f, 1.0f, 0.0f}
38
+ #define GLM_ZUP {0.0f, 0.0f, 1.0f}
39
+ #define GLM_XUP {1.0f, 0.0f, 0.0f}
40
+ #define GLM_VEC4_ONE GLM_VEC4_ONE_INIT
41
+ #define GLM_VEC4_BLACK GLM_VEC4_BLACK_INIT
42
+ #define GLM_VEC4_ZERO GLM_VEC4_ZERO_INIT
43
+
44
+ #if SIZEOF_VOIDP == SIZEOF_LONG
45
+ # define PTR2NUM(x) (LONG2NUM((long)(x)))
46
+ # define NUM2PTR(x) ((void*)(NUM2ULONG(x)))
47
+ #else
48
+ # define PTR2NUM(x) (LL2NUM((LONG_LONG)(x)))
49
+ # define NUM2PTR(x) ((void*)(NUM2ULL(x)))
50
+ #endif
51
+
52
+ #define CHECK_RANGE(val, min, max) \
53
+ if (NUM2INT(val) < min || NUM2INT(val) > max) \
54
+ rb_raise(rb_eRangeError, "index %d out of bounds (%d..%d)", NUM2INT(val), min, max);
55
+
56
+ void Init_cglm_affine();
57
+ void Init_cglm_box();
58
+ void Init_cglm_cam();
59
+ void Init_cglm_color();
60
+ void Init_cglm_ease();
61
+ void Init_cglm_euler();
62
+ void Init_cglm_frustum();
63
+ void Init_cglm_io();
64
+ void Init_cglm_mat3();
65
+ void Init_cglm_mat4();
66
+ void Init_cglm_plane();
67
+ void Init_cglm_project();
68
+ void Init_cglm_quat();
69
+ void Init_cglm_sphere();
70
+ void Init_cglm_vec3();
71
+ void Init_cglm_vec4();
72
+
73
+ #define VEC3_ALIGNMENT 8
74
+ #define VEC4_ALIGNMENT 16
75
+ #define AABB_ALIGNMENT 8
76
+ #define QUAT_ALIGNMENT 16
77
+ #ifdef __AVX__
78
+ #define MAT4_ALIGNMENT 32
79
+ #define MAT3_ALIGNMENT 32
80
+ #else
81
+ #define MAT4_ALIGNMENT 16
82
+ #define MAT3_ALIGNMENT 16
83
+ #endif
84
+ #define PLANE_ALIGNMENT VEC4_ALIGNMENT
85
+
86
+ extern VALUE rb_cFiddle, rb_cPointer, rb_mCGLM, rb_cCGLMBase, rb_cVectorType,
87
+ rb_cMat4, rb_cVec3, rb_cVec4, rb_cAABB, rb_mEuler, rb_cQuat,
88
+ rb_cFrustum, rb_cMat3, rb_cSphere, rb_cPlane;
89
+
90
+ typedef struct { vec3 corners[2]; } aabb;
91
+ typedef struct { vec4 planes[6]; } frustum;
92
+ typedef vec4 quat;
93
+ typedef vec4 plane;
94
+
95
+ static inline size_t vec3_size() { return sizeof(vec3); }
96
+ static inline size_t vec4_size() { return sizeof(vec4); }
97
+ static inline size_t aabb_size() { return sizeof(aabb); }
98
+ static inline size_t mat4_size() { return sizeof(mat4); }
99
+ static inline size_t mat3_size() { return sizeof(mat4); }
100
+ static inline size_t quat_size() { return sizeof(mat4); }
101
+ static inline size_t plane_size() { return sizeof(plane); }
102
+
103
+ #define PTR2FIDDLE(addr, size) rb_funcall(rb_cPointer, rb_intern("new"), 2, PTR2NUM(addr), SIZET2NUM(size))
104
+
105
+ static inline VALUE CGLM_NEW(VALUE klass, size_t size, void *addr) {
106
+ VALUE kw = rb_hash_new();
107
+ VALUE ptr = PTR2FIDDLE(addr, size);
108
+ rb_hash_aset(kw, ID2SYM(rb_intern("addr")), ptr);
109
+ return rb_funcall(klass, rb_intern("new"), 1, kw);
110
+ }
111
+
112
+ static inline void *__aligned_alloc(size_t align, size_t size) {
113
+ void *mem = NULL;
114
+ #ifdef __MINGW32__
115
+ mem = _aligned_malloc(size, align);
116
+ int err = 0;
117
+ if (!mem) err = ENOMEM;
118
+ #else
119
+ int err = posix_memalign(&mem, align, size);
120
+ #endif
121
+ switch(err) {
122
+ case EINVAL:
123
+ rb_raise(rb_eRuntimeError, "Alignment %zu was not a power of two, or was not a multiple of sizeof(void *) == %zu", align, sizeof(void *));
124
+ case ENOMEM:
125
+ rb_raise(rb_eRuntimeError, "Insufficient memory");
126
+ }
127
+ return mem;
128
+ }
129
+
130
+ #define ALIGNED_ALLOC(align, size) __aligned_alloc(align, size)
131
+
132
+ #define VEC3_NEW(addr) CGLM_NEW(rb_cVec3, vec3_size(), addr)
133
+ #define VEC4_NEW(addr) CGLM_NEW(rb_cVec4, vec4_size(), addr)
134
+ #define MAT4_NEW(addr) CGLM_NEW(rb_cMat4, mat4_size(), addr)
135
+ #define MAT3_NEW(addr) CGLM_NEW(rb_cMat3, mat3_size(), addr)
136
+ #define AABB_NEW(addr) CGLM_NEW(rb_cAABB, aabb_size(), addr)
137
+ #define QUAT_NEW(addr) CGLM_NEW(rb_cQuat, quat_size(), addr)
138
+ #define PLANE_NEW(addr) CGLM_NEW(rb_cPlane, plane_size(), addr);
139
+
140
+ #define ALLOC_VEC3 ALIGNED_ALLOC(VEC3_ALIGNMENT, sizeof(vec3))
141
+ #define ALLOC_VEC4 ALIGNED_ALLOC(VEC4_ALIGNMENT, sizeof(vec4))
142
+ #define ALLOC_AABB ALIGNED_ALLOC(AABB_ALIGNMENT, sizeof(aabb))
143
+ #define ALLOC_QUAT ALIGNED_ALLOC(QUAT_ALIGNMENT, sizeof(quat))
144
+ #define ALLOC_MAT4 ALIGNED_ALLOC(MAT4_ALIGNMENT, sizeof(mat4))
145
+ #define ALLOC_MAT3 ALIGNED_ALLOC(MAT3_ALIGNMENT, sizeof(mat3))
146
+ #define ALLOC_PLANE ALIGNED_ALLOC(PLANE_ALIGNMENT, sizeof(plane))
147
+
148
+ // #define VAL2ADDR(val) NUM2PTR(rb_funcall(rb_ivar_get(val, rb_intern("@addr")), rb_intern("to_i"), 0))
149
+
150
+ static inline void *VAL2ADDR(VALUE val, size_t min_size) {
151
+ VALUE addr = rb_funcall(val, rb_intern("addr"), 0);
152
+ VALUE size = rb_funcall(addr, rb_intern("size"), 0);
153
+ if (min_size > NUM2SIZET(size))
154
+ rb_raise(rb_eArgError, "memory store (size %zu) is not large enough to be converted into the requested type (size %zu)", NUM2SIZET(size), min_size);
155
+ return NUM2PTR(rb_funcall(addr, rb_intern("to_i"), 0));
156
+ }
157
+
158
+ #define VAL2VEC3(val) (*((vec3 *)(VAL2ADDR(val, sizeof(vec3) ))))
159
+ #define VAL2VEC4(val) (*((vec4 *)(VAL2ADDR(val, sizeof(vec4) ))))
160
+ #define VAL2MAT4(val) (*((mat4 *)(VAL2ADDR(val, sizeof(mat4) ))))
161
+ #define VAL2MAT3(val) (*((mat3 *)(VAL2ADDR(val, sizeof(mat3) ))))
162
+ #define VAL2AABB(val) (*((aabb *)(VAL2ADDR(val, sizeof(aabb) ))))
163
+ #define VAL2QUAT(val) (*((quat *)(VAL2ADDR(val, sizeof(quat) ))))
164
+ #define VAL2FRUSTUM(val) (*((frustum *)(VAL2ADDR(val, sizeof(frustum) ))))
165
+ #define VAL2PLANE(val) (*((plane *)(VAL2ADDR(val, sizeof(plane) ))))
166
+
167
+ #define NUM2FLT(val) ((float) NUM2DBL(val))
168
+
169
+ #endif /* CGLM_H */