mittsu-gltf 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7357b9b37036619cd1dcac6a0272db90d88f6e0caf567805c4df6f15ada7c272
4
- data.tar.gz: e9ee54d8195e9b1635163fccc9855dc9bd3a3b61333f2c8b61ac620e65899f84
3
+ metadata.gz: 5f23eb33ddc959a9590cd7a980c9c82d5f94a5377d8837c50ffdbe1b71b82088
4
+ data.tar.gz: efd9a91fbb9830b4ca9e40b802de5ba7dd1af7eb6ef15799e624f31187abdec5
5
5
  SHA512:
6
- metadata.gz: 9c66bb2249b83c4b1b7f8291ab8e619851c08dc462eb0310f08ca0198f9c20bd8cd5f9199f82d438d0dc9cc6dedadd7013129a19eec387942318efa8ef55f41b
7
- data.tar.gz: 4dc4dd25b9001add1c635608dcd3d769a5c4c3828f7a915f33e0694b3c91c697af9120b46b293b56cad9a5338096f1dea88031ee38827048077a2d7ccff370fc
6
+ metadata.gz: 8245cd6f0a0ffedc302328322bb24fba2644246f92e238eb83b2245815d8de42ab6aabeccf5d93d75f05348cbe3950996c909b97da6e5f19758807dcba7b01dc
7
+ data.tar.gz: deba7453768e7aaa50af38dcd714be4ce189b708b6a1bcb8141b59047ba74c292d53cd27a4e2b23cc4d6d4f4d3925ec535c37ade0775d3947f1ed20d5d432403
data/README.md CHANGED
@@ -20,6 +20,12 @@ exporter = Mittsu::GLTFExporter.new
20
20
  exporter.export(object, "output.gltf")
21
21
  ```
22
22
 
23
+ You can also write binary files for simple single-mesh models:
24
+
25
+ ```
26
+ exporter.export(object, "output.glb", mode: :binary)
27
+ ```
28
+
23
29
  ## About
24
30
 
25
31
  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/).
@@ -37,30 +37,45 @@ module Mittsu
37
37
  @meshes = []
38
38
  @buffer_views = []
39
39
  @accessors = []
40
+ @binary_buffer = nil
40
41
  end
41
42
 
42
- def export(object, filename)
43
+ def export(object, filename, mode: :ascii)
44
+ initialize
43
45
  object.traverse do |obj|
44
- @node_indexes << add_mesh(obj) if obj.is_a? Mittsu::Mesh
46
+ @node_indexes << add_mesh(obj, mode: mode) if obj.is_a? Mittsu::Mesh
47
+ end
48
+ json = 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
+ case mode
64
+ when :ascii
65
+ File.write(filename, json)
66
+ when :binary
67
+ File.open(filename, "wb") do |file|
68
+ size = 12 +
69
+ 8 + json.length + padding_required(json, stride: 4) +
70
+ 8 + @binary_buffer.length + padding_required(@binary_buffer, stride: 4)
71
+ file.write("glTF")
72
+ file.write([2, size].pack("L<*"))
73
+ write_chunk(file, :json, json)
74
+ write_chunk(file, :binary, @binary_buffer)
75
+ end
76
+ else
77
+ raise ArgumentError "Invalid output mode #{mode}"
45
78
  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
79
  end
65
80
 
66
81
  # Parse is here for consistency with THREE.js's weird naming of exporter methods
@@ -68,7 +83,22 @@ module Mittsu
68
83
 
69
84
  private
70
85
 
71
- def add_mesh(mesh)
86
+ def write_chunk(file, type, data)
87
+ pad = padding_required(data, stride: 4)
88
+ file.write([data.length + pad].pack("L<*"))
89
+ case type
90
+ when :json
91
+ file.write("JSON")
92
+ when :binary
93
+ file.write("BIN\0")
94
+ else
95
+ raise ArgumentError.new("Invalid chunk type: #{type}")
96
+ end
97
+ file.write data
98
+ file.write(Array.new(pad, (type == :json) ? 32 : 0).pack("C*")) # Space characters for JSON, null otherwise
99
+ end
100
+
101
+ def add_mesh(mesh, mode:)
72
102
  # Pack faces into an array
73
103
  pack_string = (mesh.geometry.faces.count > (2**16)) ? "L<*" : "S<*"
74
104
  faces = mesh.geometry.faces.map { |x| [x.a, x.b, x.c] }
@@ -88,7 +118,7 @@ module Mittsu
88
118
  max: mesh.geometry.vertices.count - 1
89
119
  )
90
120
  # Add padding to get to integer multiple of float size
91
- padding = 4 - (data.length % 4)
121
+ padding = padding_required(data, stride: 4)
92
122
  data += Array.new(padding, 0).pack("C*")
93
123
  # Pack vertices in as floats
94
124
  offset = data.length
@@ -110,10 +140,13 @@ module Mittsu
110
140
  max: mesh.geometry.bounding_box.max.elements
111
141
  )
112
142
  # Encode and store in buffers
113
- @buffers << {
143
+ @buffers << ((mode == :ascii) ? {
114
144
  uri: "data:application/octet-stream;base64," + Base64.strict_encode64(data),
115
145
  byteLength: data.length
116
- }
146
+ } : {
147
+ byteLength: data.length
148
+ })
149
+ @binary_buffer = data if mode == :binary
117
150
  # Add mesh
118
151
  mesh_index = @meshes.count
119
152
  @meshes << {
@@ -136,7 +169,7 @@ module Mittsu
136
169
 
137
170
  def add_buffer_view(buffer:, offset:, length:, target: nil)
138
171
  # Check args
139
- raise ArgumentError.new("invalid GPU buffer target: #{target}") unless target.nil? || GPU_BUFFER_TYPES.keys.include?(target)
172
+ raise ArgumentError.new("invalid GPU buffer target: #{target}") unless target.nil? || GPU_BUFFER_TYPES.key?(target)
140
173
  index = @buffer_views.count
141
174
  @buffer_views << {
142
175
  buffer: buffer,
@@ -164,5 +197,9 @@ module Mittsu
164
197
  }
165
198
  index
166
199
  end
200
+
201
+ def padding_required(data, stride: 4)
202
+ (stride - (data.length % stride)) % stride
203
+ end
167
204
  end
168
205
  end
@@ -1,5 +1,5 @@
1
1
  module Mittsu
2
2
  module GLTF
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mittsu-gltf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Smith
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2024-12-12 00:00:00.000000000 Z
@@ -127,7 +127,7 @@ metadata:
127
127
  homepage_uri: https://github.com/manyfold3d/mittsu-gltf
128
128
  source_code_uri: https://github.com/manyfold3d/mittsu-gltf
129
129
  changelog_uri: https://github.com/manyfold3d/mittsu-gltf/releases
130
- post_install_message:
130
+ post_install_message:
131
131
  rdoc_options: []
132
132
  require_paths:
133
133
  - lib
@@ -142,8 +142,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
142
142
  - !ruby/object:Gem::Version
143
143
  version: '0'
144
144
  requirements: []
145
- rubygems_version: 3.5.11
146
- signing_key:
145
+ rubygems_version: 3.5.22
146
+ signing_key:
147
147
  specification_version: 4
148
148
  summary: GLTF file support for Mittsu
149
149
  test_files: []