From 811817c14a10f7b895416c2d5ae95d4a7f13b146 Mon Sep 17 00:00:00 2001 From: spelufo Date: Wed, 24 Apr 2024 10:19:50 -0300 Subject: [PATCH 1/4] Read PLY normals. --- src/io/ply.jl | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/io/ply.jl b/src/io/ply.jl index 1889422..d4c22ed 100644 --- a/src/io/ply.jl +++ b/src/io/ply.jl @@ -1,6 +1,7 @@ function save(f::Stream{format"PLY_BINARY"}, msh::AbstractMesh) io = stream(f) points = decompose(Point{3, Float32}, msh) + point_normals = normals(msh) faces = decompose(GLTriangleFace, msh) n_points = length(points) @@ -11,12 +12,23 @@ function save(f::Stream{format"PLY_BINARY"}, msh::AbstractMesh) write(io, "format binary_little_endian 1.0\n") write(io, "element vertex $n_points\n") write(io, "property float x\nproperty float y\nproperty float z\n") + if !isnothing(point_normals) + write(io, "property float nx\nproperty float ny\nproperty float nz\n") + end write(io, "element face $n_faces\n") write(io, "property list uchar int vertex_index\n") write(io, "end_header\n") # write the vertices and faces - write(io, points) + + if isnothing(point_normals) + write(io, points) + else + for (v, n) in zip(points, point_normals) + write(io, v) + write(io, n) + end + end for f in faces write(io, convert(UInt8, 3)) @@ -28,6 +40,7 @@ end function save(f::Stream{format"PLY_ASCII"}, msh::AbstractMesh) io = stream(f) points = coordinates(msh) + point_normals = normals(msh) meshfaces = faces(msh) n_faces = length(points) @@ -38,13 +51,22 @@ function save(f::Stream{format"PLY_ASCII"}, msh::AbstractMesh) write(io, "format ascii 1.0\n") write(io, "element vertex $n_faces\n") write(io, "property float x\nproperty float y\nproperty float z\n") + if !isnothing(point_normals) + write(io, "property float nx\nproperty float ny\nproperty float nz\n") + end write(io, "element face $n_points\n") write(io, "property list uchar int vertex_index\n") write(io, "end_header\n") # write the vertices and faces - for v in points - println(io, join(Point{3, Float32}(v), " ")) + if isnothing(point_normals) + for v in points + println(io, join(Point{3, Float32}(v), " ")) + end + else + for (v, n) in zip(points, point_normals) + println(io, join([v n], " ")) + end end for f in meshfaces println(io, length(f), " ", join(raw.(ZeroIndex.(f)), " ")) @@ -137,4 +159,4 @@ function load(fs::Stream{format"PLY_BINARY"}; facetype=GLTriangleFace, pointtype end return Mesh(points, faces) -end \ No newline at end of file +end From 2a9b83d629e73fdc98baa081344f0b2956afba33 Mon Sep 17 00:00:00 2001 From: spelufo Date: Fri, 10 May 2024 14:24:00 -0300 Subject: [PATCH 2/4] Add normals handling for PLY. --- src/io/ply.jl | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/io/ply.jl b/src/io/ply.jl index d4c22ed..c78cac4 100644 --- a/src/io/ply.jl +++ b/src/io/ply.jl @@ -74,7 +74,7 @@ function save(f::Stream{format"PLY_ASCII"}, msh::AbstractMesh) close(io) end -function load(fs::Stream{format"PLY_ASCII"}; facetype=GLTriangleFace, pointtype=Point3f) +function load(fs::Stream{format"PLY_ASCII"}; facetype=GLTriangleFace, pointtype=Point3f, normalstype=Vec3f) io = stream(fs) n_points = 0 n_faces = 0 @@ -84,9 +84,12 @@ function load(fs::Stream{format"PLY_ASCII"}; facetype=GLTriangleFace, pointtype= # read the header line = readline(io) + has_normals = false while !startswith(line, "end_header") if startswith(line, "element vertex") n_points = parse(Int, split(line)[3]) + elseif startswith(line, "property float nx") + has_normals = true elseif startswith(line, "element face") n_faces = parse(Int, split(line)[3]) elseif startswith(line, "property") @@ -97,12 +100,17 @@ function load(fs::Stream{format"PLY_ASCII"}; facetype=GLTriangleFace, pointtype= faceeltype = eltype(facetype) points = Array{pointtype}(undef, n_points) + point_normals = Array{normalstype}(undef, n_points) #faces = Array{FaceType}(undef, n_faces) faces = facetype[] # read the data for i = 1:n_points - points[i] = pointtype(parse.(eltype(pointtype), split(readline(io)))) # line looks like: "-0.018 0.038 0.086" + numbers = parse.(eltype(pointtype), split(readline(io))) + points[i] = pointtype(numbers[1:3]) + if has_normals && length(numbers) >= 6 + point_normals[i] = pointtype(numbers[4:6]) + end end for i = 1:n_faces @@ -114,10 +122,14 @@ function load(fs::Stream{format"PLY_ASCII"}; facetype=GLTriangleFace, pointtype= push!(faces, convert_simplex(facetype, QuadFace{faceeltype}(reinterpret(ZeroIndex{UInt32}, parse.(UInt32, line))))...) # line looks like: "4 0 1 2 3" end end - return Mesh(points, faces) + if has_normals + return Mesh(meta(points; normals=point_normals), faces) + else + return Mesh(points, faces) + end end -function load(fs::Stream{format"PLY_BINARY"}; facetype=GLTriangleFace, pointtype=Point3f) +function load(fs::Stream{format"PLY_BINARY"}; facetype=GLTriangleFace, pointtype=Point3f, normalstype=Vec3f) io = stream(fs) n_points = 0 n_faces = 0 @@ -127,9 +139,12 @@ function load(fs::Stream{format"PLY_BINARY"}; facetype=GLTriangleFace, pointtype # read the header line = readline(io) + has_normals = false while !startswith(line, "end_header") if startswith(line, "element vertex") n_points = parse(Int, split(line)[3]) + elseif startswith(line, "property float nx") + has_normals = true elseif startswith(line, "element face") n_faces = parse(Int, split(line)[3]) elseif startswith(line, "property") @@ -140,12 +155,16 @@ function load(fs::Stream{format"PLY_BINARY"}; facetype=GLTriangleFace, pointtype faceeltype = eltype(facetype) points = Array{pointtype}(undef, n_points) + point_normals = Array{normalstype}(undef, n_points) #faces = Array{FaceType}(undef, n_faces) faces = facetype[] # read the data for i = 1:n_points points[i] = pointtype(read(io, Float32), read(io, Float32), read(io, Float32)) + if has_normals + point_normals[i] = normalstype(read(io, Float32), read(io, Float32), read(io, Float32)) + end end for i = 1:n_faces @@ -158,5 +177,9 @@ function load(fs::Stream{format"PLY_BINARY"}; facetype=GLTriangleFace, pointtype end end - return Mesh(points, faces) + if has_normals + return Mesh(meta(points; normals=point_normals), faces) + else + return Mesh(points, faces) + end end From c5f49ad21104cc1e289dde6091cfee2ab662f019 Mon Sep 17 00:00:00 2001 From: spelufo Date: Tue, 4 Jun 2024 18:26:42 -0300 Subject: [PATCH 3/4] Support ply files with double as coordinate type. --- src/io/ply.jl | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/io/ply.jl b/src/io/ply.jl index c78cac4..07b9d6c 100644 --- a/src/io/ply.jl +++ b/src/io/ply.jl @@ -88,7 +88,7 @@ function load(fs::Stream{format"PLY_ASCII"}; facetype=GLTriangleFace, pointtype= while !startswith(line, "end_header") if startswith(line, "element vertex") n_points = parse(Int, split(line)[3]) - elseif startswith(line, "property float nx") + elseif startswith(line, "property float nx") || startswith(line, "property double nx") has_normals = true elseif startswith(line, "element face") n_faces = parse(Int, split(line)[3]) @@ -140,11 +140,29 @@ function load(fs::Stream{format"PLY_BINARY"}; facetype=GLTriangleFace, pointtype line = readline(io) has_normals = false + has_doubles = Float32 + xtype = Float32; ytype = Float32; ztype = Float32 + nxtype = Float32; nytype = Float32; nztype = Float32 while !startswith(line, "end_header") if startswith(line, "element vertex") n_points = parse(Int, split(line)[3]) - elseif startswith(line, "property float nx") + elseif startswith(line, "property double x") + xtype = Float64 + elseif startswith(line, "property double y") + ytype = Float64 + elseif startswith(line, "property double z") + ztype = Float64 + elseif startswith(line, "property float n") has_normals = true + elseif startswith(line, "property double nx") + has_normals = true + nxtype = Float64 + elseif startswith(line, "property double ny") + has_normals = true + nytype = Float64 + elseif startswith(line, "property double nz") + has_normals = true + nztype = Float64 elseif startswith(line, "element face") n_faces = parse(Int, split(line)[3]) elseif startswith(line, "property") @@ -161,9 +179,9 @@ function load(fs::Stream{format"PLY_BINARY"}; facetype=GLTriangleFace, pointtype # read the data for i = 1:n_points - points[i] = pointtype(read(io, Float32), read(io, Float32), read(io, Float32)) + points[i] = pointtype(read(io, xtype), read(io, ytype), read(io, ztype)) if has_normals - point_normals[i] = normalstype(read(io, Float32), read(io, Float32), read(io, Float32)) + point_normals[i] = normalstype(read(io, nxtype), read(io, nytype), read(io, nztype)) end end From 413a70a8d394fe3b1769ca22eb239a0471069977 Mon Sep 17 00:00:00 2001 From: spelufo Date: Wed, 5 Jun 2024 18:26:25 -0300 Subject: [PATCH 4/4] Fix binary ply save. --- src/io/ply.jl | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/io/ply.jl b/src/io/ply.jl index 07b9d6c..f4a537e 100644 --- a/src/io/ply.jl +++ b/src/io/ply.jl @@ -1,11 +1,10 @@ function save(f::Stream{format"PLY_BINARY"}, msh::AbstractMesh) io = stream(f) - points = decompose(Point{3, Float32}, msh) + points = coordinates(msh) point_normals = normals(msh) - faces = decompose(GLTriangleFace, msh) - + meshfaces = faces(msh) n_points = length(points) - n_faces = length(faces) + n_faces = length(meshfaces) # write the header write(io, "ply\n") @@ -30,9 +29,9 @@ function save(f::Stream{format"PLY_BINARY"}, msh::AbstractMesh) end end - for f in faces - write(io, convert(UInt8, 3)) - write(io, raw.(f)...) + for f in meshfaces + write(io, convert(UInt8, length(f))) + write(io, raw.(ZeroIndex.(f))...) end close(io) end @@ -42,19 +41,18 @@ function save(f::Stream{format"PLY_ASCII"}, msh::AbstractMesh) points = coordinates(msh) point_normals = normals(msh) meshfaces = faces(msh) - - n_faces = length(points) - n_points = length(meshfaces) + n_points = length(points) + n_faces = length(meshfaces) # write the header write(io, "ply\n") write(io, "format ascii 1.0\n") - write(io, "element vertex $n_faces\n") + write(io, "element vertex $n_points\n") write(io, "property float x\nproperty float y\nproperty float z\n") if !isnothing(point_normals) write(io, "property float nx\nproperty float ny\nproperty float nz\n") end - write(io, "element face $n_points\n") + write(io, "element face $n_faces\n") write(io, "property list uchar int vertex_index\n") write(io, "end_header\n")