tiny_obj 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/ext/tiny_obj/init_tinyobj.c +11 -3
- data/ext/tiny_obj/rb_tinyobj.h +16 -0
- data/ext/tiny_obj/tinyobj.cpp +376 -27
- data/lib/tiny_obj/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5cb4b288a4c32292401439d4431e618b20db9feb501536521dfc73df992c9297
|
4
|
+
data.tar.gz: 83dc33eeb7db6cd9c80da7cbfe2bac6fcd89a714e802f50e827046a1ec74830b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9433112c3fa3db15ac7d8aa80cfda608d6959f979dc6b957e9e44a7c0c4045794ad1e94eb55b9371070907691df3c42678693d95993243b9d97ade144baf9bd2
|
7
|
+
data.tar.gz: fb56c01fbfb2ffa382b2b2ddba6d36a87e65e468787bc253ddfda15a69be6f8aa787bb14c01416dbcb5f6f342a20494a85c8811c36b1373b7ac3270e82cae498
|
data/Gemfile.lock
CHANGED
data/ext/tiny_obj/init_tinyobj.c
CHANGED
@@ -1,10 +1,18 @@
|
|
1
|
-
#include "
|
1
|
+
#include "rb_tinyobj.h"
|
2
2
|
|
3
3
|
VALUE rb_mTinyOBJ;
|
4
|
-
|
5
|
-
VALUE rb_tinyobj_load(int argc, VALUE *argv, VALUE self);
|
4
|
+
VALUE rb_cOBJ;
|
6
5
|
|
7
6
|
void Init_tiny_obj(void) {
|
8
7
|
rb_mTinyOBJ = rb_define_module("TinyOBJ");
|
8
|
+
rb_cOBJ = rb_define_class_under(rb_mTinyOBJ, "OBJ", rb_cObject);
|
9
|
+
rb_define_method(rb_cOBJ, "to_hash", rb_obj_to_hash, 0);
|
10
|
+
rb_define_method(rb_cOBJ, "num_indices", rb_obj_num_indices, -1);
|
11
|
+
rb_define_method(rb_cOBJ, "num_distinct_vertices", rb_obj_num_distinct_vertices, -1);
|
12
|
+
rb_define_method(rb_cOBJ, "fill_buffers", rb_obj_fill_buffers, -1);
|
13
|
+
rb_define_method(rb_cOBJ, "vertices", rb_obj_vertices, -1);
|
14
|
+
rb_define_method(rb_cOBJ, "normals", rb_obj_normals, -1);
|
15
|
+
rb_define_method(rb_cOBJ, "texcoords", rb_obj_texcoords, -1);
|
16
|
+
rb_define_method(rb_cOBJ, "colors", rb_obj_colors, -1);
|
9
17
|
rb_define_singleton_method(rb_mTinyOBJ, "load", rb_tinyobj_load, -1);
|
10
18
|
}
|
data/ext/tiny_obj/rb_tinyobj.h
CHANGED
@@ -2,6 +2,22 @@
|
|
2
2
|
#define RB_TINYOBJ_H 1
|
3
3
|
|
4
4
|
#include "ruby.h"
|
5
|
+
|
6
|
+
#ifdef __cplusplus
|
5
7
|
#include "tiny_obj_loader.h"
|
8
|
+
extern "C" {
|
9
|
+
#endif
|
10
|
+
VALUE rb_tinyobj_load(int argc, VALUE *argv, VALUE self);
|
11
|
+
VALUE rb_obj_to_hash(VALUE self);
|
12
|
+
VALUE rb_obj_num_distinct_vertices(int argc, VALUE *argv, VALUE self);
|
13
|
+
VALUE rb_obj_num_indices(int argc, VALUE *argv, VALUE self);
|
14
|
+
VALUE rb_obj_fill_buffers(int argc, VALUE *argv, VALUE self);
|
15
|
+
VALUE rb_obj_vertices(int argc, VALUE *argv, VALUE self);
|
16
|
+
VALUE rb_obj_normals(int argc, VALUE *argv, VALUE self);
|
17
|
+
VALUE rb_obj_texcoords(int argc, VALUE *argv, VALUE self);
|
18
|
+
VALUE rb_obj_colors(int argc, VALUE *argv, VALUE self);
|
19
|
+
#ifdef __cplusplus
|
20
|
+
}
|
21
|
+
#endif
|
6
22
|
|
7
23
|
#endif /* RB_TINYOBJ_H */
|
data/ext/tiny_obj/tinyobj.cpp
CHANGED
@@ -2,9 +2,54 @@
|
|
2
2
|
#define TINYOBJLOADER_USE_DOUBLE
|
3
3
|
#include "rb_tinyobj.h"
|
4
4
|
#include <stdlib.h>
|
5
|
+
#include <unordered_map>
|
6
|
+
#include <stdint.h>
|
7
|
+
|
8
|
+
// taken from Fiddle
|
9
|
+
#if SIZEOF_VOIDP == SIZEOF_LONG
|
10
|
+
# define NUM2PTR(x) ((void*)(NUM2ULONG(x)))
|
11
|
+
#else
|
12
|
+
# define NUM2PTR(x) ((void*)(NUM2ULL(x)))
|
13
|
+
#endif
|
5
14
|
|
6
15
|
#define NIL_OR_STR(cstr) (strlen(cstr) > 0 ? Qnil : rb_str_new2(cstr))
|
7
16
|
|
17
|
+
extern VALUE rb_cOBJ;
|
18
|
+
|
19
|
+
typedef struct {
|
20
|
+
bool result;
|
21
|
+
std::string *warnings;
|
22
|
+
std::vector<tinyobj::shape_t> *shapes;
|
23
|
+
std::vector<tinyobj::material_t> *materials;
|
24
|
+
tinyobj::attrib_t *attrib;
|
25
|
+
} obj_t;
|
26
|
+
|
27
|
+
void obj_free(void* data) {
|
28
|
+
obj_t *obj = (obj_t *) data;
|
29
|
+
delete obj->warnings;
|
30
|
+
delete obj->shapes;
|
31
|
+
delete obj->materials;
|
32
|
+
delete obj->attrib;
|
33
|
+
free(data);
|
34
|
+
}
|
35
|
+
|
36
|
+
size_t obj_size(const void* data) {
|
37
|
+
return sizeof(obj_t);
|
38
|
+
}
|
39
|
+
|
40
|
+
static const rb_data_type_t obj_type = {
|
41
|
+
.wrap_struct_name = "OBJ3D",
|
42
|
+
.function = {
|
43
|
+
.dmark = NULL,
|
44
|
+
.dfree = obj_free,
|
45
|
+
.dsize = obj_size,
|
46
|
+
.reserved = { 0, 0 }
|
47
|
+
},
|
48
|
+
.parent = NULL,
|
49
|
+
.data = NULL,
|
50
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY
|
51
|
+
};
|
52
|
+
|
8
53
|
VALUE build_rb_texopt(tinyobj::texture_option_t *opt) {
|
9
54
|
VALUE rt = rb_hash_new();
|
10
55
|
if (opt->colorspace.size() > 0)
|
@@ -45,6 +90,18 @@ VALUE build_rb_texopt(tinyobj::texture_option_t *opt) {
|
|
45
90
|
return rt;
|
46
91
|
}
|
47
92
|
|
93
|
+
inline void hash_combine(std::size_t& seed, int count, const float *vals) {
|
94
|
+
std::hash<float> hasher;
|
95
|
+
for (int i = 0; i < count; i++)
|
96
|
+
seed ^= hasher(vals[i]) + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
97
|
+
}
|
98
|
+
|
99
|
+
inline void hash_combine(std::size_t& seed, int count, const long *vals) {
|
100
|
+
std::hash<long> hasher;
|
101
|
+
for (int i = 0; i < count; i++)
|
102
|
+
seed ^= hasher(vals[i]) + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
103
|
+
}
|
104
|
+
|
48
105
|
extern "C" {
|
49
106
|
VALUE rb_tinyobj_load(int argc, VALUE *argv, VALUE self) {
|
50
107
|
VALUE fn, dir;
|
@@ -53,23 +110,327 @@ extern "C" {
|
|
53
110
|
dir = rb_funcall(rb_cFile, rb_intern("dirname"), 1, fn);
|
54
111
|
}
|
55
112
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
std::vector<tinyobj::shape_t>
|
60
|
-
std::vector<tinyobj::material_t>
|
61
|
-
|
62
|
-
|
113
|
+
obj_t *obj = (obj_t *) malloc(sizeof(obj_t));
|
114
|
+
memset(obj, 0, sizeof(obj_t));
|
115
|
+
obj->warnings = new std::string();
|
116
|
+
obj->shapes = new std::vector<tinyobj::shape_t>();
|
117
|
+
obj->materials = new std::vector<tinyobj::material_t>();
|
118
|
+
obj->attrib = new tinyobj::attrib_t();
|
119
|
+
std::string err;
|
63
120
|
|
64
|
-
|
121
|
+
obj->result = tinyobj::LoadObj(obj->attrib, obj->shapes, obj->materials, obj->warnings, &err, StringValuePtr(fn), StringValuePtr(dir));
|
122
|
+
if (!err.empty()) {
|
123
|
+
obj_free(obj);
|
65
124
|
rb_raise(rb_eRuntimeError, "error loading OBJ: %s", err.c_str());
|
125
|
+
}
|
126
|
+
|
127
|
+
return TypedData_Wrap_Struct(rb_cOBJ, &obj_type, obj);
|
128
|
+
}
|
129
|
+
|
130
|
+
static inline void *VAL2PTR(VALUE val) {
|
131
|
+
if (val == Qundef || NIL_P(val)) return NULL;
|
132
|
+
if (rb_respond_to(val, rb_intern("to_ptr"))) {
|
133
|
+
val = rb_funcall(val, rb_intern("to_ptr"), 0);
|
134
|
+
}
|
135
|
+
if (NIL_P(val)) return NULL;
|
136
|
+
return NUM2PTR(rb_funcall(val, rb_intern("to_i"), 0));
|
137
|
+
}
|
138
|
+
|
139
|
+
/* call-seq: fill_buffers(positions: nil, normals: nil, texcoords: nil, colors: nil, indices: nil,
|
140
|
+
* vertex_stride:, index_stride:, index_type:)
|
141
|
+
*
|
142
|
+
* Fills one or more buffers with data. This is much faster than doing it in
|
143
|
+
* Ruby because it avoids populating Ruby arrays with Ruby numeric types.
|
144
|
+
* Instead everything happens at a low level, giving essentially native
|
145
|
+
* performance for filling vertices, normals, texcoords, etc., which would
|
146
|
+
* otherwise be an expensive operation in Ruby.
|
147
|
+
*
|
148
|
+
* * `positions`, `normals`, `texcoords`, `colors` and `indices` are all
|
149
|
+
* pointers to the memory location into which to store the data. Any of
|
150
|
+
* these which is `nil` is simply omitted (data is not filled). If it
|
151
|
+
* `responds_to?(:to_ptr)` then that method is called first, and the data
|
152
|
+
* will be placed into whatever memory the result of the method refers to.
|
153
|
+
* If it does not, then the object itself represents the buffer. In both
|
154
|
+
* cases, the buffer must return a memory location from #to_i. Basically,
|
155
|
+
* the data buffer is meant to be an instance of Fiddle::Pointer, but can
|
156
|
+
* be any object which satisfies these constraints.
|
157
|
+
*
|
158
|
+
* Note that each object can point to different offsets into the same
|
159
|
+
* buffer. You don't need to use a separate allocation of memory for each
|
160
|
+
* argument.
|
161
|
+
*
|
162
|
+
* **IMPORTANT:** If the buffer's `to_i` method does not return an
|
163
|
+
* appropriate memory offset, the program will have undefined behavior
|
164
|
+
* and will typically result in a crash.
|
165
|
+
*
|
166
|
+
* * `vertex_stride` represents how many bytes to 'skip over' from one
|
167
|
+
* vertex position, color, normal or texcoord to the next. This can be used
|
168
|
+
* to populate a single buffer with interleaved vertex data.
|
169
|
+
*
|
170
|
+
* * `index_stride` is the same as `vertex_stride`, but for vertex indices.
|
171
|
+
* It is separated from `vertex_stride` because index data is often not
|
172
|
+
* interleaved with vertex data, and often lives in its own separate
|
173
|
+
* buffer. Nothing prevents you from interleaving it with the vertex data,
|
174
|
+
* of course, by specifying the same value as you did for `vertex_stride`.
|
175
|
+
*
|
176
|
+
* * `index_type` represents the primitive data type of a single index. It
|
177
|
+
* can be one of:
|
178
|
+
*
|
179
|
+
* * `:uint8` - each index is an 8-bit unsigned integer
|
180
|
+
* * `:uint16` - each index is a 16-bit unsigned integer
|
181
|
+
* * `:uint32` - each index is a 32-bit unsigned integer
|
182
|
+
* * `:uint64` - each index is a 64-bit unsigned integer
|
183
|
+
*
|
184
|
+
* Example:
|
185
|
+
*
|
186
|
+
* # In this example, we'll fill 2 buffers, one with vertex data and the
|
187
|
+
* # other with index data. In the vertex data we will gather positions,
|
188
|
+
* # normals and texture coordinates but we will omit vertex colors.
|
189
|
+
*
|
190
|
+
* vertex_stride = Fiddle::SIZEOF_FLOAT * (
|
191
|
+
* 3 + # 3 floats for each position (x, y, z)
|
192
|
+
* 3 + # 3 floats for each normal (x, y, z)
|
193
|
+
* 2 # 2 floats for each texture coord (u, v)
|
194
|
+
* )
|
195
|
+
* index_stride = 2 # each index will be one uint16, or two 8-bit bytes
|
196
|
+
* vertex_buffer = Fiddle::Pointer.malloc(obj.num_distinct_vertices * vertex_stride)
|
197
|
+
* index_buffer = Fiddle::Pointer.malloc(obj.num_indices * index_stride)
|
198
|
+
* obj.fill_buffers(positions: vertex_buffer,
|
199
|
+
* normals: vertex_buffer + Fiddle::SIZEOF_FLOAT * 3,
|
200
|
+
* texcoords: vertex_buffer + Fiddle::SIZEOF_FLOAT * 6,
|
201
|
+
* indices: index_buffer,
|
202
|
+
* vertex_stride: vertex_stride,
|
203
|
+
* index_stride: index_stride,
|
204
|
+
* index_type: :uint16)
|
205
|
+
*
|
206
|
+
* # vertex_buffer now contains interleaved vertex data, and
|
207
|
+
* # index_buffer now contains index data. Print the first complete
|
208
|
+
* # vertex:
|
209
|
+
* Vertex = Fiddle::Importer.struct(['float pos[3]', 'float normal[3]', 'float texcoord[2]'])
|
210
|
+
* v = Vertex.new(vertex_buffer)
|
211
|
+
* p position: v.pos, normal: v.normal, texcoord: v.texcoord
|
212
|
+
*/
|
213
|
+
VALUE rb_obj_fill_buffers(int argc, VALUE *argv, VALUE self) {
|
214
|
+
#define UINT8 0
|
215
|
+
#define UINT16 1
|
216
|
+
#define UINT32 2
|
217
|
+
#define UINT64 3
|
218
|
+
static ID kwargs_ids[9];
|
219
|
+
if (!kwargs_ids[0]) {
|
220
|
+
kwargs_ids[0] = rb_intern_const("vertex_stride");
|
221
|
+
kwargs_ids[1] = rb_intern_const("index_stride");
|
222
|
+
kwargs_ids[2] = rb_intern_const("index_type");
|
223
|
+
kwargs_ids[3] = rb_intern_const("positions");
|
224
|
+
kwargs_ids[4] = rb_intern_const("normals");
|
225
|
+
kwargs_ids[5] = rb_intern_const("texcoords");
|
226
|
+
kwargs_ids[6] = rb_intern_const("colors");
|
227
|
+
kwargs_ids[7] = rb_intern_const("indices");
|
228
|
+
kwargs_ids[8] = rb_intern_const("flip_v");
|
229
|
+
};
|
230
|
+
VALUE kwargs[9] = {Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil};
|
231
|
+
VALUE opts = Qnil;
|
232
|
+
rb_scan_args(argc, argv, "00:", &opts);
|
233
|
+
rb_get_kwargs(opts, kwargs_ids, 3, 6, kwargs);
|
234
|
+
|
235
|
+
bool flip_v = kwargs[8] == Qundef || kwargs[8] == Qfalse || kwargs[8] == Qnil ? false : true;
|
236
|
+
char *positions = (char *) VAL2PTR(kwargs[3]);
|
237
|
+
char *normals = (char *) VAL2PTR(kwargs[4]);
|
238
|
+
char *texcoords = (char *) VAL2PTR(kwargs[5]);
|
239
|
+
char *colors = (char *) VAL2PTR(kwargs[6]);
|
240
|
+
char *indices = (char *) VAL2PTR(kwargs[7]);
|
241
|
+
size_t vertex_stride = NUM2SIZET(kwargs[0]);
|
242
|
+
size_t index_stride = NUM2SIZET(kwargs[1]);
|
243
|
+
int index_type = -1;
|
244
|
+
if (SYM2ID(kwargs[2]) == rb_intern("uint8" )) index_type = UINT8;
|
245
|
+
else if (SYM2ID(kwargs[2]) == rb_intern("uint16")) index_type = UINT16;
|
246
|
+
else if (SYM2ID(kwargs[2]) == rb_intern("uint32")) index_type = UINT32;
|
247
|
+
else if (SYM2ID(kwargs[2]) == rb_intern("uint64")) index_type = UINT64;
|
248
|
+
else rb_raise(rb_eArgError, "unknown index_type");
|
249
|
+
|
250
|
+
obj_t *obj;
|
251
|
+
TypedData_Get_Struct(self, obj_t, &obj_type, obj);
|
252
|
+
std::vector<tinyobj::shape_t> &shapes = *(obj->shapes);
|
253
|
+
tinyobj::attrib_t &attrib = *(obj->attrib);
|
254
|
+
|
255
|
+
size_t vertex_offset = 0;
|
256
|
+
size_t index_offset = 0;
|
257
|
+
std::unordered_map<size_t, int64_t> vertex_map;
|
258
|
+
for (size_t s = 0; s < shapes.size(); s++) {
|
259
|
+
for (size_t i = 0; i < shapes[s].mesh.indices.size(); i++) {
|
260
|
+
size_t hash = 0;
|
261
|
+
long vertex[] = {
|
262
|
+
3 * shapes[s].mesh.indices[i].vertex_index + 0,
|
263
|
+
3 * shapes[s].mesh.indices[i].vertex_index + 1,
|
264
|
+
3 * shapes[s].mesh.indices[i].vertex_index + 2,
|
265
|
+
2 * shapes[s].mesh.indices[i].texcoord_index + 0,
|
266
|
+
2 * shapes[s].mesh.indices[i].texcoord_index + 1,
|
267
|
+
3 * shapes[s].mesh.indices[i].normal_index + 0,
|
268
|
+
3 * shapes[s].mesh.indices[i].normal_index + 1,
|
269
|
+
3 * shapes[s].mesh.indices[i].normal_index + 2,
|
270
|
+
};
|
271
|
+
hash_combine(hash, sizeof(vertex) / sizeof(long), vertex);
|
272
|
+
uint64_t index;
|
273
|
+
if (vertex_map.count(hash) == 0) {
|
274
|
+
if (positions && vertex[0] >= 0) {
|
275
|
+
*((float *)(positions + vertex_offset )) = attrib.vertices[vertex[0]];
|
276
|
+
*((float *)(positions + vertex_offset+1*sizeof(float))) = attrib.vertices[vertex[1]];
|
277
|
+
*((float *)(positions + vertex_offset+2*sizeof(float))) = attrib.vertices[vertex[2]];
|
278
|
+
}
|
279
|
+
if (colors && vertex[0] >= 0) {
|
280
|
+
*((float *)(colors + vertex_offset )) = attrib.colors[vertex[0]];
|
281
|
+
*((float *)(colors + vertex_offset+1*sizeof(float))) = attrib.colors[vertex[1]];
|
282
|
+
*((float *)(colors + vertex_offset+2*sizeof(float))) = attrib.colors[vertex[2]];
|
283
|
+
}
|
284
|
+
if (texcoords && vertex[3] >= 0) {
|
285
|
+
*((float *)(texcoords + vertex_offset )) = attrib.texcoords[vertex[3]];
|
286
|
+
if (flip_v)
|
287
|
+
*((float *)(texcoords + vertex_offset+1*sizeof(float))) = 1.0f - attrib.texcoords[vertex[4]];
|
288
|
+
else
|
289
|
+
*((float *)(texcoords + vertex_offset+1*sizeof(float))) = attrib.texcoords[vertex[4]];
|
290
|
+
}
|
291
|
+
if (normals && vertex[5] >= 0) {
|
292
|
+
*((float *)(normals + vertex_offset )) = attrib.normals[vertex[5]];
|
293
|
+
*((float *)(normals + vertex_offset+1*sizeof(float))) = attrib.normals[vertex[6]];
|
294
|
+
*((float *)(normals + vertex_offset+2*sizeof(float))) = attrib.normals[vertex[7]];
|
295
|
+
}
|
296
|
+
index = vertex_map.size();
|
297
|
+
vertex_map[hash] = index;
|
298
|
+
vertex_offset += vertex_stride;
|
299
|
+
} else {
|
300
|
+
index = vertex_map[hash];
|
301
|
+
}
|
302
|
+
// printf("%zu\n", index);
|
303
|
+
if (indices) {
|
304
|
+
switch(index_type) {
|
305
|
+
case UINT8: *((uint8_t *)(indices + index_offset)) = (uint8_t) index; break;
|
306
|
+
case UINT16: *((uint16_t *)(indices + index_offset)) = (uint16_t) index; break;
|
307
|
+
case UINT32: *((uint32_t *)(indices + index_offset)) = (uint32_t) index; break;
|
308
|
+
case UINT64: *((uint64_t *)(indices + index_offset)) = (uint64_t) index; break;
|
309
|
+
default: rb_raise(rb_eRuntimeError, "BUG: unexpected index type: %d", index_type);
|
310
|
+
}
|
311
|
+
index_offset += index_stride;
|
312
|
+
}
|
313
|
+
}
|
314
|
+
}
|
315
|
+
|
316
|
+
return self;
|
317
|
+
}
|
66
318
|
|
67
|
-
|
319
|
+
VALUE rb_obj_num_distinct_vertices(int argc, VALUE *argv, VALUE self) {
|
320
|
+
// cache = {}
|
321
|
+
// h[:shapes].each do |shape|
|
322
|
+
// shape[:mesh][:indices].each_with_index do |index, i|
|
323
|
+
// hash = [
|
324
|
+
// index[ :vertex_index] && 3.times.map { |i| 3 * index[:vertex_index] + i },
|
325
|
+
// index[ :vertex_index] && 3.times.map { |i| 3 * index[:vertex_index] + i },
|
326
|
+
// index[ :normal_index] && 3.times.map { |i| 3 * index[:normal_index] + i },
|
327
|
+
// index[:texcoord_index] && 2.times.map { |i| 2 * index[:texcoord_index] + i }
|
328
|
+
// ]
|
329
|
+
// cache[hash] = cache.size unless cache.include?(hash)
|
330
|
+
// end
|
331
|
+
// end
|
68
332
|
|
69
|
-
|
70
|
-
|
333
|
+
obj_t *obj;
|
334
|
+
TypedData_Get_Struct(self, obj_t, &obj_type, obj);
|
335
|
+
std::vector<tinyobj::shape_t> &shapes = *(obj->shapes);
|
336
|
+
|
337
|
+
size_t count = 0;
|
338
|
+
std::unordered_map<size_t, size_t> vertex_map;
|
339
|
+
for (size_t s = 0; s < shapes.size(); s++) {
|
340
|
+
for (size_t i = 0; i < shapes[s].mesh.indices.size(); i++) {
|
341
|
+
tinyobj::index_t &index = shapes[s].mesh.indices[i];
|
342
|
+
size_t hash = 0;
|
343
|
+
long vertex[] = {
|
344
|
+
3 * index.vertex_index + 0,
|
345
|
+
3 * index.vertex_index + 1,
|
346
|
+
3 * index.vertex_index + 2,
|
347
|
+
2 * index.texcoord_index + 0,
|
348
|
+
2 * index.texcoord_index + 1,
|
349
|
+
3 * index.normal_index + 0,
|
350
|
+
3 * index.normal_index + 1,
|
351
|
+
3 * index.normal_index + 2
|
352
|
+
};
|
353
|
+
hash_combine(hash, sizeof(vertex) / sizeof(long), vertex);
|
354
|
+
if (vertex_map.count(hash) == 0) {
|
355
|
+
vertex_map[hash] = hash;
|
356
|
+
count++;
|
357
|
+
}
|
358
|
+
}
|
359
|
+
}
|
360
|
+
|
361
|
+
return SIZET2NUM(count);
|
362
|
+
}
|
363
|
+
|
364
|
+
VALUE rb_obj_num_indices(int argc, VALUE *argv, VALUE self) {
|
365
|
+
// h[:shapes].reduce(0) { |a, shape| a + shape[:mesh][:indices].size }
|
366
|
+
|
367
|
+
obj_t *obj;
|
368
|
+
TypedData_Get_Struct(self, obj_t, &obj_type, obj);
|
369
|
+
std::vector<tinyobj::shape_t> &shapes = *(obj->shapes);
|
370
|
+
|
371
|
+
long count = 0;
|
372
|
+
for (size_t s = 0; s < shapes.size(); s++) {
|
373
|
+
count += shapes[s].mesh.indices.size();
|
374
|
+
}
|
375
|
+
|
376
|
+
return LONG2NUM(count);
|
377
|
+
}
|
378
|
+
|
379
|
+
VALUE rb_obj_vertices(int argc, VALUE *argv, VALUE self) {
|
380
|
+
obj_t *obj;
|
381
|
+
TypedData_Get_Struct(self, obj_t, &obj_type, obj);
|
382
|
+
tinyobj::attrib_t &attrib = *(obj->attrib);
|
383
|
+
VALUE rb_vertices = rb_ary_new2(attrib.vertices.size());
|
384
|
+
for (size_t i = 0; i < attrib.vertices.size(); i++)
|
385
|
+
rb_ary_push(rb_vertices, DBL2NUM(attrib.vertices[i]));
|
386
|
+
return rb_vertices;
|
387
|
+
}
|
388
|
+
|
389
|
+
VALUE rb_obj_normals(int argc, VALUE *argv, VALUE self) {
|
390
|
+
obj_t *obj;
|
391
|
+
TypedData_Get_Struct(self, obj_t, &obj_type, obj);
|
392
|
+
tinyobj::attrib_t &attrib = *(obj->attrib);
|
393
|
+
VALUE rb_normals = rb_ary_new2(attrib.normals.size());
|
394
|
+
for (size_t i = 0; i < attrib.normals.size(); i++)
|
395
|
+
rb_ary_push(rb_normals, DBL2NUM(attrib.normals[i]));
|
396
|
+
return rb_normals;
|
397
|
+
}
|
398
|
+
|
399
|
+
VALUE rb_obj_texcoords(int argc, VALUE *argv, VALUE self) {
|
400
|
+
obj_t *obj;
|
401
|
+
TypedData_Get_Struct(self, obj_t, &obj_type, obj);
|
402
|
+
tinyobj::attrib_t &attrib = *(obj->attrib);
|
403
|
+
VALUE rb_texcoords = rb_ary_new2(attrib.texcoords.size());
|
404
|
+
for (size_t i = 0; i < attrib.texcoords.size(); i++)
|
405
|
+
rb_ary_push(rb_texcoords, DBL2NUM(attrib.texcoords[i]));
|
406
|
+
return rb_texcoords;
|
407
|
+
}
|
408
|
+
|
409
|
+
VALUE rb_obj_colors(int argc, VALUE *argv, VALUE self) {
|
410
|
+
obj_t *obj;
|
411
|
+
TypedData_Get_Struct(self, obj_t, &obj_type, obj);
|
412
|
+
tinyobj::attrib_t &attrib = *(obj->attrib);
|
413
|
+
VALUE rb_colors = rb_ary_new2(attrib.colors.size());
|
414
|
+
for (size_t i = 0; i < attrib.colors.size(); i++)
|
415
|
+
rb_ary_push(rb_colors, DBL2NUM(attrib.colors[i]));
|
416
|
+
return rb_colors;
|
417
|
+
}
|
418
|
+
|
419
|
+
VALUE rb_obj_to_hash(VALUE self) {
|
420
|
+
obj_t *obj;
|
421
|
+
TypedData_Get_Struct(self, obj_t, &obj_type, obj);
|
422
|
+
std::string &warnings = *(obj->warnings);
|
423
|
+
std::vector<tinyobj::shape_t> &shapes = *(obj->shapes);
|
424
|
+
std::vector<tinyobj::material_t> &materials = *(obj->materials);
|
425
|
+
|
426
|
+
VALUE ret = rb_hash_new();
|
427
|
+
rb_hash_aset(ret, ID2SYM(rb_intern("success")), obj->result ? Qtrue : Qfalse);
|
428
|
+
|
429
|
+
if (warnings.size() > 0)
|
430
|
+
rb_hash_aset(ret, ID2SYM(rb_intern("warnings")), rb_str_new2(warnings.c_str()));
|
71
431
|
|
72
432
|
VALUE rb_materials = rb_ary_new2(materials.size());
|
433
|
+
rb_hash_aset(ret, ID2SYM(rb_intern("materials")), rb_materials);
|
73
434
|
for (size_t m = 0; m < materials.size(); m++) {
|
74
435
|
VALUE rb_material = rb_hash_new();
|
75
436
|
rb_ary_push(rb_materials, rb_material);
|
@@ -138,22 +499,10 @@ extern "C" {
|
|
138
499
|
rb_hash_aset(rb_material, ID2SYM(rb_intern("unknown_parameters")), rb_unknown_parameter);
|
139
500
|
}
|
140
501
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
rb_hash_aset(ret, ID2SYM(rb_intern("vertices")), rb_vertices);
|
146
|
-
rb_hash_aset(ret, ID2SYM(rb_intern("normals")), rb_normals);
|
147
|
-
rb_hash_aset(ret, ID2SYM(rb_intern("texcoords")), rb_texcoords);
|
148
|
-
rb_hash_aset(ret, ID2SYM(rb_intern("colors")), rb_colors);
|
149
|
-
for (size_t i = 0; i < attrib.vertices.size(); i++)
|
150
|
-
rb_ary_push(rb_vertices, DBL2NUM(attrib.vertices[i]));
|
151
|
-
for (size_t i = 0; i < attrib.normals.size(); i++)
|
152
|
-
rb_ary_push(rb_normals, DBL2NUM(attrib.normals[i]));
|
153
|
-
for (size_t i = 0; i < attrib.texcoords.size(); i++)
|
154
|
-
rb_ary_push(rb_texcoords, DBL2NUM(attrib.texcoords[i]));
|
155
|
-
for (size_t i = 0; i < attrib.colors.size(); i++)
|
156
|
-
rb_ary_push(rb_colors, DBL2NUM(attrib.colors[i]));
|
502
|
+
rb_hash_aset(ret, ID2SYM(rb_intern("vertices")), rb_funcall(self, rb_intern("vertices"), 0));
|
503
|
+
rb_hash_aset(ret, ID2SYM(rb_intern("normals")), rb_funcall(self, rb_intern("normals"), 0));
|
504
|
+
rb_hash_aset(ret, ID2SYM(rb_intern("texcoords")), rb_funcall(self, rb_intern("texcoords"), 0));
|
505
|
+
rb_hash_aset(ret, ID2SYM(rb_intern("colors")), rb_funcall(self, rb_intern("colors"), 0));
|
157
506
|
|
158
507
|
VALUE rb_shapes = rb_ary_new2(shapes.size());
|
159
508
|
rb_hash_aset(ret, ID2SYM(rb_intern("shapes")), rb_shapes);
|
data/lib/tiny_obj/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tiny_obj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Colin MacKenzie IV
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|