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,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