From 1d86639fcd7f2a9479eeb7b58a1fcbb67fee5b44 Mon Sep 17 00:00:00 2001 From: bart <bart.knuiman@wur.nl> Date: Thu, 9 Mar 2023 18:07:23 +0100 Subject: [PATCH] Important bugfix, cache now working without errors. --- Runtime/VectorTile.cs | 110 ++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 52 deletions(-) diff --git a/Runtime/VectorTile.cs b/Runtime/VectorTile.cs index ad10d35..61b08dc 100644 --- a/Runtime/VectorTile.cs +++ b/Runtime/VectorTile.cs @@ -51,7 +51,8 @@ namespace Wander // float denominator = ((vertex2.y - vertex3.y) * (vertex1.x - vertex3.x) + (vertex3.x - vertex2.x) * (vertex1.y - vertex3.y)); float denominator = ((vertices[i+1].y - vertices[i+2].y) * (vertices[i].x - vertices[i+2].x) + (vertices[i+2].x - vertices[i+1].x) * (vertices[i].y - vertices[i+2].y)); - denoms.Add( 1.0f / denominator ); + denominator = 1.0f / denominator; + denoms.Add( denominator ); } } } @@ -111,6 +112,12 @@ namespace Wander return finished; } + static bool IsTriangleCCW( Vector2 vertex1, Vector2 vertex2, Vector2 vertex3 ) + { + float signedArea = (vertex2.x - vertex1.x) * (vertex3.y - vertex1.y) - (vertex3.x - vertex1.x) * (vertex2.y - vertex1.y); + return signedArea > 0; + } + // Number of failed polys to triangulate are returned. public int Triangulate() { @@ -158,6 +165,15 @@ namespace Wander double y = vertices[indices[k]*2+1]; poly.vertices.Add( new Vector2( (float)x, (float)y ) ); } + //for ( int k = 0; k < indices.Count; k += 3) + //{ + // if ( !IsTriangleCCW( poly.vertices[k], poly.vertices[k+1], poly.vertices[k+2] )) + // { + // var t = poly.vertices[k]; + // poly.vertices[k] = poly.vertices[k+2]; + // poly.vertices[k+2] = t; + // } + //} polygons[polygons.Count-1] = poly; Debug.Assert( poly.vertices.Count % 3 == 0 ); } @@ -211,7 +227,7 @@ namespace Wander int resolution, out Dictionary<byte, byte> remappedLayerIndices, out List<Vector3Int> failedPixels, - bool? cancelToken) + bool? cancelToken ) { Debug.Assert( triangulated, "First call Triangulate." ); Debug.Assert( layersIdentified, "Identify layers first." ); @@ -220,12 +236,11 @@ namespace Wander byte [] texture = new byte[resolution*resolution]; failedPixels = new List<Vector3Int>(); remappedLayerIndices = new Dictionary<byte, byte>(); - byte cachedPixel = 0; float oneOverRes = 1.0f / resolution; - TriangulatedPolygon cachedPoly = default; - int cachedVtxIdx = -1; - int cachedTriIdx = -1; + int cachedTriIdx = 0; + int cachedLyrIdx = 0; + int cachedFtrIdx = 0; // For each pixel. for (int y = 0;y < resolution ;y++) @@ -237,70 +252,58 @@ namespace Wander // For each layer, check triangle intersections. for (int l = 0;l < layers.Count && !cancelToken.Value;l++) { - var layer = layers[l]; + var lIdx = (l+cachedLyrIdx) % layers.Count; // Try last layer/feature/triangle first. + var layer = layers[lIdx]; float fx = layer.Extent * oneOverRes; - Vector2 p = new Vector2(fx*x+0.5f*fx, fx*y+0.5f*fx); - - // First try cache, quite often adjacent pixels will hit the same triangle. - if (cachedVtxIdx!=-1) - { - var vertices = cachedPoly.vertices; - var denoms = cachedPoly.denoms; - var mins = cachedPoly.mins; - var maxs = cachedPoly.maxs; - if (!(p.x < mins[cachedTriIdx].x || p.x > maxs[cachedTriIdx].x) && - !(p.y < mins[cachedTriIdx].y || p.y > maxs[cachedTriIdx].y)) - { - hit = GeomUtil.PointIsInsideTriangle2( p, vertices[cachedVtxIdx], vertices[cachedVtxIdx+1], vertices[cachedVtxIdx+2], denoms[cachedTriIdx] ); - if (hit) - { - texture[(resolution - y -1)*resolution+x] = cachedPixel; - break; // Pass from cache, continue to next pixel. - } - } - } + Vector2 p = new Vector2(fx*x+0.5f, fx*y+0.5f); - // Must check all triangles, no cache or was no hit with cache. for (int f = 0;f < layer.VectorTileFeatures.Count;f++) { - var feature = layer.VectorTileFeatures[f]; + var ftrIdx = (f + cachedFtrIdx) % layer.VectorTileFeatures.Count; + var feature = layer.VectorTileFeatures[ftrIdx]; if (feature.GeometryType != Tile.GeomType.Polygon) continue; - var polygons = polygonLayers[l][f]; + var polygons = polygonLayers[lIdx][ftrIdx]; if (polygons.vertices.Count == 0) continue; - cachedVtxIdx = -1; - cachedPoly = polygonLayers[l][f]; - var mins = cachedPoly.mins; - var maxs = cachedPoly.maxs; - var denoms = cachedPoly.denoms; - var vertices = cachedPoly.vertices; - for (int vIdx = 0, triIdx = 0;vIdx < vertices.Count;vIdx += 3, triIdx++) + var poly = polygonLayers[lIdx][ftrIdx]; + var mins = poly.mins; + var maxs = poly.maxs; + var denoms = poly.denoms; + var vertices = poly.vertices; + var triCount = vertices.Count/3; + for (int t = 0; t < triCount;t++) { + int triIdx = (t+cachedTriIdx) % triCount; if (p.x < mins[triIdx].x || p.x > maxs[triIdx].x) continue; if (p.y < mins[triIdx].y || p.y > maxs[triIdx].y) continue; - hit = GeomUtil.PointIsInsideTriangle2( p, vertices[vIdx], vertices[vIdx+1], vertices[vIdx+2], denoms[triIdx] ); + hit = GeomUtil.PointIsInsideTriangle2( p, vertices[triIdx*3], vertices[triIdx*3+1], vertices[triIdx*3+2], denoms[triIdx] ); if (hit) { cachedTriIdx = triIdx; - cachedVtxIdx = vIdx; - cachedPixel = (byte)feature.SelectedLayerIdx; - texture[(resolution - y -1)*resolution+x] = cachedPixel; + cachedLyrIdx = lIdx; + cachedFtrIdx = ftrIdx; + texture[(resolution - y -1)*resolution+x] = (byte)feature.SelectedLayerIdx; break; } } if (hit) break; + + cachedTriIdx = 0; } if (hit) break; + + cachedFtrIdx = 0; } if (!hit) { + cachedLyrIdx = 0; texture[(resolution - y -1)*resolution+x] = 255; failedPixels.Add( new Vector3Int( x, y, 255 ) ); } @@ -309,7 +312,7 @@ namespace Wander // Determine number of different layers. For instance, if only layer 3, 8, 14 and 15 are used, we select // a material that only uses 4 textures and put 3 -> Albedo_0 -> 8 to Albedo_1, etc. in the shader. - cachedPixel = 255; + byte cachedPixel = 255; int remappedIndexCounter = -1; byte remappedPixel = 255; int addr = 0; @@ -318,21 +321,24 @@ namespace Wander for (int x = 0;x < resolution;x++) { byte pixel = texture[addr]; - if ( pixel != cachedPixel && pixel < 254 /*used for not matched layer*/ ) + if (pixel < 254) { - if (!remappedLayerIndices.TryGetValue( pixel, out remappedPixel )) + if (pixel != cachedPixel) { - if (remappedIndexCounter < 253) // 254 is reserved for no layer match, 255 is ray hit with triangle. + if (!remappedLayerIndices.TryGetValue( pixel, out remappedPixel )) { - remappedIndexCounter++; - remappedPixel = (byte)remappedIndexCounter; - remappedLayerIndices.Add( pixel, remappedPixel ); + if (remappedIndexCounter < 253) // 254 is reserved for no layer match, 255 is ray hit with triangle. + { + remappedIndexCounter++; + remappedPixel = (byte)remappedIndexCounter; + remappedLayerIndices.Add( pixel, remappedPixel ); + } + else remappedPixel = 0; } - else remappedPixel = 0; + cachedPixel = pixel; } - cachedPixel = pixel; - } - texture[addr] = remappedPixel; + texture[addr] = remappedPixel; + } // leave unfound or unhit pixels on their original value. addr++; } } -- GitLab