tiny_gltf 0.1.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/Gemfile.lock +3 -3
  4. data/bin/setup +2 -0
  5. data/ext/tiny_gltf/rb_tiny_gltf.h +18 -7
  6. data/ext/tiny_gltf/rb_tiny_gltf_accessor.cpp +4 -12
  7. data/ext/tiny_gltf/rb_tiny_gltf_animation.cpp +6 -5
  8. data/ext/tiny_gltf/rb_tiny_gltf_animation_channel.cpp +6 -5
  9. data/ext/tiny_gltf/rb_tiny_gltf_animation_sampler.cpp +6 -5
  10. data/ext/tiny_gltf/rb_tiny_gltf_asset.cpp +4 -3
  11. data/ext/tiny_gltf/rb_tiny_gltf_buffer.cpp +37 -8
  12. data/ext/tiny_gltf/rb_tiny_gltf_buffer_view.cpp +4 -3
  13. data/ext/tiny_gltf/rb_tiny_gltf_camera.cpp +4 -3
  14. data/ext/tiny_gltf/rb_tiny_gltf_extension_map.cpp +2 -2
  15. data/ext/tiny_gltf/rb_tiny_gltf_image.cpp +72 -12
  16. data/ext/tiny_gltf/rb_tiny_gltf_init.c +66 -1
  17. data/ext/tiny_gltf/rb_tiny_gltf_light.cpp +2 -1
  18. data/ext/tiny_gltf/rb_tiny_gltf_material.cpp +6 -5
  19. data/ext/tiny_gltf/rb_tiny_gltf_mesh.cpp +5 -17
  20. data/ext/tiny_gltf/rb_tiny_gltf_model.cpp +10 -10
  21. data/ext/tiny_gltf/rb_tiny_gltf_node.cpp +8 -7
  22. data/ext/tiny_gltf/rb_tiny_gltf_parameter_map.cpp +2 -2
  23. data/ext/tiny_gltf/rb_tiny_gltf_primitive.cpp +8 -7
  24. data/ext/tiny_gltf/rb_tiny_gltf_sampler.cpp +3 -2
  25. data/ext/tiny_gltf/rb_tiny_gltf_scene.cpp +7 -6
  26. data/ext/tiny_gltf/rb_tiny_gltf_skin.cpp +6 -5
  27. data/ext/tiny_gltf/rb_tiny_gltf_texture.cpp +7 -6
  28. data/ext/tiny_gltf/rb_tiny_gltf_types.cpp +7 -7
  29. data/ext/tiny_gltf/rb_tiny_gltf_value.cpp +5 -4
  30. data/ext/tiny_gltf/stb_image.h +1890 -869
  31. data/ext/tiny_gltf/stb_image_write.h +1241 -1451
  32. data/ext/tiny_gltf/tiny_gltf.h +3671 -1082
  33. data/lib/tiny_gltf.rb +385 -126
  34. data/lib/tiny_gltf/version.rb +1 -1
  35. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b954a969cc444a33651e63d72d15d816b3b5f109d419179dfded48934099c9d3
4
- data.tar.gz: fefc289f2b3c6caa665a267aa5c7f8a19c732c44a8321cca22dc5739b3a75d6f
3
+ metadata.gz: 5158d1be6e6b7ca81b1811dfe102928bf646465f249aa40d1d9a6c28ff8db94a
4
+ data.tar.gz: 8144cd44561010a81aeabd21ae722290882e99767d2aa6a1db7dbcac14436756
5
5
  SHA512:
6
- metadata.gz: de2c43dd86086b3b5abed2be79de26b0720273ad6af6fd56752be3dd12f38a92040824a46179967c672de0e3f2461c03d8df7e9f1e2f8934ca6b009e82c0e650
7
- data.tar.gz: d023f445d65862e8b20a52b38b5597e5b2b7606974f6ccddab6f7bd105611fdd1aa538f8dd36da292106bc70e0b6c2b43c4716e478cc53e92f28595f75cc8523
6
+ metadata.gz: 48dd3bf544f2af2c009c26cbf5d28e14a89a18ab27649fd2ce83863f2a9b4758ae3a7e21f71d6289be4d06ba09eac43f1db46af47e5357ae5aa36bf47036b92e
7
+ data.tar.gz: a6eb083a256ea2fb43a8ee9c241ee2ce596b32d267907a84a533c11433a47c18812934a69bed7f603470512402c1eb7e748062b528c0c753ec581126b0ae11c1
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "test/fixtures/gltf_sample_models"]
2
+ path = test/fixtures/gltf_sample_models
3
+ url = https://github.com/KhronosGroup/glTF-Sample-Models
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tiny_gltf (0.1.0)
4
+ tiny_gltf (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -12,7 +12,7 @@ GEM
12
12
  rake-compiler (1.0.5)
13
13
  rake
14
14
  redcarpet (3.4.0)
15
- yard (0.9.16)
15
+ yard (0.9.20)
16
16
 
17
17
  PLATFORMS
18
18
  ruby
@@ -28,4 +28,4 @@ DEPENDENCIES
28
28
  yard (~> 0.9)
29
29
 
30
30
  BUNDLED WITH
31
- 2.0.0.pre.1
31
+ 2.0.2
data/bin/setup CHANGED
@@ -6,3 +6,5 @@ set -vx
6
6
  bundle install
7
7
 
8
8
  # Do any other automated setup that you need to do here
9
+ git submodule init
10
+ git submodule update
@@ -35,6 +35,8 @@ extern VALUE rb_mTinyGLTF,
35
35
  VALUE name ## _is_equal(VALUE self, VALUE other); \
36
36
  VALUE name ## _alloc(VALUE klass);
37
37
 
38
+ #define RINDEX_OR_NIL(n) (n == -1 ? Qnil : INT2NUM(n))
39
+
38
40
  GLTF_TYPE(Model);
39
41
  GLTF_TYPE(Accessor);
40
42
  GLTF_TYPE(Asset);
@@ -68,18 +70,26 @@ VALUE texture_type_to_sym(int type);
68
70
  VALUE target_to_sym(int tgt);
69
71
  VALUE shader_type_to_sym(int type);
70
72
 
71
- VALUE Accessor_byte_stride(VALUE self, VALUE buffer_view);
73
+ VALUE Buffer_to_ptr(VALUE self);
74
+ VALUE Buffer_size(VALUE self);
75
+ VALUE Buffer_to_s(VALUE self);
76
+ VALUE Buffer_uri(VALUE self);
77
+ VALUE Image_set_uri(VALUE self, VALUE uri);
78
+ VALUE Image_to_ptr(VALUE self);
79
+ VALUE Image_size(VALUE self);
80
+ VALUE Image_to_s(VALUE self);
81
+ VALUE Image_uri(VALUE self);
72
82
 
73
83
  #if __cplusplus
74
84
  /*
75
- VALUE rModel_new(const Model *);
85
+ VALUE rAccessor_new(const Accessor *, VALUE);
76
86
  */
77
- #define GLTF_RUBY_WRAP(klass) VALUE r ## klass ## _new(const klass *);
87
+ #define GLTF_RUBY_WRAP(klass) VALUE r ## klass ## _new(const klass *, VALUE);
78
88
 
79
89
  /*
80
- static inline Model *Model_unwrap(VALUE val) {
81
- Model *a = NULL;
82
- TypedData_Get_Struct(val, Model, &T_Model, a);
90
+ static inline Accessor *Accessor_unwrap(VALUE val) {
91
+ Accessor *a = NULL;
92
+ TypedData_Get_Struct(val, Accessor, &T_Accessor, a);
83
93
  if (a == NULL)
84
94
  rb_raise(rb_eArgError, "BUG: " #name " is NULL");
85
95
  return a;
@@ -101,9 +111,10 @@ VALUE Accessor_byte_stride(VALUE self, VALUE buffer_view);
101
111
  GLTF_RUBY_WRAP(ParameterMap);
102
112
  GLTF_RUBY_WRAP(Value);
103
113
 
114
+ VALUE rModel_new(const Model *);
115
+ GLTF_RUBY_UNWRAP(Model);
104
116
  GLTF_RUBY_WRAPPERS(Asset);
105
117
  GLTF_RUBY_WRAPPERS(Primitive);
106
- GLTF_RUBY_WRAPPERS(Model);
107
118
  GLTF_RUBY_WRAPPERS(Accessor);
108
119
  GLTF_RUBY_WRAPPERS(Animation);
109
120
  GLTF_RUBY_WRAPPERS(AnimationSampler);
@@ -1,17 +1,18 @@
1
1
  #include "rb_tiny_gltf.h"
2
2
 
3
- VALUE rAccessor_new(const Accessor *accessor) {
3
+ VALUE rAccessor_new(const Accessor *accessor, VALUE rmodel) {
4
4
  VALUE raccessor = rb_funcall(rb_cAccessor, rb_intern("new"), 0);
5
5
  *Accessor_unwrap(raccessor) = *accessor;
6
6
 
7
- rb_ivar_set(raccessor, rb_intern("@buffer_view_index"), INT2NUM(accessor->bufferView));
7
+ rb_ivar_set(raccessor, rb_intern("@model"), rmodel);
8
+ rb_ivar_set(raccessor, rb_intern("@buffer_view_index"), RINDEX_OR_NIL(accessor->bufferView));
8
9
  rb_ivar_set(raccessor, rb_intern("@component_type"), component_type_to_sym(accessor->componentType));
9
10
  rb_ivar_set(raccessor, rb_intern("@count"), SIZET2NUM(accessor->count));
10
11
  rb_ivar_set(raccessor, rb_intern("@name"), rb_str_new2(accessor->name.c_str()));
11
12
  rb_ivar_set(raccessor, rb_intern("@byte_offset"), SIZET2NUM(accessor->byteOffset));
12
13
  rb_ivar_set(raccessor, rb_intern("@normalized"), accessor->normalized ? Qtrue : Qfalse);
13
14
  rb_ivar_set(raccessor, rb_intern("@type"), type_to_sym(accessor->type));
14
- rb_ivar_set(raccessor, rb_intern("@extras"), rValue_new(&accessor->extras));
15
+ rb_ivar_set(raccessor, rb_intern("@extras"), rValue_new(&accessor->extras, rmodel));
15
16
  rb_ivar_set(raccessor, rb_intern("@min"), Qnil);
16
17
  rb_ivar_set(raccessor, rb_intern("@max"), Qnil);
17
18
 
@@ -31,12 +32,3 @@ VALUE rAccessor_new(const Accessor *accessor) {
31
32
 
32
33
  return raccessor;
33
34
  }
34
-
35
- /* call-seq: byte_stride(buffer_view) => Numeric
36
- *
37
- * Returns the calculated byte stride for this accessor and the given buffer
38
- * view.
39
- */
40
- VALUE Accessor_byte_stride(VALUE self, VALUE buffer_view) {
41
- return INT2NUM(Accessor_unwrap(self)->ByteStride(*BufferView_unwrap(buffer_view)));
42
- }
@@ -1,21 +1,22 @@
1
1
  #include "rb_tiny_gltf.h"
2
2
 
3
- VALUE rAnimation_new(const Animation *animation) {
3
+ VALUE rAnimation_new(const Animation *animation, VALUE rmodel) {
4
4
  VALUE ranimation = rb_funcall(rb_cAnimation, rb_intern("new"), 0);
5
5
  // *Animation_unwrap(ranimation) = *animation;
6
6
 
7
7
  VALUE rchannels = rb_ary_new();
8
8
  for (size_t i = 0; i < animation->channels.size(); i++)
9
- rb_ary_push(rchannels, rAnimationChannel_new(&animation->channels[i]));
9
+ rb_ary_push(rchannels, rAnimationChannel_new(&animation->channels[i], ranimation));
10
10
 
11
11
  VALUE rsamplers = rb_ary_new();
12
12
  for (size_t i = 0; i < animation->samplers.size(); i++)
13
- rb_ary_push(rsamplers, rAnimationSampler_new(&animation->samplers[i]));
13
+ rb_ary_push(rsamplers, rAnimationSampler_new(&animation->samplers[i], ranimation));
14
14
 
15
+ rb_ivar_set(ranimation, rb_intern("@model"), rmodel);
15
16
  rb_ivar_set(ranimation, rb_intern("@name"), rb_str_new2(animation->name.c_str()));
16
17
  rb_ivar_set(ranimation, rb_intern("@channels"), rchannels);
17
- rb_ivar_set(ranimation, rb_intern("@rsamplers"), rsamplers);
18
- rb_ivar_set(ranimation, rb_intern("@extras"), rValue_new(&animation->extras));
18
+ rb_ivar_set(ranimation, rb_intern("@samplers"), rsamplers);
19
+ rb_ivar_set(ranimation, rb_intern("@extras"), rValue_new(&animation->extras, rmodel));
19
20
 
20
21
  return ranimation;
21
22
  }
@@ -1,13 +1,14 @@
1
1
  #include "rb_tiny_gltf.h"
2
2
 
3
- VALUE rAnimationChannel_new(const AnimationChannel *animation_channel) {
3
+ VALUE rAnimationChannel_new(const AnimationChannel *animation_channel, VALUE ranimation) {
4
4
  VALUE ranimation_channel = rb_funcall(rb_cAnimationChannel, rb_intern("new"), 0);
5
5
  // *AnimationChannel_unwrap(ranimation_channel) = *animation_channel;
6
6
 
7
- rb_ivar_set(ranimation_channel, rb_intern("@sampler_index"), INT2NUM(animation_channel->sampler));
8
- rb_ivar_set(ranimation_channel, rb_intern("@target_node_index"), INT2NUM(animation_channel->target_node));
9
- rb_ivar_set(ranimation_channel, rb_intern("@target_path"), rb_intern(animation_channel->target_path.c_str()));
10
- rb_ivar_set(ranimation_channel, rb_intern("@extras"), rValue_new(&animation_channel->extras));
7
+ rb_ivar_set(ranimation_channel, rb_intern("@animation"), ranimation);
8
+ rb_ivar_set(ranimation_channel, rb_intern("@sampler_index"), RINDEX_OR_NIL(animation_channel->sampler));
9
+ rb_ivar_set(ranimation_channel, rb_intern("@target_node_index"), RINDEX_OR_NIL(animation_channel->target_node));
10
+ rb_ivar_set(ranimation_channel, rb_intern("@target_path"), ID2SYM(rb_intern(animation_channel->target_path.c_str())));
11
+ rb_ivar_set(ranimation_channel, rb_intern("@extras"), rValue_new(&animation_channel->extras, rb_funcall(ranimation, rb_intern("model"), 0)));
11
12
 
12
13
  return ranimation_channel;
13
14
  }
@@ -1,16 +1,17 @@
1
1
  #include "rb_tiny_gltf.h"
2
2
 
3
- VALUE rAnimationSampler_new(const AnimationSampler *animation_sampler) {
3
+ VALUE rAnimationSampler_new(const AnimationSampler *animation_sampler, VALUE ranimation) {
4
4
  VALUE ranimation_sampler = rb_funcall(rb_cAnimationSampler, rb_intern("new"), 0);
5
5
  // *AnimationSampler_unwrap(ranimation_sampler) = *animation_sampler;
6
6
 
7
7
  std::string interp = animation_sampler->interpolation;
8
8
  std::transform(interp.begin(), interp.end(), interp.begin(), ::tolower);
9
9
 
10
- rb_ivar_set(ranimation_sampler, rb_intern("@input"), INT2NUM(animation_sampler->input));
11
- rb_ivar_set(ranimation_sampler, rb_intern("@output"), INT2NUM(animation_sampler->output));
12
- rb_ivar_set(ranimation_sampler, rb_intern("@interpolation"), rb_intern(interp.c_str()));
13
- rb_ivar_set(ranimation_sampler, rb_intern("@extras"), rValue_new(&animation_sampler->extras));
10
+ rb_ivar_set(ranimation_sampler, rb_intern("@animation"), ranimation);
11
+ rb_ivar_set(ranimation_sampler, rb_intern("@input_index"), RINDEX_OR_NIL(animation_sampler->input));
12
+ rb_ivar_set(ranimation_sampler, rb_intern("@output_index"), RINDEX_OR_NIL(animation_sampler->output));
13
+ rb_ivar_set(ranimation_sampler, rb_intern("@interpolation"), ID2SYM(rb_intern(interp.c_str())));
14
+ rb_ivar_set(ranimation_sampler, rb_intern("@extras"), rValue_new(&animation_sampler->extras, rb_funcall(ranimation, rb_intern("model"), 0)));
14
15
 
15
16
  return ranimation_sampler;
16
17
  }
@@ -1,15 +1,16 @@
1
1
  #include "rb_tiny_gltf.h"
2
2
 
3
- VALUE rAsset_new(const Asset *asset) {
3
+ VALUE rAsset_new(const Asset *asset, VALUE rmodel) {
4
4
  VALUE rasset = rb_funcall(rb_cAsset, rb_intern("new"), 0);
5
5
  // *Asset_unwrap(rasset) = *asset;
6
6
 
7
+ rb_ivar_set(rasset, rb_intern("@model"), rmodel);
7
8
  rb_ivar_set(rasset, rb_intern("@version"), rb_str_new2(asset->version.c_str()));
8
9
  rb_ivar_set(rasset, rb_intern("@generator"), rb_str_new2(asset->generator.c_str()));
9
10
  rb_ivar_set(rasset, rb_intern("@min_version"), rb_str_new2(asset->minVersion.c_str()));
10
11
  rb_ivar_set(rasset, rb_intern("@copyright"), rb_str_new2(asset->copyright.c_str()));
11
- rb_ivar_set(rasset, rb_intern("@extensions"), rExtensionMap_new(&asset->extensions));
12
- rb_ivar_set(rasset, rb_intern("@extras"), rValue_new(&asset->extras));
12
+ rb_ivar_set(rasset, rb_intern("@extensions"), rExtensionMap_new(&asset->extensions, rmodel));
13
+ rb_ivar_set(rasset, rb_intern("@extras"), rValue_new(&asset->extras, rmodel));
13
14
 
14
15
  return rasset;
15
16
  }
@@ -1,16 +1,45 @@
1
1
  #include "rb_tiny_gltf.h"
2
2
 
3
- VALUE rBuffer_new(const Buffer *buf) {
3
+ VALUE rBuffer_new(const Buffer *buf, VALUE rmodel) {
4
4
  VALUE rbuf = rb_funcall(rb_cBuffer, rb_intern("new"), 0);
5
- // *Buffer_unwrap(rbuf) = *buf;
6
5
 
7
- rb_ivar_set(rbuf, rb_intern("@name"), rb_str_new2(buf->name.c_str()));
8
- rb_ivar_set(rbuf, rb_intern("@data"), rb_str_new((char *) buf->data.data(), buf->data.size()));
9
- rb_ivar_set(rbuf, rb_intern("@uri"), Qnil);
10
- rb_ivar_set(rbuf, rb_intern("@extras"), rValue_new(&buf->extras));
6
+ // Keep (yes duplicate but the original will be freed) the buffer data
7
+ // in memory w/o having to wrap with a ruby string, which can be expensive
8
+ // and inefficient.
9
+ Buffer *dup = Buffer_unwrap(rbuf);
10
+ dup->data = buf->data;
11
+ dup->uri = buf->uri;
11
12
 
12
- if (buf->uri.size() > 0)
13
- rb_ivar_set(rbuf, rb_intern("@uri"), rb_str_new2(buf->uri.c_str()));
13
+ rb_ivar_set(rbuf, rb_intern("@model"), rmodel);
14
+ rb_ivar_set(rbuf, rb_intern("@name"), rb_str_new2(buf->name.c_str()));
15
+ rb_ivar_set(rbuf, rb_intern("@extras"), rValue_new(&buf->extras, rmodel));
14
16
 
15
17
  return rbuf;
16
18
  }
19
+
20
+ VALUE Buffer_to_ptr(VALUE self) {
21
+ // return Fiddle::Pointer.new(addr, size)
22
+ VALUE rFiddlePointer = rb_const_get(rb_const_get(rb_cObject, rb_intern("Fiddle")),
23
+ rb_intern("Pointer"));
24
+ Buffer *buf = Buffer_unwrap(self);
25
+ return rb_funcall(rFiddlePointer, rb_intern("new"), 2,
26
+ ULL2NUM((unsigned long long) buf->data.data()),
27
+ ULL2NUM((unsigned long long) buf->data.size()));
28
+ }
29
+
30
+ VALUE Buffer_size(VALUE self) {
31
+ return ULONG2NUM(Buffer_unwrap(self)->data.size());
32
+ }
33
+
34
+ VALUE Buffer_to_s(VALUE self) {
35
+ Buffer *buf = Buffer_unwrap(self);
36
+ return rb_str_new((char *) buf->data.data(), buf->data.size());
37
+ }
38
+
39
+ VALUE Buffer_uri(VALUE self) {
40
+ Buffer *buf = Buffer_unwrap(self);
41
+ if (buf->uri.size() > 0)
42
+ return rb_str_new2(buf->uri.c_str());
43
+ else
44
+ return Qnil;
45
+ }
@@ -1,16 +1,17 @@
1
1
  #include "rb_tiny_gltf.h"
2
2
 
3
- VALUE rBufferView_new(const BufferView *view) {
3
+ VALUE rBufferView_new(const BufferView *view, VALUE rmodel) {
4
4
  VALUE rbuf = rb_funcall(rb_cBufferView, rb_intern("new"), 0);
5
5
  *BufferView_unwrap(rbuf) = *view;
6
6
 
7
+ rb_ivar_set(rbuf, rb_intern("@model"), rmodel);
7
8
  rb_ivar_set(rbuf, rb_intern("@name"), rb_str_new2(view->name.c_str()));
8
- rb_ivar_set(rbuf, rb_intern("@buffer_index"), INT2NUM(view->buffer));
9
+ rb_ivar_set(rbuf, rb_intern("@buffer_index"), RINDEX_OR_NIL(view->buffer));
9
10
  rb_ivar_set(rbuf, rb_intern("@byte_offset"), SIZET2NUM(view->byteOffset));
10
11
  rb_ivar_set(rbuf, rb_intern("@byte_length"), SIZET2NUM(view->byteLength));
11
12
  rb_ivar_set(rbuf, rb_intern("@byte_stride"), SIZET2NUM(view->byteStride));
12
13
  rb_ivar_set(rbuf, rb_intern("@target"), target_to_sym(view->target));
13
- rb_ivar_set(rbuf, rb_intern("@extras"), rValue_new(&view->extras));
14
+ rb_ivar_set(rbuf, rb_intern("@extras"), rValue_new(&view->extras, rmodel));
14
15
 
15
16
  return rbuf;
16
17
  }
@@ -1,13 +1,14 @@
1
1
  #include "rb_tiny_gltf.h"
2
2
 
3
- VALUE rCamera_new(const Camera *camera) {
3
+ VALUE rCamera_new(const Camera *camera, VALUE rmodel) {
4
4
  VALUE rcamera = rb_funcall(rb_cCamera, rb_intern("new"), 0);
5
5
  // *Camera_unwrap(rcamera) = *camera;
6
6
 
7
+ rb_ivar_set(rcamera, rb_intern("@model"), rmodel);
7
8
  rb_ivar_set(rcamera, rb_intern("@name"), rb_str_new2(camera->name.c_str()));
8
9
  rb_ivar_set(rcamera, rb_intern("@type"), rb_intern(camera->type.c_str()));
9
- rb_ivar_set(rcamera, rb_intern("@extensions"), rExtensionMap_new(&camera->extensions));
10
- rb_ivar_set(rcamera, rb_intern("@extras"), rValue_new(&camera->extras));
10
+ rb_ivar_set(rcamera, rb_intern("@extensions"), rExtensionMap_new(&camera->extensions, rmodel));
11
+ rb_ivar_set(rcamera, rb_intern("@extras"), rValue_new(&camera->extras, rmodel));
11
12
 
12
13
  if (!strcmp(camera->type.c_str(), "perspective")) {
13
14
  rb_ivar_set(rcamera, rb_intern("@aspect_ratio"), DBL2NUM(camera->perspective.aspectRatio));
@@ -1,11 +1,11 @@
1
1
  #include "rb_tiny_gltf.h"
2
2
 
3
- VALUE rExtensionMap_new(const ExtensionMap *value) {
3
+ VALUE rExtensionMap_new(const ExtensionMap *value, VALUE rmodel) {
4
4
  VALUE res = Qnil;
5
5
 
6
6
  for (ExtensionMap::const_iterator iterator = value->begin(); iterator != value->end(); iterator++) {
7
7
  if (NIL_P(res)) res = rb_hash_new();
8
- rb_hash_aset(res, rb_str_new2(iterator->first.c_str()), rValue_new(&iterator->second));
8
+ rb_hash_aset(res, rb_str_new2(iterator->first.c_str()), rValue_new(&iterator->second, rmodel));
9
9
  }
10
10
 
11
11
  return res;
@@ -1,25 +1,85 @@
1
1
  #include "rb_tiny_gltf.h"
2
2
 
3
- VALUE rImage_new(const Image *img) {
4
- VALUE rimg = rb_funcall(rb_cImage, rb_intern("new"), 0);
5
- // *Image_unwrap(rimg) = *img;
3
+ void Image_set_image_data(const Image *img, VALUE rimg) {
4
+ // Keep (yes duplicate but the original will be freed) the buffer data
5
+ // in memory w/o having to wrap with a ruby string, which can be expensive
6
+ // and inefficient.
7
+ Image *dst = Image_unwrap(rimg);
8
+ dst->image = img->image;
9
+ dst->uri = img->uri;
6
10
 
7
- rb_ivar_set(rimg, rb_intern("@name"), rb_str_new2(img->name.c_str()));
8
- rb_ivar_set(rimg, rb_intern("@data"), rb_str_new((char *) img->image.data(), img->image.size()));
9
- rb_ivar_set(rimg, rb_intern("@uri"), Qnil);
10
- rb_ivar_set(rimg, rb_intern("@mime_type"), Qnil);
11
- rb_ivar_set(rimg, rb_intern("@extras"), rValue_new(&img->extras));
12
11
  rb_ivar_set(rimg, rb_intern("@width"), INT2NUM(img->width));
13
12
  rb_ivar_set(rimg, rb_intern("@height"), INT2NUM(img->height));
14
13
  rb_ivar_set(rimg, rb_intern("@components"), INT2NUM(img->component));
15
- rb_ivar_set(rimg, rb_intern("@buffer_view_index"), INT2NUM(img->bufferView));
16
- rb_ivar_set(rimg, rb_intern("@extensions"), rExtensionMap_new(&img->extensions));
14
+ }
17
15
 
18
- if (img->uri.size() > 0)
19
- rb_ivar_set(rimg, rb_intern("@uri"), rb_str_new2(img->uri.c_str()));
16
+ VALUE rImage_new(const Image *img, VALUE rmodel) {
17
+ VALUE rimg = rb_funcall(rb_cImage, rb_intern("new"), 0);
18
+
19
+ Image_set_image_data(img, rimg);
20
+ rb_ivar_set(rimg, rb_intern("@model"), rmodel);
21
+ rb_ivar_set(rimg, rb_intern("@name"), rb_str_new2(img->name.c_str()));
22
+ rb_ivar_set(rimg, rb_intern("@mime_type"), Qnil);
23
+ rb_ivar_set(rimg, rb_intern("@extras"), rValue_new(&img->extras, rmodel));
24
+ rb_ivar_set(rimg, rb_intern("@buffer_view_index"), RINDEX_OR_NIL(img->bufferView));
25
+ rb_ivar_set(rimg, rb_intern("@extensions"), rExtensionMap_new(&img->extensions, rmodel));
20
26
 
21
27
  if (img->mimeType.size() > 0)
22
28
  rb_ivar_set(rimg, rb_intern("@mime_type"), rb_str_new2(img->mimeType.c_str()));
23
29
 
24
30
  return rimg;
25
31
  }
32
+
33
+ VALUE Image_set_uri(VALUE self, VALUE ruri) {
34
+ if (NIL_P(ruri)) return self;
35
+ const char *uri = StringValueCStr(ruri);
36
+ std::string str = uri;
37
+ if (IsDataURI(str)) {
38
+ std::vector<unsigned char> data;
39
+ std::string mime_type;
40
+ if (DecodeDataURI(&data, mime_type, str, strlen(uri), false)) {
41
+ std::string err, warn;
42
+ Image img;
43
+ rb_ivar_set(self, rb_intern("@mime_type"), rb_str_new2(mime_type.c_str()));
44
+ memset(&img, 0, sizeof(img));
45
+ if (tinygltf::LoadImageData(&img, -1, &err, &warn, 0, 0, data.data(), (int) data.size(), NULL)) {
46
+ Image_set_image_data(&img, self);
47
+ } else {
48
+ rb_raise(rb_eStandardError, "Could not parse image data: %s", err.c_str());
49
+ }
50
+ if (warn.size() > 0) {
51
+ rb_warning("%s", warn.c_str());
52
+ }
53
+ } else {
54
+ rb_raise(rb_eStandardError, "Could not decode data URI");
55
+ }
56
+ }
57
+ return self;
58
+ }
59
+
60
+ VALUE Image_to_ptr(VALUE self) {
61
+ // return Fiddle::Pointer.new(addr, size)
62
+ VALUE rFiddlePointer = rb_const_get(rb_const_get(rb_cObject, rb_intern("Fiddle")),
63
+ rb_intern("Pointer"));
64
+ Image *img = Image_unwrap(self);
65
+ return rb_funcall(rFiddlePointer, rb_intern("new"), 2,
66
+ ULL2NUM((unsigned long long) img->image.data()),
67
+ ULL2NUM((unsigned long long) img->image.size()));
68
+ }
69
+
70
+ VALUE Image_size(VALUE self) {
71
+ return ULONG2NUM(Image_unwrap(self)->image.size());
72
+ }
73
+
74
+ VALUE Image_to_s(VALUE self) {
75
+ Image *img = Image_unwrap(self);
76
+ return rb_str_new((char *) img->image.data(), img->image.size());
77
+ }
78
+
79
+ VALUE Image_uri(VALUE self) {
80
+ Image *img = Image_unwrap(self);
81
+ if (img->uri.size() > 0)
82
+ return rb_str_new2(img->uri.c_str());
83
+ else
84
+ return Qnil;
85
+ }
@@ -74,7 +74,72 @@ void Init_tiny_gltf(void) {
74
74
  DEFINE_RB_GLTF_CLASS(Scene);
75
75
  DEFINE_RB_GLTF_CLASS(Light);
76
76
 
77
- rb_define_method(rb_cAccessor, "byte_stride", Accessor_byte_stride, 1);
77
+ /*
78
+ * Document-method: to_ptr
79
+ *
80
+ * Returns a Fiddle::Pointer representing the start of the buffer data in
81
+ * memory. For performance, try to use this rather than #to_s.
82
+ */
83
+ rb_define_method(rb_cBuffer, "to_ptr", Buffer_to_ptr, 0);
84
+
85
+ /*
86
+ * Document-method: size
87
+ *
88
+ * Returns the size of the buffer data in bytes.
89
+ */
90
+ rb_define_method(rb_cBuffer, "size", Buffer_size, 0);
91
+
92
+ /*
93
+ * Document-method: to_s
94
+ *
95
+ * Returns a string containing the raw buffer data. For better performance,
96
+ * prefer #to_ptr where possible.
97
+ */
98
+ rb_define_method(rb_cBuffer, "to_s", Buffer_to_s, 0);
99
+
100
+ /*
101
+ * Document-method: uri
102
+ *
103
+ * Returns the URI from which this data was retrieved, if available. Returns
104
+ * `nil` if a URI was not used.
105
+ */
106
+ rb_define_method(rb_cBuffer, "uri", Buffer_uri, 0);
107
+
108
+ /*
109
+ * Document-method: uri=
110
+ */
111
+ rb_define_method(rb_cImage, "uri=", Image_set_uri, 1);
112
+
113
+ /*
114
+ * Document-method: to_ptr
115
+ *
116
+ * Returns a Fiddle::Pointer representing the start of the image data in
117
+ * memory. For performance, try to use this rather than #to_s.
118
+ */
119
+ rb_define_method(rb_cImage, "to_ptr", Image_to_ptr, 0);
120
+
121
+ /*
122
+ * Document-method: size
123
+ *
124
+ * Returns the size of the image data in bytes.
125
+ */
126
+ rb_define_method(rb_cImage, "size", Image_size, 0);
127
+
128
+ /*
129
+ * Document-method: to_s
130
+ *
131
+ * Returns a string containing the raw image data. For better performance,
132
+ * prefer #to_ptr where possible.
133
+ */
134
+ rb_define_method(rb_cImage, "to_s", Image_to_s, 0);
135
+
136
+ /*
137
+ * Document-method: uri
138
+ *
139
+ * Returns the URI from which this data was retrieved, if available. Returns
140
+ * `nil` if a URI was not used.
141
+ */
142
+ rb_define_method(rb_cImage, "uri", Image_uri, 0);
78
143
 
79
144
  rb_eTinyGLTFError = rb_define_class_under(rb_mTinyGLTF, "Error", rb_eStandardError);
80
145
  rb_define_singleton_method(rb_mTinyGLTF, "load", rb_tgltf_load, -1);