Skip to content

Commit

Permalink
update MeshIO
Browse files Browse the repository at this point in the history
  • Loading branch information
ffreyer committed Sep 6, 2024
1 parent b7739eb commit 7658f18
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 57 deletions.
12 changes: 5 additions & 7 deletions src/io/gts.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@ function parseGtsLine( s::AbstractString, C, T=eltype(C) )
end
end

function load( st::Stream{format"GTS"}, MeshType=GLNormalMesh )
function load( st::Stream{format"GTS"}; facetype=GLTriangleFace, pointtype=Point)
io = stream(st)
head = readline( io )
FT = facetype(MeshType)
VT = vertextype(MeshType)

nVertices, nEdges, nFacets = parseGtsLine( head, Tuple{Int,Int,Int} )
iV = iE = iF = 1
vertices = Vector{VT}(undef, nVertices)
vertices = Vector{pointtype}(undef, nVertices)
edges = Vector{Vector{Int}}(undef, nEdges)
facets = Vector{Vector{Int}}(undef, nFacets)
for full_line::String in eachline(io)
Expand All @@ -30,7 +28,7 @@ function load( st::Stream{format"GTS"}, MeshType=GLNormalMesh )

if !startswith(line, "#") && !isempty(line) && !all(iscntrl, line) #ignore comments
if iV <= nVertices
vertices[iV] = parseGtsLine( line, VT )
vertices[iV] = parseGtsLine( line, pointtype )
iV += 1
elseif iV > nVertices && iE <= nEdges
edges[iE] = parseGtsLine( line, Array{Int} )
Expand All @@ -41,8 +39,8 @@ function load( st::Stream{format"GTS"}, MeshType=GLNormalMesh )
end # if
end # if
end # for
faces = [ FT( union( edges[facets[i][1]], edges[facets[i][2]], edges[facets[i][3]] ) ) for i in 1:length(facets) ] # orientation not guaranteed
return MeshType( vertices, faces )
faces = [ facetype( union( edges[facets[i][1]], edges[facets[i][2]], edges[facets[i][3]] ) ) for i in 1:length(facets) ] # orientation not guaranteed
return Mesh( vertices, faces )
end

function save( st::Stream{format"GTS"}, mesh::AbstractMesh )
Expand Down
12 changes: 6 additions & 6 deletions src/io/ifs.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function load(fs::Stream{format"IFS"}, MeshType = GLNormalMesh)
function load(fs::Stream{format"IFS"}; facetype=GLTriangleFace, pointtype=Point3f)
io = stream(fs)
function str()
n = read(io, UInt32)
Expand All @@ -11,15 +11,15 @@ function load(fs::Stream{format"IFS"}, MeshType = GLNormalMesh)
end
nverts = read(io, UInt32)
verts_float = read(io, Float32, nverts * 3)
verts = reinterpret(Point3f0, verts_float)
verts = reinterpret(pointtype, verts_float)
tris = str()
if tris != "TRIANGLES\0"
error("$(filename(fs)) does not seem to be of format IFS")
end
nfaces = read(io, UInt32)
faces_int = read(io, UInt32, nfaces * 3)
faces = reinterpret(GLTriangle, faces_int)
MeshType(vertices = verts, faces = faces)
faces = reinterpret(facetype, faces_int)
return GeometryBasics.mesh(vertices = verts, faces = faces)
end

function save(fs::Stream{format"IFS"}, msh::AbstractMesh; meshname = "mesh")
Expand All @@ -29,8 +29,8 @@ function save(fs::Stream{format"IFS"}, msh::AbstractMesh; meshname = "mesh")
write(io, UInt32(length(s0)))
write(io, s0)
end
vts = decompose(Point3f0, msh)
fcs = decompose(GLTriangle, msh)
vts = decompose(Point3f, msh)
fcs = decompose(GLTriangleFace, msh)

# write the header
write0str("IFS")
Expand Down
26 changes: 9 additions & 17 deletions src/io/obj.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
##############################

function load(io::Stream{format"OBJ"}; facetype=GLTriangleFace,
pointtype=Point3f, normaltype=Vec3f, uvtype=Vec2f)
pointtype=Point3f, normaltype=Vec3f, uvtype=Any)

points, v_normals, uv, faces = pointtype[], normaltype[], uvtype[], Any[]
last_command = ""
attrib_type = nothing

for full_line in eachline(stream(io))
# read a line, remove newline and leading/trailing whitespaces
line = strip(chomp(full_line))
Expand Down Expand Up @@ -54,7 +53,7 @@ function load(io::Stream{format"OBJ"}; facetype=GLTriangleFace,
append!(faces, GeometryBasics.UVFace.(pos_faces, uv_faces))
else
normal_faces = triangulated_faces(facetype, getindex.(fs, 3))
append!(faces, GeometryBasics.NormalUVFace.(pos_faces, normal_faces, uv_faces))
append!(faces, GeometryBasics.UVNormalFace.(pos_faces, uv_faces, normal_faces))
end
else
append!(faces, triangulated_faces(facetype, lines))
Expand All @@ -65,22 +64,15 @@ function load(io::Stream{format"OBJ"}; facetype=GLTriangleFace,
end
end

vertex_attributes = Dict{Symbol, Any}()

# TODO: add GeometryBasics convenience for dropping nothing vertex attributes?
if !isempty(v_normals)
vertex_attributes[:normal] = v_normals
end

if !isempty(uv)
vertex_attributes[:uv] = uv
end

# TODO: Can we avoid this conversion?
# Also, is it safe to do? Or can an obj file define different face types for different groups?
faces = convert(Vector{typeof(first(faces))}, faces)

return GeometryBasics.mesh(points, faces, facetype = facetype; vertex_attributes...)
return GeometryBasics.mesh(
points, faces, facetype = facetype;
uv = isempty(uv) ? nothing : uv,
normal = isempty(v_normals) ? nothing : v_normals
)
end

# of form "faces v1 v2 v3 ....""
Expand Down Expand Up @@ -111,7 +103,7 @@ function save(f::Stream{format"OBJ"}, mesh::AbstractMesh)
end
end

if hasproperty(mesh, :normals)
if hasproperty(mesh, :normal)
for n in decompose_normals(mesh)
println(io, "vn ", n[1], " ", n[2], " ", n[3])
end
Expand Down
4 changes: 2 additions & 2 deletions src/io/ply.jl
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ function load(fs::Stream{format"PLY_ASCII"}; facetype=GLTriangleFace, pointtype=
end
end
if has_normals
return Mesh(meta(points; normals=point_normals), faces)
return Mesh(points, faces; normal = point_normals)
else
return Mesh(points, faces)
end
Expand Down Expand Up @@ -194,7 +194,7 @@ function load(fs::Stream{format"PLY_BINARY"}; facetype=GLTriangleFace, pointtype
end

if has_normals
return Mesh(meta(points; normals=point_normals), faces)
return Mesh(points, faces; normal = point_normals)
else
return Mesh(points, faces)
end
Expand Down
36 changes: 11 additions & 25 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ using Test
const tf = joinpath(dirname(@__FILE__), "testfiles")
using MeshIO

using GeometryBasics: GLNormalMesh

function test_face_indices(mesh)
for face in faces(mesh)
for index in face
Expand All @@ -23,6 +25,8 @@ end
]
uvn_mesh = merge(map(uv_normal_mesh, mesh))
mesh = merge(map(triangle_mesh, mesh))
empty!(uvn_mesh.views)
empty!(mesh.views)


mktempdir() do tmpdir
Expand Down Expand Up @@ -54,6 +58,8 @@ end
@test mesh_loaded == uvn_mesh
end
end


@testset "Real world files" begin

@testset "STL" begin
Expand All @@ -67,7 +73,7 @@ end
@test msh isa GLNormalMesh
@test length(faces(msh)) == 828
@test length(coordinates(msh)) == 2484
@test length(msh.normals) == 2484
@test length(normals(msh)) == 2484
@test test_face_indices(msh)

mktempdir() do tmpdir
Expand All @@ -76,7 +82,7 @@ end
@test msh1 isa GLNormalMesh
@test faces(msh) == faces(msh1)
@test coordinates(msh) == coordinates(msh1)
@test msh.normals == msh1.normals
@test normals(msh) == normals(msh1)
end

msh = load(joinpath(tf, "binary_stl_from_solidworks.STL"))
Expand Down Expand Up @@ -172,29 +178,9 @@ end
end
@testset "GTS" begin
# TODO: FileIO upstream
#msh = load(joinpath(tf, "sphere5.gts"))
#@test typeof(msh) == GLNormalMesh
#test_face_indices(msh)
end

@testset "Index remapping" begin
pos_faces = GLTriangleFace[(5, 6, 7), (5, 6, 8), (5, 7, 8)]
normal_faces = GLTriangleFace[(5, 6, 7), (3, 6, 8), (5, 7, 8)]
uv_faces = GLTriangleFace[(1, 2, 3), (4, 2, 5), (1, 3, 1)]

# unique combinations -> new indices
# 551 662 773 534 885 881 1 2 3 4 5 6 (or 0..5 with 0 based indices)
faces, maps = MeshIO.merge_vertex_attribute_indices(pos_faces, normal_faces, uv_faces)

@test length(faces) == 3
@test faces == GLTriangleFace[(1, 2, 3), (4, 2, 5), (1, 3, 6)]

# maps are structured as map[new_index] = old_index, so they grab the
# first/second/third index of the unique combinations above
# maps = (pos_map, normal_map, uv_map)
@test maps[1] == [5, 6, 7, 5, 8, 8]
@test maps[2] == [5, 6, 7, 3, 8, 8]
@test maps[3] == [1, 2, 3, 4, 5, 1]
# msh = load(joinpath(tf, "sphere5.gts"))
# @test typeof(msh) == GLNormalMesh
# test_face_indices(msh)
end
end
end

0 comments on commit 7658f18

Please sign in to comment.