assimp-ffi 0.1.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.
@@ -0,0 +1,250 @@
1
+ module Assimp
2
+
3
+ MAX_FACE_INDICES = 0x7fff
4
+ MAX_BONE_WEIGHTS = 0x7fffffff
5
+ MAX_VERTICES = 0x7fffffff
6
+ MAX_FACES = 0x7fffffff
7
+ MAX_NUMBER_OF_COLOR_SETS = 0x8
8
+ MAX_NUMBER_OF_TEXTURECOORDS = 0x8
9
+
10
+ class Face < FFI::Struct
11
+ extend StructAccessors
12
+ layout :num_indices, :uint,
13
+ :indices, :pointer #:uint[num_indices]
14
+
15
+ struct_attr_accessor :num_indices
16
+
17
+ struct_array_attr_accessor [:indices, :uint]
18
+
19
+ end
20
+
21
+ class VertexWeight < FFI::Struct
22
+ extend StructAccessors
23
+
24
+ layout :vertex_id, :uint,
25
+ :weight, :float
26
+
27
+ struct_attr_accessor :vertex_id,
28
+ :weight
29
+ end
30
+
31
+ class Bone < FFI::Struct
32
+ extend StructAccessors
33
+
34
+ layout :name, String,
35
+ :num_weights, :uint,
36
+ :weights, :pointer, #VertexWeight[num_weights]
37
+ :offset_matrix, Matrix4x4
38
+
39
+ struct_attr_accessor :name,
40
+ :num_weights,
41
+ :offset_matrix
42
+
43
+ struct_array_attr_accessor [:weights, VertexWeight]
44
+
45
+ end
46
+
47
+ PrimitiveType = bitmask(:primitive_type, [
48
+ :POINT,
49
+ :LINE,
50
+ :TRIANGLE,
51
+ :POLYGON
52
+ ])
53
+
54
+ class AnimMesh < FFI::Struct
55
+ extend StructAccessors
56
+
57
+ layout :vertices, :pointer, #Vector3D[]
58
+ :normals, :pointer, #Vector3D[]
59
+ :tangents, :pointer, #Vector3D[]
60
+ :bitangents, :pointer, #Vector3D[]
61
+ :colors, [:pointer, MAX_NUMBER_OF_COLOR_SETS], #Color4D[num_vertices]
62
+ :texture_coords, [:pointer, MAX_NUMBER_OF_TEXTURECOORDS], #Vector3D[num_vertices]
63
+ :num_vertices, :uint,
64
+ :weight, :float
65
+
66
+ struct_attr_accessor :num_vertices,
67
+ :weight
68
+
69
+ struct_array_attr_accessor [:vertices, Vector3D],
70
+ [:normals, Vector3D, :num_vertices],
71
+ [:tangents, Vector3D, :num_vertices],
72
+ [:bitangents, Vector3D, :num_vertices]
73
+
74
+ def colors
75
+ cs = self[:colors].to_a
76
+ cs.collect { |c_ptr|
77
+ if c_ptr.null?
78
+ nil
79
+ else
80
+ s = Color4D.size
81
+ num_vertices.times.collect { |i|
82
+ Color4D::new(c_ptr+i*s)
83
+ }
84
+ end
85
+ }
86
+ end
87
+
88
+ def set_colors(index, colors)
89
+ @colors = [nil]*MAX_NUMBER_OF_COLOR_SETS unless @colors
90
+ raise "Invalid colors index #{index}!" if index < 0 || index >= MAX_NUMBER_OF_COLOR_SETS
91
+ unless colors && colors.length > 0
92
+ @colors[index] = nil
93
+ return self
94
+ end
95
+ raise "Invalid colors count: #{colors.length}!" if num_vertices != colors.length
96
+ ptr = FFI::MemoryPointer::new(Assimp::Color4D, num_vertices)
97
+ s = Assimp::Color4D.size
98
+ colors.each_with_index { |v, i|
99
+ ptr.put_array_of_uint8(i*s, v.pointer.read_array_of_uint8(s))
100
+ }
101
+ @colors[index] = ptr
102
+ self
103
+ end
104
+
105
+ def texture_coords
106
+ tcs = self[:texture_coords].to_a
107
+ tcs.collect { |tc_ptr|
108
+ if tc_ptr.null?
109
+ nil
110
+ else
111
+ s = Vector3D.size
112
+ num_vertices.times.collect { |i|
113
+ Vector3D::new(tc_ptr+i*s)
114
+ }
115
+ end
116
+ }
117
+ end
118
+
119
+ def set_texture_coords(index, uvs)
120
+ @texture_coords = [nil]*MAX_NUMBER_OF_TEXTURECOORDS unless @texture_coords
121
+ raise "Invalid texture_coords index #{index}!" if index < 0 || index >= MAX_NUMBER_OF_TEXTURECOORDS
122
+ unless uvs && uvs.length > 0
123
+ @texture_coords[index] = nil
124
+ return self
125
+ end
126
+ raise "Invalid texture_coords count: #{uvs.length}!" if num_vertices != uvs.length
127
+ ptr = FFI::MemoryPointer::new(Assimp::Vector3D, num_vertices)
128
+ s = Assimp::Vector3D.size
129
+ uvs.each_with_index { |v, i|
130
+ ptr.put_array_of_uint8(i*s, v.pointer.read_array_of_uint8(s))
131
+ }
132
+ @texture_coords[index] = ptr
133
+ self
134
+ end
135
+
136
+ end
137
+
138
+ MorphingMethod = enum(:morphing_method, [
139
+ :VERTEX_BLEND, 1,
140
+ :MORPH_NORMALIZED, 2,
141
+ :MORPH_RELATIVE, 3
142
+ ])
143
+
144
+ class Mesh < FFI::Struct
145
+ extend StructAccessors
146
+
147
+ layout :primitive_types, PrimitiveType,
148
+ :num_vertices, :uint,
149
+ :num_faces, :uint,
150
+ :vertices, :pointer, #Vector3D[num_vertices]
151
+ :normals, :pointer, #Vector3D[num_vertices]
152
+ :tangents, :pointer, #Vector3D[num_vertices]
153
+ :bitangents, :pointer, #Vector3D[num_vertices]
154
+ :colors, [:pointer, MAX_NUMBER_OF_COLOR_SETS], #Color4D[num_vertices]
155
+ :texture_coords, [:pointer, MAX_NUMBER_OF_TEXTURECOORDS], #Vector3D[num_vertices]
156
+ :num_uv_components, [:uint, MAX_NUMBER_OF_TEXTURECOORDS],
157
+ :faces, :pointer, #Face[num_faces]
158
+ :num_bones, :uint,
159
+ :bones, :pointer, #Bone*[num_bones]
160
+ :material_index, :uint,
161
+ :name, String,
162
+ :num_anim_meshes, :uint,
163
+ :anim_meshes, :pointer, #AnimMesh*[num_anim_meshes]
164
+ :method, MorphingMethod
165
+
166
+ struct_attr_accessor :name,
167
+ :primitive_types,
168
+ :num_vertices,
169
+ :num_faces,
170
+ :num_uv_components,
171
+ :num_bones,
172
+ :material_index,
173
+ :num_anim_meshes,
174
+ :method
175
+
176
+ struct_array_attr_accessor [:vertices, Vector3D],
177
+ [:normals, Vector3D, :num_vertices],
178
+ [:tangents, Vector3D, :num_vertices],
179
+ [:bitangents, Vector3D, :num_vertices],
180
+ [:faces, Face]
181
+
182
+ struct_ref_array_attr_accessor [:bones, Bone],
183
+ [:anim_meshes, AnimMesh]
184
+
185
+ def colors
186
+ cs = self[:colors].to_a
187
+ cs.collect { |c_ptr|
188
+ if c_ptr.null?
189
+ nil
190
+ else
191
+ s = Color4D.size
192
+ num_vertices.times.collect { |i|
193
+ Color4D::new(c_ptr+i*s)
194
+ }
195
+ end
196
+ }
197
+ end
198
+
199
+ def set_colors(index, colors)
200
+ @colors = [nil]*MAX_NUMBER_OF_COLOR_SETS unless @colors
201
+ raise "Invalid colors index #{index}!" if index < 0 || index >= MAX_NUMBER_OF_COLOR_SETS
202
+ unless colors && colors.length > 0
203
+ @colors[index] = nil
204
+ return self
205
+ end
206
+ raise "Invalid colors count: #{colors.length}!" if num_vertices != colors.length
207
+ ptr = FFI::MemoryPointer::new(Assimp::Color4D, num_vertices)
208
+ s = Assimp::Color4D.size
209
+ colors.each_with_index { |v, i|
210
+ ptr.put_array_of_uint8(i*s, v.pointer.read_array_of_uint8(s))
211
+ }
212
+ @colors[index] = ptr
213
+ self[:colors][index] = ptr
214
+ self
215
+ end
216
+
217
+ def texture_coords
218
+ tcs = self[:texture_coords].to_a
219
+ tcs.collect { |tc_ptr|
220
+ if tc_ptr.null?
221
+ nil
222
+ else
223
+ s = Vector3D.size
224
+ num_vertices.times.collect { |i|
225
+ Vector3D::new(tc_ptr+i*s)
226
+ }
227
+ end
228
+ }
229
+ end
230
+
231
+ def set_texture_coords(index, uvs)
232
+ @texture_coords = [nil]*MAX_NUMBER_OF_TEXTURECOORDS unless @texture_coords
233
+ raise "Invalid texture_coords index #{index}!" if index < 0 || index >= MAX_NUMBER_OF_TEXTURECOORDS
234
+ unless uvs && uvs.length > 0
235
+ @texture_coords[index] = nil
236
+ return self
237
+ end
238
+ raise "Invalid texture_coords count: #{uvs.length}!" if num_vertices != uvs.length
239
+ ptr = FFI::MemoryPointer::new(Assimp::Vector3D, num_vertices)
240
+ s = Assimp::Vector3D.size
241
+ uvs.each_with_index { |v, i|
242
+ ptr.put_array_of_uint8(i*s, v.pointer.read_array_of_uint8(s))
243
+ }
244
+ @texture_coords[index] = ptr
245
+ self[:texture_coords][index] = ptr
246
+ self
247
+ end
248
+
249
+ end
250
+ end
@@ -0,0 +1,53 @@
1
+ module Assimp
2
+
3
+ MetadataType = enum(:metadata_type, [
4
+ :BOOL,
5
+ :INT32,
6
+ :UINT64,
7
+ :FLOAT,
8
+ :DOUBLE,
9
+ :AISTRING,
10
+ :AIVECTOR3D
11
+ ])
12
+
13
+ class MetadataEntry < FFI::Struct
14
+ extend StructAccessors
15
+ layout :type, MetadataType,
16
+ :data, :pointer
17
+ struct_attr_accessor :type
18
+
19
+ def data
20
+ d = self[:data]
21
+ case type
22
+ when :BOOL
23
+ d.read_uint != 0
24
+ when :INT32
25
+ d.read_int
26
+ when :UINT64
27
+ d.read(find_type(:uint64))
28
+ when :FLOAT
29
+ d.read_float
30
+ when :DOUBLE
31
+ d.read_double
32
+ when :AISTRING
33
+ s = d.read_uint
34
+ self[:data].get_string(4, s)
35
+ when :AIVECTOR3D
36
+ Vector3D::new(d)
37
+ else
38
+ raise "Unknown MetadataType : #{type}!"
39
+ end
40
+ end
41
+ end
42
+
43
+ class Metadata < FFI::Struct
44
+ extend StructAccessors
45
+ layout :num_properties, :uint,
46
+ :keys, :pointer, #String[num_properties]
47
+ :values, :pointer #MetadataEntry[num_properties]
48
+ struct_attr_accessor :num_properties
49
+ struct_array_attr_accessor [:values, MetadataEntry, :num_properties],
50
+ [:keys, String, :num_properties]
51
+ end
52
+
53
+ end
@@ -0,0 +1,81 @@
1
+ module Assimp
2
+
3
+ PostProcessSteps = bitmask(:post_process_steps, [
4
+ :CalcTangentSpace,
5
+ :JoinIdenticalVertices,
6
+ :MakeLeftHanded,
7
+ :Triangulate,
8
+ :RemoveComponent,
9
+ :GenNormals,
10
+ :GenSmoothNormals,
11
+ :SplitLargeMeshes,
12
+ :PreTransformVertices,
13
+ :LimitBoneWeights,
14
+ :ValidateDataStructure,
15
+ :ImproveCacheLocality,
16
+ :RemoveRedundantMaterials,
17
+ :FixInfacingNormals,
18
+ :SortByPType, 15,
19
+ :FindDegenerates,
20
+ :FindInvalidData,
21
+ :GenUVCoords,
22
+ :TransformUVCoords,
23
+ :FindInstances,
24
+ :OptimizeMeshes,
25
+ :OptimizeGraph,
26
+ :FlipUVs,
27
+ :FlipWindingOrder,
28
+ :SplitByBoneCount,
29
+ :Debone,
30
+ :GlobalScale
31
+ ])
32
+
33
+ ProcessPreset_ConvertToLeftHanded = Assimp::PostProcessSteps[
34
+ :MakeLeftHanded,
35
+ :FlipUVs,
36
+ :FlipWindingOrder
37
+ ]
38
+
39
+ ProcessPreset_TargetRealtime_Fast = Assimp::PostProcessSteps[
40
+ :CalcTangentSpace,
41
+ :GenNormals,
42
+ :JoinIdenticalVertices,
43
+ :Triangulate,
44
+ :GenUVCoords,
45
+ :SortByPType
46
+ ]
47
+
48
+ ProcessPreset_TargetRealtime_Quality = Assimp::PostProcessSteps[
49
+ :CalcTangentSpace,
50
+ :GenSmoothNormals,
51
+ :JoinIdenticalVertices,
52
+ :ImproveCacheLocality,
53
+ :LimitBoneWeights,
54
+ :RemoveRedundantMaterials,
55
+ :SplitLargeMeshes,
56
+ :Triangulate,
57
+ :GenUVCoords,
58
+ :SortByPType,
59
+ :FindDegenerates,
60
+ :FindInvalidData
61
+ ]
62
+
63
+ ProcessPreset_TargetRealtime_MaxQuality = Assimp::PostProcessSteps[
64
+ :CalcTangentSpace,
65
+ :GenSmoothNormals,
66
+ :JoinIdenticalVertices,
67
+ :ImproveCacheLocality,
68
+ :LimitBoneWeights,
69
+ :RemoveRedundantMaterials,
70
+ :SplitLargeMeshes,
71
+ :Triangulate,
72
+ :GenUVCoords,
73
+ :SortByPType,
74
+ :FindDegenerates,
75
+ :FindInvalidData,
76
+ :FindInstances,
77
+ :ValidateDataStructure,
78
+ :OptimizeMeshes
79
+ ]
80
+
81
+ end
@@ -0,0 +1,47 @@
1
+ module Assimp
2
+
3
+ class Quaternion < FFI::Struct
4
+ extend StructAccessors
5
+ layout :w, :ai_real,
6
+ :x, :ai_real,
7
+ :y, :ai_real,
8
+ :z, :ai_real
9
+ struct_attr_accessor :w, :x, :y, :z
10
+
11
+ def to_s
12
+ "{#{w}, #{x}, #{y}, #{z}}"
13
+ end
14
+
15
+ def conjugate
16
+ q = Quaternion::new
17
+ q.w = w
18
+ q.x = -x
19
+ q.y = -y
20
+ q.z = -z
21
+ q
22
+ end
23
+
24
+ def *(other)
25
+ if other.kind_of?(Quaternion)
26
+ q = Quaternion::new
27
+ q.w = w*other.w - x*other.x - y*other.y - z*other.z
28
+ q.x = w*other.x + x*other.w + y*other.z - z*other.y
29
+ q.y = w*other.y + y*other.w + z*other.x - x*other.z
30
+ q.z = w*other.z + z*other.w + x*other.y - y*other.x
31
+ q
32
+ elsif other.kind_of?(Vector3D)
33
+ v = Vector3D::new
34
+ q2 = Quaternion::new
35
+ q2.x = other.x
36
+ q2.y = other.y
37
+ q2.z = other.z
38
+ r = self * q2 * conjugate
39
+ v.set(r.x, r.y, r.z)
40
+ else
41
+ "Unsupported operand: #{other.inspect}!"
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,168 @@
1
+ module Assimp
2
+
3
+ class Node < FFI::Struct
4
+ extend StructAccessors
5
+
6
+ layout :name, String,
7
+ :transformation, Matrix4x4,
8
+ :parent, :pointer, #Node or null,
9
+ :num_children, :uint,
10
+ :children, :pointer, #Node*[num_chidren]
11
+ :num_meshes, :uint,
12
+ :meshes, :pointer, #uint[num_meshes]
13
+ :meta_data, :pointer #Metadata.ptr
14
+
15
+ struct_attr_accessor :name,
16
+ :transformation,
17
+ :num_children,
18
+ :num_meshes
19
+
20
+ struct_ref_array_attr_accessor [:children, Node]
21
+
22
+ struct_array_attr_accessor [:meshes, :uint]
23
+
24
+ def parent
25
+ ptr = self[:parent]
26
+ return nil if ptr.null?
27
+ Node::new(ptr)
28
+ end
29
+
30
+ def parent=(other)
31
+ if other.kind_of? FFI::Pointer
32
+ self[:parent] = other
33
+ elsif other.kind_of? Node
34
+ self[:parent] = other.pointer
35
+ else
36
+ raise ArgumentError::new("Argument should be a Node!")
37
+ end
38
+ other
39
+ end
40
+
41
+ def each_node(&block)
42
+ if block then
43
+ block.call self
44
+ children.each { |c|
45
+ c.each_node(&block)
46
+ }
47
+ return self
48
+ else
49
+ to_enum(:each_node)
50
+ end
51
+ end
52
+
53
+ def meta_data
54
+ p = self[:meta_data]
55
+ return nil if p.null?
56
+ Metadata::new(p)
57
+ end
58
+
59
+ end
60
+
61
+ SceneFlags = bitmask(:scene_flags, [
62
+ :INCOMPLETE,
63
+ :VALIDATED,
64
+ :VALIDATION_WARNING,
65
+ :NON_VERBOSE_FORMAT,
66
+ :FLAGS_TERRAIN,
67
+ :FLAGS_ALLOW_SHARED
68
+ ])
69
+
70
+ class Scene < FFI::ManagedStruct
71
+ extend StructAccessors
72
+
73
+ layout :flags, SceneFlags,
74
+ :root_node, Node.ptr,
75
+ :num_meshes, :uint,
76
+ :meshes, :pointer, #Mesh*[num_meshes]
77
+ :num_materials, :uint,
78
+ :materials, :pointer, #Material*[num_materials]
79
+ :num_animations, :uint,
80
+ :animations, :pointer, #Animation*[num_animations]
81
+ :num_textures, :uint,
82
+ :textures, :pointer, #Texture*[num_textures]
83
+ :num_lights, :uint,
84
+ :lights, :pointer, #Light*[num_lights]
85
+ :num_cameras, :uint,
86
+ :cameras, :pointer, #Camera*[num_cameras]
87
+ :private, :pointer #void * really...
88
+
89
+ struct_attr_accessor :flags,
90
+ :root_node,
91
+ :num_meshes,
92
+ :num_materials,
93
+ :num_animations,
94
+ :num_textures,
95
+ :num_lights,
96
+ :num_cameras,
97
+ :private
98
+
99
+ struct_ref_array_attr_accessor [:meshes, Mesh],
100
+ [:materials, Material],
101
+ [:animations, Animation],
102
+ [:textures, Texture],
103
+ [:lights, Light],
104
+ [:cameras, Camera]
105
+
106
+ def self.inherited(klass)
107
+ klass.instance_variable_set(:@layout, @layout)
108
+ end
109
+
110
+ def self.release(ptr)
111
+ Assimp::aiReleaseImport(ptr)
112
+ end
113
+
114
+ def each_node(&block)
115
+ if block then
116
+ node = root_node
117
+ node.each_node(&block)
118
+ return self
119
+ else
120
+ to_enum(:each_obj)
121
+ end
122
+ end
123
+
124
+ def apply_post_processing(steps)
125
+ ptr = Assimp::aiApplyPostProcessing(self, steps)
126
+ raise "Post processing failed!" if ptr.null?
127
+ self
128
+ end
129
+
130
+ def memory_requirements
131
+ m = Assimp::MemoryInfo::new
132
+ Assimp::aiGetMemoryRequirements(self, m)
133
+ m
134
+ end
135
+
136
+ def copy
137
+ m = FFI::MemoryPointer::new(:pointer)
138
+ Assimp::aiCopyScene(self, m)
139
+ ptr = m.read_pointer
140
+ raise "Could not copy scene: #{Assimp::LogStream::error_string}" if ptr.null?
141
+ Assimp::SceneCopy::new(ptr)
142
+ end
143
+
144
+ def export(format_id, file_name, preprocessing: 0, io: nil)
145
+ if io
146
+ Assimp::aiExportSceneEx(self, format_id, file_name, io, preprocessing)
147
+ else
148
+ Assimp::aiExportScene(self, format_id, file_name, preprocessing)
149
+ end
150
+ end
151
+
152
+ def export_to_blob(format_id, preprocessing: 0)
153
+ ptr = Assimp::aiExportSceneToBlob(self, format_id, preprocessing)
154
+ raise "Could not export scene: #{Assimp::LogStream::error_string}" if ptr.null?
155
+ Assimp::ExportDataBlob::new(FFI::AutoPointer::new(ptr, Assimp::ExportDataBlob::method(:releaser)))
156
+ end
157
+
158
+ end
159
+
160
+ class SceneCopy < Scene
161
+
162
+ def self.release(ptr)
163
+ Assimp::aiFreeScene(ptr)
164
+ end
165
+
166
+ end
167
+
168
+ end
@@ -0,0 +1,31 @@
1
+ module Assimp
2
+
3
+ class Texel < FFI::Struct
4
+ extend StructAccessors
5
+ pack 1
6
+ layout :b, :uchar,
7
+ :g, :uchar,
8
+ :r, :uchar,
9
+ :a, :uchar
10
+ struct_attr_accessor :b, :g, :r, :a
11
+ def to_s
12
+ "[#{r}, #{g}, #{b}, #{a}]"
13
+ end
14
+ end
15
+
16
+ class Texture < FFI::Struct
17
+ extend StructAccessors
18
+ layout :width, :uint,
19
+ :height, :uint,
20
+ :format_hint, [:char, 9],
21
+ :data, :pointer #Texel[width*height]
22
+ struct_attr_accessor :width,
23
+ :height
24
+
25
+ def format_hint
26
+ self[:format_hint].to_a.pack("U*")
27
+ end
28
+
29
+ end
30
+
31
+ end