I’m trying to port a JavaScript 3D slicer example to Julia. The example loads a 3D model of a bunny (from https://enkimute.github.io/ganja.js/examples/bunny.obj having 5002 triangle faces) and then calculates horizontal cross sections. The JavaScript version scales all the vertex coordinates in the mesh by a factor of 13 while parsing the individual text lines of the bunny object file. The Julia version can parse the whole bunny object file using Makie.FileIO’s load(). A scalar multiplication broadcast works at the level of triangle faces, but I don’t know how to save the multiplication results back into the structure.
julia> using Makie.FileIO
julia> faces = load("bunny.obj");
julia> nFace = length(faces)
5002
julia> typeof(faces)
GeometryBasics.Mesh{3, Float32, GeometryBasics.Ngon{3, Float32, 3, Point{3, Float32}}, GeometryBasics.SimpleFaceView{3, Float32, 3, GeometryBasics.OffsetInteger{-1, UInt32}, Point{3, Float32}, GeometryBasics.NgonFace{3, GeometryBasics.OffsetInteger{-1, UInt32}}}}
julia> typeof(faces[1]) # 3 vertices of a triangle face
GeometryBasics.Ngon{3, Float32, 3, Point{3, Float32}}
julia> typeof(faces[1][1]) # 3 coordinates of a vertex
Point{3, Float32}
julia> typeof(faces[1][1][1]) # a coordinate
Float32
julia> faces[1]
Triangle(Float32[-0.089491, 0.143926, 0.0124885], Float32[-0.0865619, 0.142492, 0.00843268], Float32[-0.0896984, 0.139713, 0.0137748])
julia> faces[1] .* 13
3-element Vector{Point{3, Float32}}:
[-1.163383, 1.871038, 0.1623505]
[-1.1253047, 1.852396, 0.10962484]
[-1.1660792, 1.816269, 0.1790724]
julia> faces[1] = faces[1] .* 13
ERROR: CanonicalIndexError: setindex! not defined for GeometryBasics.Mesh{3, Float32, GeometryBasics.Ngon{3, Float32, 3, Point{3, Float32}}, GeometryBasics.SimpleFaceView{3, Float32, 3, GeometryBasics.OffsetInteger{-1, UInt32}, Point{3, Float32}, GeometryBasics.NgonFace{3, GeometryBasics.OffsetInteger{-1, UInt32}}}}
Stacktrace:
[1] error_if_canonical_setindex(#unused#::IndexCartesian, A::GeometryBasics.Mesh{3, Float32, GeometryBasics.Ngon{3, Float32, 3, Point{3, Float32}}, GeometryBasics.SimpleFaceView{3, Float32, 3, GeometryBasics.OffsetInteger{-1, UInt32}, Point{3, Float32}, GeometryBasics.NgonFace{3, GeometryBasics.OffsetInteger{-1, UInt32}}}}, #unused#::Int64)
@ Base .\abstractarray.jl:1354
[2] setindex!(A::GeometryBasics.Mesh{3, Float32, GeometryBasics.Ngon{3, Float32, 3, Point{3, Float32}}, GeometryBasics.SimpleFaceView{3, Float32, 3, GeometryBasics.OffsetInteger{-1, UInt32}, Point{3, Float32}, GeometryBasics.NgonFace{3, GeometryBasics.OffsetInteger{-1, UInt32}}}}, v::Vector{Point{3, Float32}}, I::Int64)
@ Base .\abstractarray.jl:1343
[3] top-level scope
@ REPL[17]:1
julia>
I tried using StaticArrays and declaring faces::MArray = load(“bunny.obj”) but got the following error and hint, but I don’t know how to apply the hint to such a complex structure. Any suggestions?
ERROR: LoadError: The size of type `MArray` is not known.
If you were trying to construct (or `convert` to) a `StaticArray` you
may need to add the size explicitly as a type parameter so its size is
inferrable to the Julia compiler (or performance would be terrible). For
example, you might try
m = zeros(3,3)
SMatrix(m) # this error
SMatrix{3,3}(m) # correct - size is inferrable
SArray{Tuple{3,3}}(m) # correct, note Tuple{3,3}
Stacktrace:
[1] error(s::String)
@ Base .\error.jl:35
[2] missing_size_error(#unused#::Type{MArray})
@ StaticArraysCore C:\Users\gsgm2\.julia\packages\StaticArraysCore\U2Z1K\src\StaticArraysCore.jl:475
[3] Size(#unused#::Type{MArray})
@ StaticArraysCore C:\Users\gsgm2\.julia\packages\StaticArraysCore\U2Z1K\src\StaticArraysCore.jl:491
[4] length(a::Type{MArray})
@ StaticArrays C:\Users\gsgm2\.julia\packages\StaticArrays\jA1zK\src\abstractarray.jl:2
[5] convert(#unused#::Type{MArray}, a::GeometryBasics.Mesh{3, Float32, GeometryBasics.Ngon{3, Float32, 3, Point{3, Float32}}, GeometryBasics.SimpleFaceView{3, Float32, 3, GeometryBasics.OffsetInteger{-1, UInt32}, Point{3, Float32}, GeometryBasics.NgonFace{3, GeometryBasics.OffsetInteger{-1, UInt32}}}})
@ StaticArrays C:\Users\gsgm2\.julia\packages\StaticArrays\jA1zK\src\convert.jl:195
[6] top-level scope
@ C:\dev\olarth\PGA\ripga2d3d\slicing.jl:9
[7] include(fname::String)
@ Base.MainInclude .\client.jl:476
[8] top-level scope
@ REPL[1]:1
in expression starting at C:\dev\olarth\PGA\ripga2d3d\slicing.jl:9