extract (non-user) textures from glb + import user texture into glb
This commit is contained in:
parent
43ff366ca4
commit
e9b6500579
6 changed files with 175 additions and 106 deletions
83
manyfold/root/hook.d/experience_updated/1000-extract-textures.rb
Executable file
83
manyfold/root/hook.d/experience_updated/1000-extract-textures.rb
Executable file
|
|
@ -0,0 +1,83 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'json'
|
||||
require_relative './../../xrforge.rb'
|
||||
|
||||
# Check if a filename is provided
|
||||
if ARGV.length != 1
|
||||
puts "Usage: #{$0} <path/to/experience/somefile.xxx>"
|
||||
exit 1
|
||||
end
|
||||
|
||||
filename = ARGV[0]
|
||||
|
||||
require 'base64'
|
||||
require 'json'
|
||||
|
||||
begin
|
||||
|
||||
# Change the directory
|
||||
dir = File.dirname(filename)
|
||||
Dir.chdir( dir )
|
||||
# Read and parse the JSON file
|
||||
data = JSON.parse( File.read( "datapackage.json" ) )
|
||||
logfile = File.join( File.dirname(filename), ".xrforge/log.txt" )
|
||||
|
||||
|
||||
data['resources'].each do |resource|
|
||||
ext = File.extname(resource['path'])
|
||||
filenameWithoutExt = File.basename(resource['path'], ext)
|
||||
if ! XRForge::MODEL_EXT.any?( ext )
|
||||
next # skip unknown 3d files
|
||||
end
|
||||
if ! resource['path'].match(/^[a-zA-Z0-9]/)
|
||||
next # skip filenames like '_generated.glb' e.g. (produced by hooks)
|
||||
end
|
||||
|
||||
XRForge.log("✅ unpacking textures", logfile)
|
||||
gltf_path = ".xrforge/#{filenameWithoutExt}.gltf"
|
||||
system("assimp export #{resource['path']} #{gltf_path} --embed-textures")
|
||||
Dir.chdir("#{dir}/.xrforge")
|
||||
system("assimp extract #{filenameWithoutExt}.gltf | sed 's|/.*/||g'")
|
||||
Dir.chdir(dir)
|
||||
|
||||
# Read and parse the GLTF JSON
|
||||
gltf = JSON.parse(File.read(gltf_path))
|
||||
|
||||
# Ensure images section exists
|
||||
unless gltf['images'] && gltf['images'].is_a?(Array)
|
||||
puts "✅ No 'images' array found in #{gltf_path}"
|
||||
next
|
||||
end
|
||||
|
||||
# Iterate through the images array
|
||||
gltf['images'].each_with_index do |img, i|
|
||||
name = img['name']
|
||||
next unless name && !name.empty?
|
||||
|
||||
old_filename = "#{dir}/.xrforge/#{filenameWithoutExt}_img#{i}.png"
|
||||
new_filename = "#{dir}/#{name}.png"
|
||||
|
||||
puts old_filename
|
||||
puts new_filename
|
||||
|
||||
# move file to modeldirectory (but dont overwrite if user overwrite it)
|
||||
if File.exist?(old_filename) && !File.exist?(new_filename)
|
||||
puts "✅ Renaming #{old_filename} -> #{new_filename}"
|
||||
File.rename(old_filename, new_filename)
|
||||
else
|
||||
puts "✅ Not overwriting (useruploaded) #{new_filename}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
XRForge.log(" ", logfile)
|
||||
|
||||
rescue Errno::ENOENT
|
||||
puts "File #{filename} not found"
|
||||
rescue JSON::ParserError
|
||||
puts "Error parsing JSON from #{filename}"
|
||||
rescue => e
|
||||
puts "An error occurred: #{e.message}"
|
||||
end
|
||||
|
||||
80
manyfold/root/hook.d/experience_updated/1050-compile-textures.rb
Executable file
80
manyfold/root/hook.d/experience_updated/1050-compile-textures.rb
Executable file
|
|
@ -0,0 +1,80 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'json'
|
||||
require_relative './../../xrforge.rb'
|
||||
|
||||
# Check if a filename is provided
|
||||
if ARGV.length != 1
|
||||
puts "Usage: #{$0} <path/to/experience/somefile.xxx>"
|
||||
exit 1
|
||||
end
|
||||
|
||||
filename = ARGV[0]
|
||||
|
||||
require 'base64'
|
||||
require 'json'
|
||||
|
||||
begin
|
||||
|
||||
# Change the directory
|
||||
dir = File.dirname(filename)
|
||||
Dir.chdir( dir )
|
||||
# Read and parse the JSON file
|
||||
data = JSON.parse( File.read( "datapackage.json" ) )
|
||||
logfile = File.join( File.dirname(filename), ".xrforge/log.txt" )
|
||||
update = false
|
||||
|
||||
data['resources'].each do |resource|
|
||||
ext = File.extname(resource['path'])
|
||||
filenameWithoutExt = File.basename(resource['path'], ext)
|
||||
if ! XRForge::MODEL_EXT.any?( ext )
|
||||
next # skip unknown 3d files
|
||||
end
|
||||
if ! resource['path'].match(/^[a-zA-Z0-9]/)
|
||||
next # skip filenames like '_generated.glb' e.g. (produced by hooks)
|
||||
end
|
||||
|
||||
XRForge.log("✅ compiling textures", logfile)
|
||||
gltf_path = ".xrforge/#{filenameWithoutExt}.gltf"
|
||||
|
||||
# Read and parse the GLTF JSON
|
||||
gltf = JSON.parse(File.read(gltf_path))
|
||||
|
||||
# Ensure images section exists
|
||||
unless gltf['images'] && gltf['images'].is_a?(Array)
|
||||
XRForge.log("✅ No 'images' array found in #{gltf_path}",logfile)
|
||||
next
|
||||
end
|
||||
|
||||
# Iterate through the images array
|
||||
gltf['images'].each_with_index do |img, i|
|
||||
name = img['name']
|
||||
next unless name && !name.empty?
|
||||
|
||||
new_filename = "#{dir}/#{name}.png"
|
||||
|
||||
# move file to modeldirectory (but dont overwrite if user overwrite it)
|
||||
XRForge.log("🤔 checking #{new_filename}",logfile)
|
||||
if File.exist?(new_filename)
|
||||
XRForge.log("✅ importing #{new_filename} -> #{resource['path']}",logfile)
|
||||
img['uri'] = "#{name}.png"
|
||||
update = true
|
||||
end
|
||||
end
|
||||
if update
|
||||
File.write( gltf_path, JSON.pretty_generate(gltf) )
|
||||
XRForge.log("✅ writing #{resource['path']}",logfile)
|
||||
system("assimp export #{gltf_path} #{resource['path']} --embed-textures")
|
||||
end
|
||||
end
|
||||
|
||||
XRForge.log(" ", logfile)
|
||||
|
||||
rescue Errno::ENOENT
|
||||
puts "File #{filename} not found"
|
||||
rescue JSON::ParserError
|
||||
puts "Error parsing JSON from #{filename}"
|
||||
rescue => e
|
||||
puts "An error occurred: #{e.message}"
|
||||
end
|
||||
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'json'
|
||||
require_relative './../../xrforge.rb'
|
||||
|
||||
# Check if a filename is provided
|
||||
if ARGV.length != 1
|
||||
puts "Usage: #{$0} <path/to/experience/somefile.xxx>"
|
||||
exit 1
|
||||
end
|
||||
|
||||
puts "TODO"
|
||||
exit 0
|
||||
|
||||
filename = ARGV[0]
|
||||
|
||||
require 'base64'
|
||||
require 'json'
|
||||
|
||||
# Updates the 'uri' of an image in a GLTF hash when a matching PNG filename is found.
|
||||
#
|
||||
# gltf: a parsed JSON hash from a .gltf file
|
||||
# png_path: path to the PNG file to embed
|
||||
#
|
||||
# returns: true if updated successfully, false if not found
|
||||
def update_gltf_image(gltf, png_path)
|
||||
# Get base name (without extension)
|
||||
name = File.basename(png_path, '.png')
|
||||
|
||||
# Find image entry with the same name
|
||||
image_entry = gltf['images']&.find { |img| img['name'] == name }
|
||||
|
||||
unless image_entry
|
||||
warn "No image named '#{name}' found in GLTF"
|
||||
return false
|
||||
end
|
||||
|
||||
# Read and base64-encode the PNG file
|
||||
data = File.binread(png_path)
|
||||
encoded = Base64.strict_encode64(data)
|
||||
|
||||
# Update the URI field with the base64-encoded PNG data URI
|
||||
image_entry['uri'] = "data:image/png;base64,#{encoded}"
|
||||
|
||||
puts "Updated image '#{name}' in GLTF"
|
||||
true
|
||||
end
|
||||
|
||||
begin
|
||||
|
||||
# Change the directory
|
||||
dir = File.dirname(filename)
|
||||
Dir.chdir( File.dirname(filename) )
|
||||
# Read and parse the JSON file
|
||||
data = JSON.parse( File.read( "datapackage.json" ) )
|
||||
|
||||
ext = File.extname(filename)
|
||||
filenameWithoutExt = File.basename(filename, ext)
|
||||
|
||||
if ! XRForge::MODEL_EXT.any?( ext )
|
||||
exit(0) # not a 3d file
|
||||
end
|
||||
|
||||
logfile = File.join( File.dirname(filename), ".xrforge/log.txt" )
|
||||
XRForge.log("✅ unpacking textures", logfile)
|
||||
gltf_path = ".xrforge/#{filenameWithoutExt}.gltf"
|
||||
system("assimp export #{filename} #{gltf_path}")
|
||||
system("assimp extract #{filename} | sed 's|/.*/||g'")
|
||||
|
||||
# Read and parse the GLTF JSON
|
||||
gltf = JSON.parse(File.read(gltf_path))
|
||||
|
||||
# Ensure images section exists
|
||||
unless gltf['images'] && gltf['images'].is_a?(Array)
|
||||
abort("No 'images' array found in #{gltf_path}")
|
||||
end
|
||||
|
||||
# Iterate through the images array
|
||||
gltf['images'].each_with_index do |img, i|
|
||||
name = img['name']
|
||||
next unless name && !name.empty?
|
||||
|
||||
old_filename = "website_img#{i}.png"
|
||||
new_filename = "#{name}.png"
|
||||
|
||||
if File.exist?(old_filename)
|
||||
XRForge.log("✅ Renaming #{old_filename} -> #{new_filename}", logfile)
|
||||
File.rename(old_filename, new_filename)
|
||||
end
|
||||
end
|
||||
|
||||
XRForge.log(" ", logfile)
|
||||
|
||||
rescue Errno::ENOENT
|
||||
puts "File #{filename} not found"
|
||||
rescue JSON::ParserError
|
||||
puts "Error parsing JSON from #{filename}"
|
||||
rescue => e
|
||||
puts "An error occurred: #{e.message}"
|
||||
end
|
||||
|
||||
|
|
@ -49,10 +49,12 @@ begin
|
|||
if model_file
|
||||
XRForge.log("✅ Final model file: '#{model_file}'", logfile)
|
||||
# update datapackage
|
||||
data['main'] = model_file
|
||||
if ! data['keywords'].include?('xrfragments')
|
||||
data['keywords'].push('xrfragments')
|
||||
File.write("datapackage.json", JSON.pretty_generate(data) )
|
||||
end
|
||||
File.write("datapackage.json", JSON.pretty_generate(data) )
|
||||
system("assimp export #{model_file} .xrforge/scene.gltf")
|
||||
else
|
||||
XRForge.log("❌ No suitable 3D file found for XR Fragments-compatible experience", logfile)
|
||||
# update datapackage
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ begin
|
|||
data = JSON.parse( File.read( "datapackage.json" ) )
|
||||
logfile = File.join( File.dirname(filename), ".xrforge/log.txt" )
|
||||
|
||||
data['keywords'].any? do |tag|
|
||||
if tag.match?(/@.*@.*\./) # scan for activitypub handle (@foo@mastodon.online e.g.)
|
||||
data['keywords'].each do |tag|
|
||||
if tag.match?(/^@.*@.*\./) # scan for activitypub handle (@foo@mastodon.online e.g.)
|
||||
generate(tag,filename,dir,data,logfile)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,17 +3,22 @@ test -n "$5" || { echo "usage: ./mastodon-post.sh <text> <title> <link> <handle>
|
|||
|
||||
out="$5"
|
||||
tmpdir=/tmp/.mastodon-post
|
||||
outdir="$(dirname "$out")"
|
||||
mydir="$(dirname $(readlink -f $0))"
|
||||
bgfile="$outdir"/mastodon-post-bg.png
|
||||
cd $mydir
|
||||
|
||||
set -x
|
||||
# create tmp workspace
|
||||
test -d $tmpdir && rm -rf $tmpdir
|
||||
mkdir $tmpdir
|
||||
cp * $tmpdir/.
|
||||
# use template PNG from modeldir
|
||||
test -f "$bgfile" || cp $tmpdir/mastodon-post-bg.png "$bgfile"
|
||||
cp "$bgfile" $tmpdir/.
|
||||
rm $tmpdir/mastodon-post.png # IMPORTANT: prevent newer/older imagemagick -clobber (non)existence
|
||||
|
||||
set -x
|
||||
magick $tmpdir/mastodon-post-bg.png \
|
||||
magick "$bgfile" \
|
||||
\( -size 580x -background none -pointsize 32 -interline-spacing 10 -fill \#FFF -font Montserrat-SemiBold.ttf "caption:$1" \) \
|
||||
-gravity center -composite \
|
||||
-pointsize 20 \
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue