changeset 5695:ef80748ae4f3 sr-v2

Finish deserializing v2 of the mesh index.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 12 Feb 2024 21:23:55 +0100
parents 3bc15e38c7e8
children a6dc68389c37
files pkg/mesh/meshserialize.go pkg/mesh/meshserialize_v1.go pkg/mesh/meshserialize_v2.go
diffstat 3 files changed, 94 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/pkg/mesh/meshserialize.go	Mon Feb 12 14:43:31 2024 +0100
+++ b/pkg/mesh/meshserialize.go	Mon Feb 12 21:23:55 2024 +0100
@@ -24,10 +24,13 @@
 	"gemma.intevation.de/gemma/pkg/log"
 )
 
-const Version = 1
+// Version is current version of the format the mesh index is stored in.
+const Version = 2
 
+// magicHeader is a magic header to tell if the data blob is a mesh index.
 const magicHeader = "SR3D"
 
+// coalesceVersion returns the most recent version if version is less or equal zero.
 func coalesceVersion(version int) int {
 	if version > 0 {
 		return version
@@ -35,6 +38,8 @@
 	return Version
 }
 
+// OptimizeForSerialization apply version specific storage optimizations
+// before serialization.
 func (s *STRTree) OptimizeForSerialization(version int) {
 	version = coalesceVersion(version)
 	if version == 2 {
@@ -44,22 +49,18 @@
 
 // Bytes serializes this tree to a byte slice.
 func (s *STRTree) Bytes(version int) ([]byte, int, error) {
-
 	var buf bytes.Buffer
 	w, err := gzip.NewWriterLevel(&buf, gzip.BestSpeed)
 	if err != nil {
 		return nil, 0, err
 	}
-
 	version = coalesceVersion(version)
 	if err := s.serializeVn(w, version); err != nil {
 		return nil, 0, err
 	}
-
 	if err := w.Close(); err != nil {
 		return nil, 0, err
 	}
-
 	return buf.Bytes(), version, nil
 }
 
@@ -85,12 +86,10 @@
 }
 
 func (s *STRTree) deserialize(r *bufio.Reader, version int) error {
-
 	header, err := r.Peek(8)
 	if err != nil {
 		return err
 	}
-
 	if bytes.HasPrefix(header, []byte(magicHeader)) {
 		realVersion := int(binary.LittleEndian.Uint32(header[4:]))
 		if realVersion != version {
@@ -103,7 +102,6 @@
 		}
 		return s.deserializeVn(r, realVersion)
 	}
-
 	return s.deserializeV1(r)
 }
 
@@ -119,7 +117,7 @@
 }
 
 // serializer is a generic function to apply a chain of
-// serializer/deserializer functions to an object given a reader.
+// serializer/deserializer functions to an object given a reader or writer.
 func serializer[T, S any](
 	s S,
 	t T,
--- a/pkg/mesh/meshserialize_v1.go	Mon Feb 12 14:43:31 2024 +0100
+++ b/pkg/mesh/meshserialize_v1.go	Mon Feb 12 21:23:55 2024 +0100
@@ -86,7 +86,7 @@
 	return serializer(w, t,
 		(*Tin).serializeEPSG,
 		(*Tin).serializeExtent,
-		(*Tin).serializeV1,
+		(*Tin).serializeVerticesV1,
 		(*Tin).serializeTrianglesV1,
 	)
 }
--- a/pkg/mesh/meshserialize_v2.go	Mon Feb 12 14:43:31 2024 +0100
+++ b/pkg/mesh/meshserialize_v2.go	Mon Feb 12 21:23:55 2024 +0100
@@ -17,7 +17,6 @@
 	"bufio"
 	"cmp"
 	"encoding/binary"
-	"errors"
 	"io"
 	"math"
 	"slices"
@@ -164,13 +163,48 @@
 }
 
 func (s *STRTree) deserializeBBoxesV2(r *bufio.Reader) error {
-	// TODO: implement me!
-	return errors.New("not implemented, yet")
+	var numBoxes uint32
+	if err := binary.Read(r, binary.LittleEndian, &numBoxes); err != nil {
+		return err
+	}
+	boxes := make([]Box2D, numBoxes)
+	s.bboxes = boxes
+	var (
+		m      = s.Min()
+		x1     = func(b *Box2D, v float64) { b.X1 = v + m.X }
+		y1     = func(b *Box2D, v float64) { b.Y1 = v + m.Y }
+		width  = func(b *Box2D, v float64) { b.X2 = b.X1 + v }
+		height = func(b *Box2D, v float64) { b.Y2 = b.Y1 + v }
+	)
+	for _, unproj := range []func(*Box2D, float64){x1, y1, width, height} {
+		invDelta := common.InvDelta()
+		for i := range boxes {
+			v, err := binary.ReadVarint(r)
+			if err != nil {
+				return err
+			}
+			unproj(&boxes[i], unquant(invDelta(v)))
+		}
+	}
+	return nil
 }
 
 func (s *STRTree) deserializeIndexV2(r *bufio.Reader) error {
-	// TODO: implement me!
-	return errors.New("not implemented, yet")
+	var numIndices uint32
+	if err := binary.Read(r, binary.LittleEndian, &numIndices); err != nil {
+		return err
+	}
+	index := make([]int32, numIndices)
+	s.index = index
+	invDelta := common.InvDelta()
+	for i := range index {
+		d, err := binary.ReadVarint(r)
+		if err != nil {
+			return err
+		}
+		index[i] = int32(invDelta(d))
+	}
+	return nil
 }
 
 func (t *Tin) deserializeV2(r *bufio.Reader) error {
@@ -183,13 +217,56 @@
 }
 
 func (t *Tin) deserializeVerticesV2(r *bufio.Reader) error {
-	// TODO: implement me!
-	return errors.New("not implemented, yet")
+	var numVertices uint32
+	if err := binary.Read(r, binary.LittleEndian, &numVertices); err != nil {
+		return err
+	}
+	vertices := make([]Vertex, numVertices)
+	t.Vertices = vertices
+	m := t.Min
+	for dim := range 3 {
+		invDelta := common.InvDelta()
+		for i := range vertices {
+			d, err := binary.ReadVarint(r)
+			if err != nil {
+				return err
+			}
+			v := unquant(invDelta(d))
+			switch dim {
+			case 0:
+				vertices[i].X = v + m.X
+			case 1:
+				vertices[i].Y = v + m.Y
+			case 2:
+				vertices[i].Z = v + m.Z
+			}
+		}
+	}
+	return nil
 }
 
 func (t *Tin) deserializeTrianglesV2(r *bufio.Reader) error {
-	// TODO: implement me!
-	return errors.New("not implemented, yet")
+	var numTriangles uint32
+	if err := binary.Read(r, binary.LittleEndian, &numTriangles); err != nil {
+		return err
+	}
+	indices := make([]int32, 3*numTriangles)
+	triangles := make([][]int32, numTriangles)
+	t.Triangles = triangles
+	invDelta := common.InvDelta()
+	for i := range triangles {
+		tri := indices[:3]
+		indices = indices[3:]
+		triangles[i] = tri
+		for j := range tri {
+			v, err := binary.ReadVarint(r)
+			if err != nil {
+				return err
+			}
+			tri[j] = int32(invDelta(v))
+		}
+	}
+	return nil
 }
 
 // optimizeForSerializationV2 prepares the mesh to be stored in V2.