# HG changeset patch # User Sascha L. Teichmann # Date 1707769435 -3600 # Node ID ef80748ae4f30180170c5c8a712171372faa750c # Parent 3bc15e38c7e8bfd8e14112660a1f18f754056b00 Finish deserializing v2 of the mesh index. diff -r 3bc15e38c7e8 -r ef80748ae4f3 pkg/mesh/meshserialize.go --- 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, diff -r 3bc15e38c7e8 -r ef80748ae4f3 pkg/mesh/meshserialize_v1.go --- 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, ) } diff -r 3bc15e38c7e8 -r ef80748ae4f3 pkg/mesh/meshserialize_v2.go --- 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.