mittsu-gltf 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7357b9b37036619cd1dcac6a0272db90d88f6e0caf567805c4df6f15ada7c272
4
+ data.tar.gz: e9ee54d8195e9b1635163fccc9855dc9bd3a3b61333f2c8b61ac620e65899f84
5
+ SHA512:
6
+ metadata.gz: 9c66bb2249b83c4b1b7f8291ab8e619851c08dc462eb0310f08ca0198f9c20bd8cd5f9199f82d438d0dc9cc6dedadd7013129a19eec387942318efa8ef55f41b
7
+ data.tar.gz: 4dc4dd25b9001add1c635608dcd3d769a5c4c3828f7a915f33e0694b3c91c697af9120b46b293b56cad9a5338096f1dea88031ee38827048077a2d7ccff370fc
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # Mittsu: GLTF
2
+ GLTF support for [Mittsu](https://github.com/danini-the-panini/mittsu).
3
+
4
+ ## Installation
5
+
6
+ Just install:
7
+
8
+ `bundle add mittsu-gltf`
9
+
10
+ Then require in your code:
11
+
12
+ `require 'mittsu/gltf'`
13
+
14
+ ## Usage
15
+
16
+ Currently this gem just includes an exporter. Loading GLTF files might happen at some point.
17
+
18
+ ```
19
+ exporter = Mittsu::GLTFExporter.new
20
+ exporter.export(object, "output.gltf")
21
+ ```
22
+
23
+ ## About
24
+
25
+ This code was originally written for [Manyfold](https://manyfold.app), supported by funding from [NLNet](https://nlnet.nl) and [NGI Zero](https://ngi.eu/ngi-projects/ngi-zero/).
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/setup"
2
+
3
+ require "rspec/core"
4
+ require "rspec/core/rake_task"
5
+ require "standard/rake"
6
+ Bundler::GemHelper.install_tasks
7
+
8
+ desc "Run all specs in spec directory"
9
+ RSpec::Core::RakeTask.new(:spec)
10
+
11
+ task default: :spec
@@ -0,0 +1,168 @@
1
+ require "jbuilder"
2
+ require "base64"
3
+
4
+ module Mittsu
5
+ class GLTFExporter
6
+ COMPONENT_TYPES = {
7
+ # 8 bit
8
+ byte: 5120,
9
+ unsigned_byte: 5121,
10
+ # 16 bit
11
+ short: 5122,
12
+ unsigned_short: 5123,
13
+ # 32 bit
14
+ unsigned_int: 5125,
15
+ float: 5126
16
+ }.freeze
17
+
18
+ GPU_BUFFER_TYPES = {
19
+ array_buffer: 34962,
20
+ element_array_buffer: 34963
21
+ }
22
+
23
+ ELEMENT_TYPES = [
24
+ "SCALAR",
25
+ "VEC2",
26
+ "VEC3",
27
+ "VEC4",
28
+ "MAT2",
29
+ "MAT3",
30
+ "MAT4"
31
+ ].freeze
32
+
33
+ def initialize(options = {})
34
+ @node_indexes = []
35
+ @nodes = []
36
+ @buffers = []
37
+ @meshes = []
38
+ @buffer_views = []
39
+ @accessors = []
40
+ end
41
+
42
+ def export(object, filename)
43
+ object.traverse do |obj|
44
+ @node_indexes << add_mesh(obj) if obj.is_a? Mittsu::Mesh
45
+ end
46
+ File.write(
47
+ filename,
48
+ Jbuilder.new do |json|
49
+ json.asset do
50
+ json.generator "Mittsu-GLTF"
51
+ json.version "2.0"
52
+ end
53
+ json.scene 0
54
+ json.scenes [{
55
+ nodes: @node_indexes
56
+ }]
57
+ json.nodes { json.array! @nodes }
58
+ json.meshes { json.array! @meshes }
59
+ json.buffers { json.array! @buffers }
60
+ json.bufferViews { json.array! @buffer_views }
61
+ json.accessors { json.array! @accessors }
62
+ end.target!
63
+ )
64
+ end
65
+
66
+ # Parse is here for consistency with THREE.js's weird naming of exporter methods
67
+ alias_method :parse, :export
68
+
69
+ private
70
+
71
+ def add_mesh(mesh)
72
+ # Pack faces into an array
73
+ pack_string = (mesh.geometry.faces.count > (2**16)) ? "L<*" : "S<*"
74
+ faces = mesh.geometry.faces.map { |x| [x.a, x.b, x.c] }
75
+ data = faces.flatten.pack(pack_string)
76
+ # Add bufferView and accessor for faces
77
+ face_accessor_index = add_accessor(
78
+ buffer_view: add_buffer_view(
79
+ buffer: @buffers.count,
80
+ offset: 0,
81
+ length: data.length,
82
+ target: :element_array_buffer
83
+ ),
84
+ component_type: (mesh.geometry.faces.count > (2**16)) ? :unsigned_int : :unsigned_short,
85
+ count: mesh.geometry.faces.count * 3,
86
+ type: "SCALAR",
87
+ min: 0,
88
+ max: mesh.geometry.vertices.count - 1
89
+ )
90
+ # Add padding to get to integer multiple of float size
91
+ padding = 4 - (data.length % 4)
92
+ data += Array.new(padding, 0).pack("C*")
93
+ # Pack vertices in as floats
94
+ offset = data.length
95
+ vertices = mesh.geometry.vertices.map(&:elements)
96
+ data += vertices.flatten.pack("f*")
97
+ # Add bufferView and accessor for vertices
98
+ mesh.geometry.compute_bounding_box
99
+ vertex_accessor_index = add_accessor(
100
+ buffer_view: add_buffer_view(
101
+ buffer: @buffers.count,
102
+ offset: offset,
103
+ length: data.length - offset,
104
+ target: :array_buffer
105
+ ),
106
+ component_type: :float,
107
+ count: mesh.geometry.vertices.count,
108
+ type: "VEC3",
109
+ min: mesh.geometry.bounding_box.min.elements,
110
+ max: mesh.geometry.bounding_box.max.elements
111
+ )
112
+ # Encode and store in buffers
113
+ @buffers << {
114
+ uri: "data:application/octet-stream;base64," + Base64.strict_encode64(data),
115
+ byteLength: data.length
116
+ }
117
+ # Add mesh
118
+ mesh_index = @meshes.count
119
+ @meshes << {
120
+ "primitives" => [
121
+ {
122
+ "attributes" => {
123
+ "POSITION" => vertex_accessor_index
124
+ },
125
+ "indices" => face_accessor_index
126
+ }
127
+ ]
128
+ }
129
+ # Add node
130
+ index = @nodes.count
131
+ @nodes << {
132
+ mesh: mesh_index
133
+ }
134
+ index
135
+ end
136
+
137
+ def add_buffer_view(buffer:, offset:, length:, target: nil)
138
+ # Check args
139
+ raise ArgumentError.new("invalid GPU buffer target: #{target}") unless target.nil? || GPU_BUFFER_TYPES.keys.include?(target)
140
+ index = @buffer_views.count
141
+ @buffer_views << {
142
+ buffer: buffer,
143
+ byteOffset: offset,
144
+ byteLength: length,
145
+ target: GPU_BUFFER_TYPES[target]
146
+ }
147
+ index
148
+ end
149
+
150
+ def add_accessor(buffer_view:, component_type:, count:, type:, min:, max:, offset: 0)
151
+ # Check args
152
+ raise ArgumentError.new("invalid component type: #{component_type}") unless COMPONENT_TYPES.key?(component_type)
153
+ raise ArgumentError.new("invalid element type: #{type}") unless ELEMENT_TYPES.include?(type)
154
+ # Add data
155
+ index = @accessors.count
156
+ @accessors << {
157
+ bufferView: buffer_view,
158
+ byteOffset: offset,
159
+ componentType: COMPONENT_TYPES[component_type],
160
+ count: count,
161
+ type: type,
162
+ min: Array(min),
163
+ max: Array(max)
164
+ }
165
+ index
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,5 @@
1
+ module Mittsu
2
+ module GLTF
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ require "mittsu"
2
+ require "mittsu/gltf/version"
3
+ require "mittsu/gltf/exporter"
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mittsu-gltf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - James Smith
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-12-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mittsu
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: jbuilder
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.13'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.13'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '13.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.13'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.13'
69
+ - !ruby/object:Gem::Dependency
70
+ name: standard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.41'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.41'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop-rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.2'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.2'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.6'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.6'
111
+ description: GLTF file support for Mittsu
112
+ email:
113
+ - james@floppy.org.uk
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - README.md
119
+ - Rakefile
120
+ - lib/mittsu/gltf.rb
121
+ - lib/mittsu/gltf/exporter.rb
122
+ - lib/mittsu/gltf/version.rb
123
+ homepage: https://github.com/manyfold3d/mittsu-gltf
124
+ licenses:
125
+ - MIT
126
+ metadata:
127
+ homepage_uri: https://github.com/manyfold3d/mittsu-gltf
128
+ source_code_uri: https://github.com/manyfold3d/mittsu-gltf
129
+ changelog_uri: https://github.com/manyfold3d/mittsu-gltf/releases
130
+ post_install_message:
131
+ rdoc_options: []
132
+ require_paths:
133
+ - lib
134
+ required_ruby_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '3.1'
139
+ required_rubygems_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ requirements: []
145
+ rubygems_version: 3.5.11
146
+ signing_key:
147
+ specification_version: 4
148
+ summary: GLTF file support for Mittsu
149
+ test_files: []