In my JavaScript to Julia port of a 3D slicer example application, some simple way to orient/scale/offset 3D model axes would have been helpful.
The JavaScript version of the application loads a Wavefront 3D object text file that defines all the triangle vertices and the triangle faces of a model of a bunny. As the JavaScript version plots the bunny rotating, it also calculates horizontal cross sections.
The Julia/GLMake/FileIO version of the application load()-ed the bunny object on its side (because that old Wavefront object text file format defined the model with the y-axis as the azimuth but GLMakie apparently expects the z-axis to be the azimuth). I ended up writing the following script to change the azimuth axis, and also change vertex scaling and offsets.
# xobj.jl
# Transform a wavefront 3D object's
# - axis orientations (new y = -old z; new z = old y)
# - scale
# - offsets
function xobj(fn="xbunny.obj", scale=13.,
xOff=0.218413, yOff=-0.01927, zOff=-0.4330287)
# initialize
iLine = 0
i1 = 1
LIM = [Inf -Inf; Inf -Inf; Inf -Inf]
# open output file
open(fn, "w") do io
# for each line of input file
for line in eachline(fn[2:end])
iLine += 1
# if line does not define a vertex
if line[1] != 'v'
println(io, line) # copy it
# else line defines a vertex
else
nChar = length(line)
print(io, "v")
iState = 0
vTmp = 0.
i1 = 3
for iChar = 3:nChar
if isspace(line[iChar]) || iChar==nChar
iState += 1
i2 = iChar==nChar ? iChar : iChar - 1
v = parse(Float32,line[i1:i2])
v *= Float32(scale)
if iState == 1 # x
v += Float32(xOff)
print(io, ' ') # prefix space
print(io, v)
if LIM[1,1] > v
LIM[1,1] = v
end
if LIM[1,2] < v
LIM[1,2] = v
end
elseif iState == 2 # y
vTmp = v
elseif iState == 3 # z
v = -v + Float32(yOff)
print(io, ' ') # prefix space
print(io, v)
if LIM[2,1] > v
LIM[2,1] = v
end
if LIM[2,2] < v
LIM[2,2] = v
end
vTmp += Float32(zOff)
print(io, ' ') # prefix space
println(io, vTmp)
if LIM[3,1] > vTmp
LIM[3,1] = vTmp
end
if LIM[3,2] < vTmp
LIM[3,2] = vTmp
end
break
end
i1 = iChar + 1
end # if character ends a field
end # for each character
end # else line defines a vertex
end # input file
display(LIM)
end # output file
end
With the modified orientation of axes, GLMakie greatly simplifies this 3D slicer example application by using the azimuth parameter to rotate the object, avoiding the JavaScript application’s approach of implementing a rotor and moving a camera. (When I finally get the Julia version’s projective geometric algebra code to calculate the slices, I’ll post the code here.)