Skip to content

Commit

Permalink
ply reader vector 4 fallback to vector3 when W component missing
Browse files Browse the repository at this point in the history
  • Loading branch information
EliCDavis committed Dec 22, 2024
1 parent e8d2daa commit 6d3fa1b
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 14 deletions.
3 changes: 3 additions & 0 deletions formats/ply/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,20 +252,23 @@ var defaultReader MeshReader = MeshReader{
},
&Vector4PropertyReader{
ModelAttribute: modeling.ColorAttribute,
IgnorableW: true,
PlyPropertyX: "red",
PlyPropertyY: "green",
PlyPropertyZ: "blue",
PlyPropertyW: "alpha",
},
&Vector4PropertyReader{
ModelAttribute: modeling.ColorAttribute,
IgnorableW: true,
PlyPropertyX: "r",
PlyPropertyY: "g",
PlyPropertyZ: "b",
PlyPropertyW: "a",
},
&Vector4PropertyReader{
ModelAttribute: modeling.ColorAttribute,
IgnorableW: true,
PlyPropertyX: "diffuse_red",
PlyPropertyY: "diffuse_green",
PlyPropertyZ: "diffuse_blue",
Expand Down
70 changes: 70 additions & 0 deletions formats/ply/reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,73 @@ end_header
assert.Equal(t, 10., opacityData.At(0))
assert.Equal(t, 20., opacityData.At(1))
}

func TestMeshReader_ASCII_Vector4FallsbackToVector3WhenWMissing(t *testing.T) {
// ARRANGE ================================================================
plyFile := `ply
format ascii 1.0
element vertex 2
property uchar r
property uchar g
property uchar b
end_header
1 2 3
4 5 6
`

// ACT ====================================================================
mesh, err := ply.ReadMesh(strings.NewReader(plyFile))

// ASSERT =================================================================
assert.NoError(t, err)
assert.True(t, mesh.HasFloat3Attribute(modeling.ColorAttribute), "mesh should have color attribute")

colorData := mesh.Float3Attribute(modeling.ColorAttribute)
assert.Equal(t, 2, colorData.Len())
assert.Equal(t, vector3.New(1./255., 2./255., 3./255.), colorData.At(0))
assert.Equal(t, vector3.New(4./255., 5./255., 6./255.), colorData.At(1))

}

func TestMeshReader_Binary_Vector4FallsbackToVector3WhenWMissing(t *testing.T) {
// ARRANGE ================================================================
header := ply.Header{
Format: ply.BinaryBigEndian,
Elements: []ply.Element{{
Name: ply.VertexElementName,
Count: 2,
Properties: []ply.Property{
ply.ScalarProperty{PropertyName: "r", Type: ply.UChar},
ply.ScalarProperty{PropertyName: "g", Type: ply.UChar},
ply.ScalarProperty{PropertyName: "b", Type: ply.UChar},
},
}},
}

type Point struct {
r byte
g byte
b byte
}

inputData := []Point{
{r: 1, g: 2, b: 3},
{r: 4, g: 5, b: 6},
}

buf := &bytes.Buffer{}
header.Write(buf)
binary.Write(buf, binary.BigEndian, inputData)

// ACT ====================================================================
mesh, err := ply.ReadMesh(buf)

// ASSERT =================================================================
assert.NoError(t, err)
assert.True(t, mesh.HasFloat3Attribute(modeling.ColorAttribute), "mesh should have color attribute")

colorData := mesh.Float3Attribute(modeling.ColorAttribute)
assert.Equal(t, 2, colorData.Len())
assert.Equal(t, vector3.New(1./255., 2./255., 3./255.), colorData.At(0))
assert.Equal(t, vector3.New(4./255., 5./255., 6./255.), colorData.At(1))
}
47 changes: 33 additions & 14 deletions formats/ply/reader_vector4.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ type Vector4PropertyReader struct {
PlyPropertyY string
PlyPropertyZ string
PlyPropertyW string
IgnorableW bool
}

func (v3pr Vector4PropertyReader) buildBinary(element Element, endian binary.ByteOrder) binaryPropertyReader {
func (v4pr Vector4PropertyReader) buildBinary(element Element, endian binary.ByteOrder) binaryPropertyReader {
totalSize := 0
xOffset := -1
yOffset := -1
Expand All @@ -28,7 +29,7 @@ func (v3pr Vector4PropertyReader) buildBinary(element Element, endian binary.Byt
for _, prop := range element.Properties {
scalar := prop.(ScalarProperty)

if scalar.PropertyName == v3pr.PlyPropertyX {
if scalar.PropertyName == v4pr.PlyPropertyX {
xOffset = totalSize
if string(scalarType) == "" {
scalarType = scalar.Type
Expand All @@ -40,7 +41,7 @@ func (v3pr Vector4PropertyReader) buildBinary(element Element, endian binary.Byt
}
}

if scalar.PropertyName == v3pr.PlyPropertyY {
if scalar.PropertyName == v4pr.PlyPropertyY {
yOffset = totalSize

if string(scalarType) == "" {
Expand All @@ -53,7 +54,7 @@ func (v3pr Vector4PropertyReader) buildBinary(element Element, endian binary.Byt
}
}

if scalar.PropertyName == v3pr.PlyPropertyZ {
if scalar.PropertyName == v4pr.PlyPropertyZ {
zOffset = totalSize

if string(scalarType) == "" {
Expand All @@ -66,7 +67,7 @@ func (v3pr Vector4PropertyReader) buildBinary(element Element, endian binary.Byt
}
}

if scalar.PropertyName == v3pr.PlyPropertyW {
if scalar.PropertyName == v4pr.PlyPropertyW {
wOffset = totalSize
scalarType = scalar.Type

Expand All @@ -83,23 +84,32 @@ func (v3pr Vector4PropertyReader) buildBinary(element Element, endian binary.Byt
totalSize += scalar.Size()
}

if xOffset > -1 && yOffset > -1 && zOffset > -1 {
if xOffset > -1 && yOffset > -1 && zOffset > -1 && wOffset > -1 {
return &builtVector4PropertyReader{
arr: make([]vector4.Float64, element.Count),
xOffset: xOffset,
yOffset: yOffset,
zOffset: zOffset,
wOffset: wOffset,
modelAttribute: v3pr.ModelAttribute,
modelAttribute: v4pr.ModelAttribute,
scalarType: scalarType,
endian: endian,
}
}

if xOffset > -1 && yOffset > -1 && zOffset > -1 && v4pr.IgnorableW {
return Vector3PropertyReader{
ModelAttribute: v4pr.ModelAttribute,
PlyPropertyX: v4pr.PlyPropertyX,
PlyPropertyY: v4pr.PlyPropertyY,
PlyPropertyZ: v4pr.PlyPropertyZ,
}.buildBinary(element, endian)
}

return nil
}

func (v3pr Vector4PropertyReader) buildAscii(element Element) asciiPropertyReader {
func (v4pr Vector4PropertyReader) buildAscii(element Element) asciiPropertyReader {
xOffset := -1
yOffset := -1
zOffset := -1
Expand All @@ -108,7 +118,7 @@ func (v3pr Vector4PropertyReader) buildAscii(element Element) asciiPropertyReade
for i, prop := range element.Properties {
scalar := prop.(ScalarProperty)

if scalar.PropertyName == v3pr.PlyPropertyX {
if scalar.PropertyName == v4pr.PlyPropertyX {
xOffset = i
if string(scalarType) == "" {
scalarType = scalar.Type
Expand All @@ -120,7 +130,7 @@ func (v3pr Vector4PropertyReader) buildAscii(element Element) asciiPropertyReade
}
}

if scalar.PropertyName == v3pr.PlyPropertyY {
if scalar.PropertyName == v4pr.PlyPropertyY {
yOffset = i

if string(scalarType) == "" {
Expand All @@ -133,7 +143,7 @@ func (v3pr Vector4PropertyReader) buildAscii(element Element) asciiPropertyReade
}
}

if scalar.PropertyName == v3pr.PlyPropertyZ {
if scalar.PropertyName == v4pr.PlyPropertyZ {
zOffset = i

if string(scalarType) == "" {
Expand All @@ -146,7 +156,7 @@ func (v3pr Vector4PropertyReader) buildAscii(element Element) asciiPropertyReade
}
}

if scalar.PropertyName == v3pr.PlyPropertyW {
if scalar.PropertyName == v4pr.PlyPropertyW {
wOffset = i

if string(scalarType) == "" {
Expand All @@ -160,18 +170,27 @@ func (v3pr Vector4PropertyReader) buildAscii(element Element) asciiPropertyReade
}
}

if xOffset > -1 && yOffset > -1 && zOffset > -1 {
if xOffset > -1 && yOffset > -1 && zOffset > -1 && wOffset > -1 {
return &builtAsciiVector4PropertyReader{
arr: make([]vector4.Float64, element.Count),
xOffset: xOffset,
yOffset: yOffset,
zOffset: zOffset,
wOffset: wOffset,
modelAttribute: v3pr.ModelAttribute,
modelAttribute: v4pr.ModelAttribute,
scalarType: scalarType,
}
}

if xOffset > -1 && yOffset > -1 && zOffset > -1 && v4pr.IgnorableW {
return Vector3PropertyReader{
ModelAttribute: v4pr.ModelAttribute,
PlyPropertyX: v4pr.PlyPropertyX,
PlyPropertyY: v4pr.PlyPropertyY,
PlyPropertyZ: v4pr.PlyPropertyZ,
}.buildAscii(element)
}

return nil
}

Expand Down

0 comments on commit 6d3fa1b

Please sign in to comment.