Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ply normals #91

Merged
merged 4 commits into from
Jun 14, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 83 additions & 22 deletions src/io/ply.jl
Original file line number Diff line number Diff line change
@@ -1,58 +1,78 @@
function save(f::Stream{format"PLY_BINARY"}, msh::AbstractMesh)
io = stream(f)
points = decompose(Point{3, Float32}, msh)
faces = decompose(GLTriangleFace, msh)

points = coordinates(msh)
point_normals = normals(msh)
meshfaces = faces(msh)
n_points = length(points)
n_faces = length(faces)
n_faces = length(meshfaces)

# write the header
write(io, "ply\n")
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")

Check warning on line 15 in src/io/ply.jl

View check run for this annotation

Codecov / codecov/patch

src/io/ply.jl#L15

Added line #L15 was not covered by tests
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)

for f in faces
write(io, convert(UInt8, 3))
write(io, raw.(f)...)
if isnothing(point_normals)
write(io, points)
else
for (v, n) in zip(points, point_normals)
write(io, v)
write(io, n)

Check warning on line 28 in src/io/ply.jl

View check run for this annotation

Codecov / codecov/patch

src/io/ply.jl#L26-L28

Added lines #L26 - L28 were not covered by tests
end
end

for f in meshfaces
write(io, convert(UInt8, length(f)))
write(io, raw.(ZeroIndex.(f))...)
end
close(io)
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)
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")
write(io, "element face $n_points\n")
if !isnothing(point_normals)
write(io, "property float nx\nproperty float ny\nproperty float nz\n")

Check warning on line 53 in src/io/ply.jl

View check run for this annotation

Codecov / codecov/patch

src/io/ply.jl#L53

Added line #L53 was not covered by tests
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
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], " "))

Check warning on line 66 in src/io/ply.jl

View check run for this annotation

Codecov / codecov/patch

src/io/ply.jl#L65-L66

Added lines #L65 - L66 were not covered by tests
end
end
for f in meshfaces
println(io, length(f), " ", join(raw.(ZeroIndex.(f)), " "))
end
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
Expand All @@ -62,9 +82,12 @@
# 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") || startswith(line, "property double nx")
has_normals = true
elseif startswith(line, "element face")
n_faces = parse(Int, split(line)[3])
elseif startswith(line, "property")
Expand All @@ -75,12 +98,17 @@

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
Expand All @@ -92,10 +120,14 @@
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
Expand All @@ -105,9 +137,30 @@
# read the header
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 double x")
xtype = Float64

Check warning on line 148 in src/io/ply.jl

View check run for this annotation

Codecov / codecov/patch

src/io/ply.jl#L148

Added line #L148 was not covered by tests
elseif startswith(line, "property double y")
ytype = Float64

Check warning on line 150 in src/io/ply.jl

View check run for this annotation

Codecov / codecov/patch

src/io/ply.jl#L150

Added line #L150 was not covered by tests
elseif startswith(line, "property double z")
ztype = Float64

Check warning on line 152 in src/io/ply.jl

View check run for this annotation

Codecov / codecov/patch

src/io/ply.jl#L152

Added line #L152 was not covered by tests
elseif startswith(line, "property float n")
has_normals = true

Check warning on line 154 in src/io/ply.jl

View check run for this annotation

Codecov / codecov/patch

src/io/ply.jl#L154

Added line #L154 was not covered by tests
elseif startswith(line, "property double nx")
has_normals = true
nxtype = Float64

Check warning on line 157 in src/io/ply.jl

View check run for this annotation

Codecov / codecov/patch

src/io/ply.jl#L156-L157

Added lines #L156 - L157 were not covered by tests
elseif startswith(line, "property double ny")
has_normals = true
nytype = Float64

Check warning on line 160 in src/io/ply.jl

View check run for this annotation

Codecov / codecov/patch

src/io/ply.jl#L159-L160

Added lines #L159 - L160 were not covered by tests
elseif startswith(line, "property double nz")
has_normals = true
nztype = Float64

Check warning on line 163 in src/io/ply.jl

View check run for this annotation

Codecov / codecov/patch

src/io/ply.jl#L162-L163

Added lines #L162 - L163 were not covered by tests
elseif startswith(line, "element face")
n_faces = parse(Int, split(line)[3])
elseif startswith(line, "property")
Expand All @@ -118,12 +171,16 @@

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))
points[i] = pointtype(read(io, xtype), read(io, ytype), read(io, ztype))
if has_normals
point_normals[i] = normalstype(read(io, nxtype), read(io, nytype), read(io, nztype))
end
end

for i = 1:n_faces
Expand All @@ -136,5 +193,9 @@
end
end

return Mesh(points, faces)
end
if has_normals
return Mesh(meta(points; normals=point_normals), faces)

Check warning on line 197 in src/io/ply.jl

View check run for this annotation

Codecov / codecov/patch

src/io/ply.jl#L197

Added line #L197 was not covered by tests
else
return Mesh(points, faces)
end
end