assimp-ffi 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +25 -0
- data/README.md +2 -0
- data/assimp.gemspec +14 -0
- data/lib/assimp/anim.rb +131 -0
- data/lib/assimp/base.rb +197 -0
- data/lib/assimp/camera.rb +25 -0
- data/lib/assimp/color4.rb +24 -0
- data/lib/assimp/config.rb +34 -0
- data/lib/assimp/defs.rb +25 -0
- data/lib/assimp/export.rb +58 -0
- data/lib/assimp/fileio.rb +48 -0
- data/lib/assimp/import.rb +226 -0
- data/lib/assimp/importerdesc.rb +42 -0
- data/lib/assimp/light.rb +49 -0
- data/lib/assimp/material.rb +407 -0
- data/lib/assimp/matrix3x3.rb +100 -0
- data/lib/assimp/matrix4x4.rb +178 -0
- data/lib/assimp/mesh.rb +250 -0
- data/lib/assimp/metadata.rb +53 -0
- data/lib/assimp/postprocess.rb +81 -0
- data/lib/assimp/quaternion.rb +47 -0
- data/lib/assimp/scene.rb +168 -0
- data/lib/assimp/texture.rb +31 -0
- data/lib/assimp/types.rb +93 -0
- data/lib/assimp/vector2.rb +14 -0
- data/lib/assimp/vector3.rb +99 -0
- data/lib/assimp/version.rb +52 -0
- data/lib/assimp-ffi.rb +25 -0
- metadata +92 -0
@@ -0,0 +1,407 @@
|
|
1
|
+
module Assimp
|
2
|
+
|
3
|
+
TextureOp = enum(:texture_op, [
|
4
|
+
:Multiply,
|
5
|
+
:Add,
|
6
|
+
:Subtract,
|
7
|
+
:Divide,
|
8
|
+
:SmoothAdd,
|
9
|
+
:SignedAdd
|
10
|
+
])
|
11
|
+
|
12
|
+
TextureMapMode = enum(:texture_map_mode, [
|
13
|
+
:Wrap,
|
14
|
+
:Clamp,
|
15
|
+
:Mirror,
|
16
|
+
:Decal
|
17
|
+
])
|
18
|
+
|
19
|
+
TextureMapping = enum(:texture_mapping, [
|
20
|
+
:UV,
|
21
|
+
:SPHERE,
|
22
|
+
:CYLINDER,
|
23
|
+
:BOX,
|
24
|
+
:PLANE,
|
25
|
+
:OTHER
|
26
|
+
])
|
27
|
+
|
28
|
+
TextureType = enum(:texture_type, [
|
29
|
+
:NONE,
|
30
|
+
:DIFFUSE,
|
31
|
+
:SPECULAR,
|
32
|
+
:AMBIENT,
|
33
|
+
:EMISSIVE,
|
34
|
+
:HEIGHT,
|
35
|
+
:NORMALS,
|
36
|
+
:SHININESS,
|
37
|
+
:OPACITY,
|
38
|
+
:DISPLACEMENT,
|
39
|
+
:LIGHTMAP,
|
40
|
+
:REFLECTION,
|
41
|
+
:UNKNOWN
|
42
|
+
])
|
43
|
+
|
44
|
+
ShadingMode = enum(:shading_mode, [
|
45
|
+
:Flat, 1,
|
46
|
+
:Gouraud,
|
47
|
+
:Phong,
|
48
|
+
:Blinn,
|
49
|
+
:Toon,
|
50
|
+
:OrenNayar,
|
51
|
+
:Minnaert,
|
52
|
+
:CookTorrance,
|
53
|
+
:NoShading,
|
54
|
+
:Fresnel
|
55
|
+
])
|
56
|
+
|
57
|
+
TextureFlags = bitmask(:texture_flags, [
|
58
|
+
:Invert,
|
59
|
+
:UseAlpha,
|
60
|
+
:IgnoreAlpha
|
61
|
+
])
|
62
|
+
|
63
|
+
BlendMode = enum(:blend_mode, [
|
64
|
+
:Default,
|
65
|
+
:Additive
|
66
|
+
])
|
67
|
+
|
68
|
+
class UVTransform < FFI::Struct
|
69
|
+
extend StructAccessors
|
70
|
+
pack 1
|
71
|
+
layout :translation, Vector2D,
|
72
|
+
:scaling, Vector2D,
|
73
|
+
:rotation, :ai_real
|
74
|
+
struct_attr_accessor :translation,
|
75
|
+
:scaling,
|
76
|
+
:rotation
|
77
|
+
end
|
78
|
+
|
79
|
+
PropertyTypeInfo = enum(:property_type_info, [
|
80
|
+
:Float, 1,
|
81
|
+
:Double,
|
82
|
+
:String,
|
83
|
+
:Integer,
|
84
|
+
:Buffer
|
85
|
+
])
|
86
|
+
|
87
|
+
MATKEY_NAME = "?mat.name"
|
88
|
+
MATKEY_TWOSIDED = "$mat.twosided"
|
89
|
+
MATKEY_SHADING_MODEL = "$mat.shadingm"
|
90
|
+
MATKEY_ENABLE_WIREFRAME = "$mat.wireframe"
|
91
|
+
MATKEY_BLEND_FUNC = "$mat.blend"
|
92
|
+
MATKEY_OPACITY = "$mat.opacity"
|
93
|
+
MATKEY_BUMPSCALING = "$mat.bumpscaling"
|
94
|
+
MATKEY_SHININESS = "$mat.shininess"
|
95
|
+
MATKEY_REFLECTIVITY = "$mat.reflectivity"
|
96
|
+
MATKEY_SHININESS_STRENGTH = "$mat.shinpercent"
|
97
|
+
MATKEY_REFRACTI = "$mat.refracti"
|
98
|
+
MATKEY_COLOR_DIFFUSE = "$clr.diffuse"
|
99
|
+
MATKEY_COLOR_AMBIENT = "$clr.ambient"
|
100
|
+
MATKEY_COLOR_SPECULAR = "$clr.specular"
|
101
|
+
MATKEY_COLOR_EMISSIVE = "$clr.emissive"
|
102
|
+
MATKEY_COLOR_TRANSPARENT = "$clr.transparent"
|
103
|
+
MATKEY_COLOR_REFLECTIVE = "$clr.reflective"
|
104
|
+
MATKEY_GLOBAL_BACKGROUND_IMAGE = "?bg.global"
|
105
|
+
MATKEY_TEXTURE = "$tex.file"
|
106
|
+
MATKEY_UVWSRC = "$tex.uvwsrc"
|
107
|
+
MATKEY_TEXOP = "$tex.op"
|
108
|
+
MATKEY_MAPPING = "$tex.mapping"
|
109
|
+
MATKEY_TEXBLEND = "$tex.blend"
|
110
|
+
MATKEY_MAPPINGMODE_U = "$tex.mapmodeu"
|
111
|
+
MATKEY_MAPPINGMODE_V = "$tex.mapmodev"
|
112
|
+
MATKEY_MAPPINGMODE_W = "$tex.mapmodew"
|
113
|
+
MATKEY_TEXMAP_AXIS = "$tex.mapaxis"
|
114
|
+
MATKEY_UVTRANSFORM = "$tex.uvtrafo"
|
115
|
+
MATKEY_TEXFLAGS = "$tex.flags"
|
116
|
+
|
117
|
+
class MaterialProperty < FFI::Struct
|
118
|
+
TEX_PROPERTIES = [ MATKEY_TEXTURE,
|
119
|
+
MATKEY_UVWSRC,
|
120
|
+
MATKEY_TEXOP,
|
121
|
+
MATKEY_MAPPING,
|
122
|
+
MATKEY_TEXBLEND,
|
123
|
+
MATKEY_MAPPINGMODE_U,
|
124
|
+
MATKEY_MAPPINGMODE_V,
|
125
|
+
MATKEY_MAPPINGMODE_W,
|
126
|
+
MATKEY_TEXMAP_AXIS,
|
127
|
+
MATKEY_UVTRANSFORM,
|
128
|
+
MATKEY_TEXFLAGS ]
|
129
|
+
COLOR_PROPERTIES = [ MATKEY_COLOR_DIFFUSE,
|
130
|
+
MATKEY_COLOR_AMBIENT,
|
131
|
+
MATKEY_COLOR_SPECULAR,
|
132
|
+
MATKEY_COLOR_EMISSIVE,
|
133
|
+
MATKEY_COLOR_TRANSPARENT,
|
134
|
+
MATKEY_COLOR_REFLECTIVE ]
|
135
|
+
STRING_PROPERTIES = [ MATKEY_NAME,
|
136
|
+
MATKEY_GLOBAL_BACKGROUND_IMAGE,
|
137
|
+
MATKEY_TEXTURE ]
|
138
|
+
BOOL_PROPERTIES = [ MATKEY_TWOSIDED, MATKEY_ENABLE_WIREFRAME ]
|
139
|
+
INTEGER_PROPERTIES = BOOL_PROPERTIES +
|
140
|
+
[ MATKEY_UVWSRC,
|
141
|
+
MATKEY_SHADING_MODEL,
|
142
|
+
MATKEY_MAPPINGMODE_U,
|
143
|
+
MATKEY_MAPPINGMODE_V,
|
144
|
+
MATKEY_MAPPINGMODE_W,
|
145
|
+
MATKEY_BLEND_FUNC,
|
146
|
+
MATKEY_TEXFLAGS,
|
147
|
+
MATKEY_MAPPING,
|
148
|
+
MATKEY_TEXOP ]
|
149
|
+
FLOAT_PROPERTIES = COLOR_PROPERTIES +
|
150
|
+
[ MATKEY_UVTRANSFORM,
|
151
|
+
MATKEY_TEXBLEND,
|
152
|
+
MATKEY_OPACITY,
|
153
|
+
MATKEY_SHININESS,
|
154
|
+
MATKEY_REFLECTIVITY,
|
155
|
+
MATKEY_REFRACTI,
|
156
|
+
MATKEY_SHININESS_STRENGTH,
|
157
|
+
MATKEY_BUMPSCALING,
|
158
|
+
MATKEY_TEXMAP_AXIS ]
|
159
|
+
|
160
|
+
extend StructAccessors
|
161
|
+
layout :key, String,
|
162
|
+
:semantic, TextureType,
|
163
|
+
:index, :uint,
|
164
|
+
:data_length, :uint,
|
165
|
+
:type, PropertyTypeInfo,
|
166
|
+
:data, :pointer #byte[data_length]
|
167
|
+
struct_attr_accessor :key,
|
168
|
+
:semantic,
|
169
|
+
:index,
|
170
|
+
:data_length,
|
171
|
+
:type
|
172
|
+
|
173
|
+
@__has_ref = true
|
174
|
+
|
175
|
+
def set_property(key, val, semantic: 0, index: 0, type: nil)
|
176
|
+
if type
|
177
|
+
self.type = type
|
178
|
+
else
|
179
|
+
case key
|
180
|
+
when *STRING_PROPERTIES
|
181
|
+
self.type = :String
|
182
|
+
when *INTEGER_PROPERTIES
|
183
|
+
self.type = :Integer
|
184
|
+
when *FLOAT_PROPERTIES
|
185
|
+
if ENV["ASSIMP_DOUBLE_PRECISION"]
|
186
|
+
self.type = :Double
|
187
|
+
else
|
188
|
+
self.type = :Float
|
189
|
+
end
|
190
|
+
else
|
191
|
+
raise ArgumentError::new("Could not determine property type!")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
if semantic == 0 && TEX_PROPERTIES.include?(key)
|
195
|
+
raise ArgumentError::new("Missing semantic for texture property!")
|
196
|
+
elsif semantic != 0 && ! TEX_PROPERTIES.include?(key)
|
197
|
+
raise ArgumentError::new("Semantic given for non texture property!")
|
198
|
+
else
|
199
|
+
self.semantic = semantic
|
200
|
+
end
|
201
|
+
if index != 0 && ! TEX_PROPERTIES.include?(key)
|
202
|
+
raise ArgumentError::new("Index given for non texture property!")
|
203
|
+
else
|
204
|
+
self.index = index
|
205
|
+
end
|
206
|
+
self.key = key
|
207
|
+
self.data = val
|
208
|
+
self
|
209
|
+
end
|
210
|
+
|
211
|
+
def data=(val)
|
212
|
+
ptr = nil
|
213
|
+
case type
|
214
|
+
when :String
|
215
|
+
length = val.bytesize
|
216
|
+
ptr = FFI::MemoryPointer::new(length+4+1)
|
217
|
+
ptr.write_uint(length)
|
218
|
+
ptr.put_string(4, val)
|
219
|
+
when :Integer
|
220
|
+
if val.kind_of? Array
|
221
|
+
ptr = FFI::MemoryPointer::new(:int, val.length)
|
222
|
+
ptr.write_array_of_int(val)
|
223
|
+
else
|
224
|
+
i = nil
|
225
|
+
case key
|
226
|
+
when *BOOL_PROPERTIES
|
227
|
+
if val.nil? || val == false || val == 0
|
228
|
+
i = Assimp::FALSE
|
229
|
+
else
|
230
|
+
i = Assimp::TRUE
|
231
|
+
end
|
232
|
+
when MATKEY_SHADING_MODEL
|
233
|
+
i = ShadingMode.to_native(val, nil)
|
234
|
+
when MATKEY_MAPPINGMODE_U, MATKEY_MAPPINGMODE_V, MATKEY_MAPPINGMODE_W
|
235
|
+
i = TextureMapMode.to_native(val, nil)
|
236
|
+
when MATKEY_BLEND_FUNC
|
237
|
+
i = BlendMode.to_native(val, nil)
|
238
|
+
when MATKEY_TEXFLAGS
|
239
|
+
i = TextureFlags.to_native(val, nil)
|
240
|
+
when MATKEY_MAPPING
|
241
|
+
i = TextureMapping.to_native(val, nil)
|
242
|
+
when MATKEY_TEXOP
|
243
|
+
i = TextureOp.to_native(val, nil)
|
244
|
+
else
|
245
|
+
i = val
|
246
|
+
end
|
247
|
+
ptr = FFI::MemoryPointer::new(:int)
|
248
|
+
ptr.write_int(i)
|
249
|
+
end
|
250
|
+
when :Float
|
251
|
+
if val.kind_of? Array
|
252
|
+
ptr = FFI::MemoryPointer::new(:float, val.length)
|
253
|
+
ptr.write_array_of_float(val)
|
254
|
+
elsif val.kind_of? FFI::Struct
|
255
|
+
ptr = FFI::MemoryPointer::new(val.class.size)
|
256
|
+
ptr.write_array_of_uint8(val.pointer.read_array_of_uint8(val.class.size))
|
257
|
+
else
|
258
|
+
ptr = FFI::MemoryPointer::new(:float)
|
259
|
+
ptr.write_float(val)
|
260
|
+
end
|
261
|
+
when :Double
|
262
|
+
if val.kind_of? Array
|
263
|
+
ptr = FFI::MemoryPointer::new(:double, val.length)
|
264
|
+
ptr.write_array_of_double(val)
|
265
|
+
elsif val.kind_of? FFI::Struct
|
266
|
+
ptr = FFI::MemoryPointer::new(val.class.size)
|
267
|
+
ptr.write_array_of_uint8(val.pointer.read_array_of_uint8(val.class.size))
|
268
|
+
else
|
269
|
+
ptr.write_double(val)
|
270
|
+
end
|
271
|
+
when :Buffer
|
272
|
+
if val.kind_of? FFI::Pointer
|
273
|
+
ptr = FFI::MemoryPointer::new(val.size)
|
274
|
+
ptr.write_array_of_uint8(val.pointer.read_array_of_uint8(val.size))
|
275
|
+
else
|
276
|
+
ptr = FFI::MemoryPointer.from_string(val)
|
277
|
+
end
|
278
|
+
else
|
279
|
+
raise ArgumentError::new("Invalid type: #{type.inspect}!")
|
280
|
+
end
|
281
|
+
@data = ptr
|
282
|
+
self[:data] = ptr
|
283
|
+
self.data_length = (ptr ? ptr.size : 0)
|
284
|
+
val
|
285
|
+
end
|
286
|
+
|
287
|
+
def data
|
288
|
+
case type
|
289
|
+
when :String
|
290
|
+
length = self[:data].read_uint
|
291
|
+
self[:data].get_string(4, length)
|
292
|
+
when :Integer
|
293
|
+
if data_length == 4
|
294
|
+
i = self[:data].read_int
|
295
|
+
case key
|
296
|
+
when *BOOL_PROPERTIES
|
297
|
+
i != 0
|
298
|
+
when MATKEY_SHADING_MODEL
|
299
|
+
ShadingMode[i]
|
300
|
+
when MATKEY_MAPPINGMODE_U, MATKEY_MAPPINGMODE_V, MATKEY_MAPPINGMODE_W
|
301
|
+
TextureMapMode[i]
|
302
|
+
when MATKEY_BLEND_FUNC
|
303
|
+
BlendMode[i]
|
304
|
+
when MATKEY_TEXFLAGS
|
305
|
+
TextureFlags[i]
|
306
|
+
when MATKEY_MAPPING
|
307
|
+
TextureMapping[i]
|
308
|
+
when MATKEY_TEXOP
|
309
|
+
TextureOp[i]
|
310
|
+
else
|
311
|
+
i
|
312
|
+
end
|
313
|
+
elsif data_length > 4
|
314
|
+
self[:data].read_array_of_int(data_length/4)
|
315
|
+
else
|
316
|
+
nil
|
317
|
+
end
|
318
|
+
when :Float
|
319
|
+
if data_length == 4
|
320
|
+
self[:data].read_float
|
321
|
+
elsif data_length > 4
|
322
|
+
if key.match("\\$clr\\.") && data_length == Color4D.size
|
323
|
+
Color4D.new(self[:data])
|
324
|
+
elsif key == MATKEY_TEXMAP_AXIS && data_length == Vector3D.size
|
325
|
+
Vector3D.new(self[:data])
|
326
|
+
elsif key == MATKEY_UVTRANSFORM && data_length == UVTransform.size
|
327
|
+
UVTransform.new(self[:data])
|
328
|
+
else
|
329
|
+
self[:data].read_array_of_float(data_length/4)
|
330
|
+
end
|
331
|
+
else
|
332
|
+
nil
|
333
|
+
end
|
334
|
+
when :Double
|
335
|
+
if data_length == 8
|
336
|
+
self[:data].read_double
|
337
|
+
elsif data_length > 8
|
338
|
+
if key.match("\\$clr\\.") && data_length == Color4D.size
|
339
|
+
Color4D.new(self[:data])
|
340
|
+
elsif key == MATKEY_TEXMAP_AXIS && data_length == Vector3D.size
|
341
|
+
Vector3D.new(self[:data])
|
342
|
+
elsif key == MATKEY_UVTRANSFORM && data_length == UVTransform.size
|
343
|
+
UVTransform.new(self[:data])
|
344
|
+
else
|
345
|
+
self[:data].read_array_of_double(data_length/8)
|
346
|
+
end
|
347
|
+
else
|
348
|
+
nil
|
349
|
+
end
|
350
|
+
when :Buffer
|
351
|
+
self[:data].slice(0, data_length)
|
352
|
+
else
|
353
|
+
raise "Invalid type: #{type.inspect}!"
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def to_s
|
358
|
+
"#{key}: #{data}"
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
class Material < FFI::Struct
|
363
|
+
extend StructAccessors
|
364
|
+
layout :properties, :pointer, #MaterialProperty*[num_properties]
|
365
|
+
:num_properties, :uint,
|
366
|
+
:num_allocated, :uint
|
367
|
+
struct_attr_accessor :num_properties,
|
368
|
+
:num_allocated
|
369
|
+
struct_ref_array_attr_accessor [:properties, MaterialProperty]
|
370
|
+
|
371
|
+
def property(key, type, index)
|
372
|
+
ptr = FFI::MemoryPointer::new(:pointer)
|
373
|
+
res = Assimp::aiGetMaterialProperty(self, key, type, index, ptr)
|
374
|
+
raise "get_material_property error!" unless res == :SUCCESS
|
375
|
+
new_ptr = ptr.read_pointer
|
376
|
+
return nil if new_ptr.null?
|
377
|
+
MaterialProperty::new(new_ptr)
|
378
|
+
end
|
379
|
+
|
380
|
+
end
|
381
|
+
|
382
|
+
attach_function :aiGetMaterialProperty,
|
383
|
+
[Material.ptr, :string, :uint, :uint, :pointer ], Return
|
384
|
+
|
385
|
+
|
386
|
+
attach_function :aiGetMaterialFloatArray,
|
387
|
+
[Material.ptr, :string, :uint, :uint, :pointer, :pointer], Return
|
388
|
+
|
389
|
+
attach_function :aiGetMaterialIntegerArray,
|
390
|
+
[Material.ptr, :string, :uint, :uint, :pointer, :pointer], Return
|
391
|
+
|
392
|
+
attach_function :aiGetMaterialColor,
|
393
|
+
[Material.ptr, :string, :uint, :uint, Color4D.ptr], Return
|
394
|
+
|
395
|
+
attach_function :aiGetMaterialUVTransform,
|
396
|
+
[Material.ptr, :string, :uint, :uint, UVTransform.ptr], Return
|
397
|
+
|
398
|
+
attach_function :aiGetMaterialString,
|
399
|
+
[Material.ptr, :string, :uint, :uint, String.ptr], Return
|
400
|
+
|
401
|
+
attach_function :aiGetMaterialTextureCount,
|
402
|
+
[Material.ptr, TextureType], :uint
|
403
|
+
|
404
|
+
attach_function :aiGetMaterialTexture,
|
405
|
+
[Material.ptr, TextureType, :uint, String.ptr, :pointer, :uint, :pointer, :pointer, :pointer, :pointer], Return
|
406
|
+
|
407
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Assimp
|
2
|
+
|
3
|
+
class Matrix3x3 < FFI::Struct
|
4
|
+
extend StructAccessors
|
5
|
+
layout :a1, :ai_real, :a2, :ai_real, :a3, :ai_real,
|
6
|
+
:b1, :ai_real, :b2, :ai_real, :b3, :ai_real,
|
7
|
+
:c1, :ai_real, :c2, :ai_real, :c3, :ai_real
|
8
|
+
struct_attr_accessor :a1, :a2, :a3,
|
9
|
+
:b1, :b2, :b3,
|
10
|
+
:c1, :c2, :c3
|
11
|
+
|
12
|
+
def self.identity
|
13
|
+
m = Matrix3x3::new
|
14
|
+
Assimp::aiIdentityMatrix3(m)
|
15
|
+
m
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.rotation(a, axis)
|
19
|
+
# https://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle
|
20
|
+
c = Math::cos(a)
|
21
|
+
s = Math::sin(a)
|
22
|
+
t = 1 - c
|
23
|
+
x = axis.x
|
24
|
+
y = axis.y
|
25
|
+
z = axis.z
|
26
|
+
|
27
|
+
out = Matrix3x3
|
28
|
+
out.a1 = t*x*x + c
|
29
|
+
out.a2 = t*x*y - s*z
|
30
|
+
out.a3 = t*x*z + s*y
|
31
|
+
out.b1 = t*x*y + s*z
|
32
|
+
out.b2 = t*y*y + c
|
33
|
+
out.b3 = t*y*z - s*x
|
34
|
+
out.c1 = t*x*z - s*y
|
35
|
+
out.c2 = t*y*z + s*x
|
36
|
+
out.c3 = t*z*z + c
|
37
|
+
out
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
<<EOF
|
42
|
+
< <#{a1}, #{a2}, #{a3}>,
|
43
|
+
<#{b1}, #{b2}, #{b3}>,
|
44
|
+
<#{c1}, #{c2}, #{c3}> >
|
45
|
+
EOF
|
46
|
+
end
|
47
|
+
|
48
|
+
def quaternion
|
49
|
+
q = Quaternion::new
|
50
|
+
Assimp::aiCreateQuaternionFromMatrix(q, self)
|
51
|
+
end
|
52
|
+
|
53
|
+
def transpose!
|
54
|
+
Assimp::aiTransposeMatrix3(self)
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def transpose
|
59
|
+
t = self.dup
|
60
|
+
t.transpose!
|
61
|
+
end
|
62
|
+
|
63
|
+
def *(other)
|
64
|
+
if other.kind_of?(Matrix3x3)
|
65
|
+
m = self.dup
|
66
|
+
Assimp::aiMultiplyMatrix3(m, other)
|
67
|
+
m
|
68
|
+
elsif other.kind_of?(Vector3D)
|
69
|
+
v = other.dup
|
70
|
+
Assimp::aiTransformVecByMatrix3(v, self)
|
71
|
+
v
|
72
|
+
else
|
73
|
+
"Unsupported operand: #{other.inspect}!"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def determinant
|
78
|
+
a1*b2*c3 - a1*b3*c2 + a2*b3*c1 - a2*b1*c3 + a3*b1*c2 - a3*b2*c1
|
79
|
+
end
|
80
|
+
|
81
|
+
def inverse
|
82
|
+
det = determinant
|
83
|
+
raise "Not inversible!" if det == 0.0
|
84
|
+
m = Matrix3x3::new
|
85
|
+
invdet = 1.0/det
|
86
|
+
m.a1 = invdet * (b2 * c3 - b3 * c2)
|
87
|
+
m.a2 = -invdet * (a2 * c3 - a3 * c2)
|
88
|
+
m.a3 = invdet * (a2 * b3 - a3 * b2)
|
89
|
+
m.b1 = -invdet * (b1 * c3 - b3 * c1)
|
90
|
+
m.b2 = invdet * (a1 * c3 - a3 * c1)
|
91
|
+
m.b3 = -invdet * (a1 * b3 - a3 * b1)
|
92
|
+
m.c1 = invdet * (b1 * c2 - b2 * c1)
|
93
|
+
m.c2 = -invdet * (a1 * c2 - a2 * c1)
|
94
|
+
m.c3 = invdet * (a1 * b2 - a2 * b1)
|
95
|
+
m
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
module Assimp
|
2
|
+
|
3
|
+
class Matrix4x4 < FFI::Struct
|
4
|
+
extend StructAccessors
|
5
|
+
layout :a1, :ai_real, :a2, :ai_real, :a3, :ai_real, :a4, :ai_real,
|
6
|
+
:b1, :ai_real, :b2, :ai_real, :b3, :ai_real, :b4, :ai_real,
|
7
|
+
:c1, :ai_real, :c2, :ai_real, :c3, :ai_real, :c4, :ai_real,
|
8
|
+
:d1, :ai_real, :d2, :ai_real, :d3, :ai_real, :d4, :ai_real
|
9
|
+
struct_attr_accessor :a1, :a2, :a3, :a4,
|
10
|
+
:b1, :b2, :b3, :b4,
|
11
|
+
:c1, :c2, :c3, :c4,
|
12
|
+
:d1, :d2, :d3, :d4
|
13
|
+
|
14
|
+
def self.identity
|
15
|
+
m = Matrix4x4::new
|
16
|
+
Assimp::aiIdentityMatrix4(m)
|
17
|
+
m
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.rotation(a, axis)
|
21
|
+
# https://en.wikipedia.org/wiki/Rotation_matrix#Axis_and_angle
|
22
|
+
c = Math::cos(a)
|
23
|
+
s = Math::sin(a)
|
24
|
+
t = 1 - c
|
25
|
+
x = axis.x
|
26
|
+
y = axis.y
|
27
|
+
z = axis.z
|
28
|
+
|
29
|
+
out = Matrix4x4
|
30
|
+
out.a1 = t*x*x + c
|
31
|
+
out.a2 = t*x*y - s*z
|
32
|
+
out.a3 = t*x*z + s*y
|
33
|
+
out.a4 = 0.0
|
34
|
+
out.b1 = t*x*y + s*z
|
35
|
+
out.b2 = t*y*y + c
|
36
|
+
out.b3 = t*y*z - s*x
|
37
|
+
out.b4 = 0.0
|
38
|
+
out.c1 = t*x*z - s*y
|
39
|
+
out.c2 = t*y*z + s*x
|
40
|
+
out.c3 = t*z*z + c
|
41
|
+
out.c4 = 0.0
|
42
|
+
out.d1 = 0.0
|
43
|
+
out.d2 = 0.0
|
44
|
+
out.d3 = 0.0
|
45
|
+
out.d4 = 1.0
|
46
|
+
out
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.translation(vec)
|
50
|
+
out = identity
|
51
|
+
out.a4 = vec.x
|
52
|
+
out.b4 = vec.y
|
53
|
+
out.c4 = vec.z
|
54
|
+
out
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.scaling(vec)
|
58
|
+
out = identity
|
59
|
+
out.a1 = v.x
|
60
|
+
out.b2 = v.y
|
61
|
+
out.c3 = v.z
|
62
|
+
out
|
63
|
+
end
|
64
|
+
|
65
|
+
def identity!
|
66
|
+
Assimp::aiIdentityMatrix4(self)
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_s
|
71
|
+
<<EOF
|
72
|
+
< <#{a1}, #{a2}, #{a3}, #{a4}>,
|
73
|
+
<#{b1}, #{b2}, #{b3}, #{b4}>,
|
74
|
+
<#{c1}, #{c2}, #{c3}, #{c4}>,
|
75
|
+
<#{d1}, #{d2}, #{d3}, #{d4}> >
|
76
|
+
EOF
|
77
|
+
end
|
78
|
+
|
79
|
+
def decompose
|
80
|
+
scaling = Vector3D::new
|
81
|
+
rotation = Quaternion::new
|
82
|
+
position = Vector3D::new
|
83
|
+
Assimp::aiDecomposeMatrix(self, scaling, rotation, position)
|
84
|
+
[scaling, rotation, position]
|
85
|
+
end
|
86
|
+
|
87
|
+
def transpose!
|
88
|
+
Assimp::aiTransposeMatrix4(self)
|
89
|
+
self
|
90
|
+
end
|
91
|
+
|
92
|
+
def transpose
|
93
|
+
t = self.dup
|
94
|
+
t.transpose!
|
95
|
+
end
|
96
|
+
|
97
|
+
def *(other)
|
98
|
+
if other.kind_of?(Matrix4x4)
|
99
|
+
m = self.dup
|
100
|
+
Assimp::aiMultiplyMatrix4(m, other)
|
101
|
+
m
|
102
|
+
elsif other.kind_of?(Vector3D)
|
103
|
+
v = other.dup
|
104
|
+
Assimp::aiTransformVecByMatrix4(v, self)
|
105
|
+
v
|
106
|
+
else
|
107
|
+
"Unsupported operand: #{other.inspect}!"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def determinant
|
112
|
+
a1*b2*c3*d4 - a1*b2*c4*d3 + a1*b3*c4*d2 - a1*b3*c2*d4 +
|
113
|
+
a1*b4*c2*d3 - a1*b4*c3*d2 - a2*b3*c4*d1 + a2*b3*c1*d4 -
|
114
|
+
a2*b4*c1*d3 + a2*b4*c3*d1 - a2*b1*c3*d4 + a2*b1*c4*d3 +
|
115
|
+
a3*b4*c1*d2 - a3*b4*c2*d1 + a3*b1*c2*d4 - a3*b1*c4*d2 +
|
116
|
+
a3*b2*c4*d1 - a3*b2*c1*d4 - a4*b1*c2*d3 + a4*b1*c3*d2 -
|
117
|
+
a4*b2*c3*d1 + a4*b2*c1*d3 - a4*b3*c1*d2 + a4*b3*c2*d1
|
118
|
+
end
|
119
|
+
|
120
|
+
def inverse
|
121
|
+
det = determinant
|
122
|
+
raise "Not inversible!" if det == 0.0
|
123
|
+
m = Matrix4x4::new
|
124
|
+
invdet = 1.0/det
|
125
|
+
m.a1 = invdet * (b2 * (c3 * d4 - c4 * d3) +
|
126
|
+
b3 * (c4 * d2 - c2 * d4) +
|
127
|
+
b4 * (c2 * d3 - c3 * d2))
|
128
|
+
m.a2 = -invdet * (a2 * (c3 * d4 - c4 * d3) +
|
129
|
+
a3 * (c4 * d2 - c2 * d4) +
|
130
|
+
a4 * (c2 * d3 - c3 * d2))
|
131
|
+
m.a3 = invdet * (a2 * (b3 * d4 - b4 * d3) +
|
132
|
+
a3 * (b4 * d2 - b2 * d4) +
|
133
|
+
a4 * (b2 * d3 - b3 * d2))
|
134
|
+
m.a4 = -invdet * (a2 * (b3 * c4 - b4 * c3) +
|
135
|
+
a3 * (b4 * c2 - b2 * c4) +
|
136
|
+
a4 * (b2 * c3 - b3 * c2))
|
137
|
+
m.b1 = -invdet * (b1 * (c3 * d4 - c4 * d3) +
|
138
|
+
b3 * (c4 * d1 - c1 * d4) +
|
139
|
+
b4 * (c1 * d3 - c3 * d1))
|
140
|
+
m.b2 = invdet * (a1 * (c3 * d4 - c4 * d3) +
|
141
|
+
a3 * (c4 * d1 - c1 * d4) +
|
142
|
+
a4 * (c1 * d3 - c3 * d1))
|
143
|
+
m.b3 = -invdet * (a1 * (b3 * d4 - b4 * d3) +
|
144
|
+
a3 * (b4 * d1 - b1 * d4) +
|
145
|
+
a4 * (b1 * d3 - b3 * d1))
|
146
|
+
m.b4 = invdet * (a1 * (b3 * c4 - b4 * c3) +
|
147
|
+
a3 * (b4 * c1 - b1 * c4) +
|
148
|
+
a4 * (b1 * c3 - b3 * c1))
|
149
|
+
m.c1 = invdet * (b1 * (c2 * d4 - c4 * d2) +
|
150
|
+
b2 * (c4 * d1 - c1 * d4) +
|
151
|
+
b4 * (c1 * d2 - c2 * d1))
|
152
|
+
m.c2 = -invdet * (a1 * (c2 * d4 - c4 * d2) +
|
153
|
+
a2 * (c4 * d1 - c1 * d4) +
|
154
|
+
a4 * (c1 * d2 - c2 * d1))
|
155
|
+
m.c3 = invdet * (a1 * (b2 * d4 - b4 * d2) +
|
156
|
+
a2 * (b4 * d1 - b1 * d4) +
|
157
|
+
a4 * (b1 * d2 - b2 * d1))
|
158
|
+
m.c4 = -invdet * (a1 * (b2 * c4 - b4 * c2) +
|
159
|
+
a2 * (b4 * c1 - b1 * c4) +
|
160
|
+
a4 * (b1 * c2 - b2 * c1))
|
161
|
+
m.d1 = -invdet * (b1 * (c2 * d3 - c3 * d2) +
|
162
|
+
b2 * (c3 * d1 - c1 * d3) +
|
163
|
+
b3 * (c1 * d2 - c2 * d1))
|
164
|
+
m.d2 = invdet * (a1 * (c2 * d3 - c3 * d2) +
|
165
|
+
a2 * (c3 * d1 - c1 * d3) +
|
166
|
+
a3 * (c1 * d2 - c2 * d1))
|
167
|
+
m.d3 = -invdet * (a1 * (b2 * d3 - b3 * d2) +
|
168
|
+
a2 * (b3 * d1 - b1 * d3) +
|
169
|
+
a3 * (b1 * d2 - b2 * d1))
|
170
|
+
m.d4 = invdet * (a1 * (b2 * c3 - b3 * c2) +
|
171
|
+
a2 * (b3 * c1 - b1 * c3) +
|
172
|
+
a3 * (b1 * c2 - b2 * c1))
|
173
|
+
m
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|