assimp-ffi 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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