Skip to content
Snippets Groups Projects
Commit b72ce56a authored by Knuiman, Bart's avatar Knuiman, Bart
Browse files

Now correctly handles two pixels per byte. So 4 bits per pixel (16 channels of...

Now correctly handles two pixels per byte. So 4 bits per pixel (16 channels of which the last one is reserved for not valid).
parent 322ce668
No related branches found
No related tags found
No related merge requests found
......@@ -7,33 +7,33 @@ using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
namespace Wander
{
namespace Wander
{
internal class QuadTreeNode
{
internal Vector2 min, max;
internal QuadTreeNode[] children;
internal List<(int, int, int)> triangles; // Layer, Feature, Triangle index.
internal int depth;
}
// Always multiple of 3. Each 3 form a triangle.
}
// Always multiple of 3. Each 3 form a triangle.
public class TriangulatedPolygon
{
public List<Vector2> vertices;
public List<Vector2> vertices;
public List<Vector2> mins;
public List<Vector2> maxs;
public List<float> denoms;
public void OptimizeForIsPointInTriangle()
{
if ( vertices == null ) return; // Non poly layers have this.
if (vertices == null) return; // Non poly layers have this.
mins = new List<Vector2>( vertices.Count / 3 );
maxs = new List<Vector2>( vertices.Count / 3 );
denoms = new List<float>( vertices.Count / 3 );
for ( int i = 0; i < vertices.Count; i += 3 )
for (int i = 0;i < vertices.Count;i += 3)
{
float minx = float.MaxValue;
float miny = float.MaxValue;
......@@ -61,8 +61,8 @@ namespace Wander
denoms.Add( denominator );
}
}
}
}
public class VectorTile
{
public bool DownloadStarted => started;
......@@ -84,7 +84,7 @@ namespace Wander
public void StartDownload()
{
UnityEngine.Debug.Assert(!started);
UnityEngine.Debug.Assert( !started );
request.SendWebRequest();
started = true;
}
......@@ -122,17 +122,17 @@ namespace Wander
// Number of failed polys to triangulate are returned.
public int Triangulate()
{
if (triangulated )
if (triangulated)
return 0;
int numFailedPolys = 0;
polygonLayers = new List<List<TriangulatedPolygon>>();
List<double> vertices = new List<double>();
List<int> holeIndices = new List<int>();
for ( int i =0; i < layers.Count; i++ )
for (int i = 0;i < layers.Count;i++)
{
var features = layers[i].VectorTileFeatures;
var polygons = new List<TriangulatedPolygon>();
for (int j = 0; j< features.Count; j++)
for (int j = 0;j< features.Count;j++)
{
polygons.Add( new TriangulatedPolygon() ); // Add empty to ensure list(layer) of lists(features) match.
if (features[j].GeometryType != Tile.GeomType.Polygon)
......@@ -160,7 +160,7 @@ namespace Wander
var indices = EarcutNet.Earcut.Tessellate( vertices, holeIndices );
TriangulatedPolygon poly = new TriangulatedPolygon();
poly.vertices = new List<Vector2>( indices.Count );
for (int k = 0;k < indices.Count; k++)
for (int k = 0;k < indices.Count;k++)
{
double x = vertices[indices[k]*2];
double y = vertices[indices[k]*2+1];
......@@ -273,7 +273,7 @@ namespace Wander
}
UnityEngine.Debug.Log( "Optimize for raytracing took " + sw.ElapsedMilliseconds );
}
catch ( Exception e )
catch (Exception e)
{
UnityEngine.Debug.LogException( e );
}
......@@ -304,15 +304,15 @@ namespace Wander
layersIdentified = true;
}
// Generates a raster for each position (pixel) (256 channels) where each value represents a single channel.
// If no polygon was hit, 255 is encoded.
// If polygon was hit, but no feature was matched, 254 is encoded.
// Generates a raster for each position (pixel). 2 pixels are pushed in 1 (each 16 bit).
// If no polygon was hit, 15 is encoded (reserved).
// If polygon was hit, but no feature was matched, also 15 is encoded.
// Returns a list of failed to match pixels. This can be due to geometry not exactly matching or a layer not being found.
// Also outputs a remap of layer indices. For instance for a specific tile, only layerIdx 1, 6 and 3 are used.
// Then it applies a remapping of 1->0, 6->1, 3->2. So that in the shader only 3 textures are needed starting from 0, 1.. etc.
public byte[] RenderToTextureSingle(
int resolution,
out Dictionary<byte, byte> remappedLayerIndices,
out Dictionary<byte, byte> remappedLayerIndices,
out List<Vector3Int> failedPixels,
ref bool cancelToken )
{
......@@ -323,7 +323,7 @@ namespace Wander
UnityEngine.Debug.Assert( layersIdentified, "Identify layers first." );
UnityEngine.Debug.Assert( resolution > 1, "Must be at least 2." );
byte [] texture = new byte[resolution*resolution];
byte [] texture = new byte[resolution*resolution/2];
failedPixels = new List<Vector3Int>();
remappedLayerIndices = new Dictionary<byte, byte>();
float oneOverRes = 1.0f / resolution;
......@@ -336,7 +336,7 @@ namespace Wander
// For each pixel.
for (int y = 0;y < resolution && !cancelToken;y++)
{
for (int x = 0;x < resolution && !cancelToken ;x++)
for (int x = 0;x < resolution && !cancelToken;x++)
{
bool hit = false;
Vector2 p = new Vector2(fx*x+0.5f, fx*y+0.5f);
......@@ -351,16 +351,16 @@ namespace Wander
continue;
}
if ( node.children != null )
if (node.children != null)
{
for ( int c = 0; c < node.children.Length; c++ )
for (int c = 0;c < node.children.Length;c++)
{
stack.Add( node.children[c] );
}
}
else if (node.triangles != null) // Is leaf
{
for( int t = 0; t < node.triangles.Count; t++ )
for (int t = 0;t < node.triangles.Count;t++)
{
int ti = (cachedTriIdx + t) % node.triangles.Count; // Continue searching where we left off
int l = node.triangles[ti].Item1;
......@@ -375,9 +375,13 @@ namespace Wander
hit = GeomUtil.PointIsInsideTriangle2( p, vertices[t2*3], vertices[t2*3+1], vertices[t2*3+2], denoms[t2] );
if (hit)
{
cachedTriIdx = ti;
cachedTriIdx = ti;
var layerIdx = (byte)layers[l].VectorTileFeatures[f].SelectedLayerIdx;
texture[(resolution - y -1)*resolution+x] = layerIdx;
//var addr2 = y*resolution+x;
var addr2 = (resolution - y -1)*resolution+x;
if (layerIdx > 15) layerIdx = 15; // max layers 15 (15 is reserved, nothing was hit).
var shift = (addr2&1) << 2;
texture[addr2>>1] |= (byte)(layerIdx << shift);
break;
}
}
......@@ -390,8 +394,10 @@ namespace Wander
stack.Clear();
if (!hit)
{
texture[(resolution - y -1)*resolution+x] = 255;
failedPixels.Add( new Vector3Int( x, y, 255 ) );
var addr2 = (resolution - y -1)*resolution+x;
var shift = (addr2&1) << 2;
texture[addr2>>1] |= (byte)(15 << shift);
failedPixels.Add( new Vector3Int( x, y, 15 ) );
}
else
{
......@@ -402,47 +408,61 @@ 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.
byte cachedPixel = 255;
byte cachedPixel = 15;
int remappedIndexCounter = -1;
byte remappedPixel = 255;
int addr = 0;
byte remappedPixel = 15;
uint addr = 0;
byte pixel = 0;
for (int y = 0;y < resolution && !cancelToken;y++)
{
for (int x = 0;x < resolution;x++)
for (int x = 0;x < resolution && !cancelToken;x++)
{
byte pixel = texture[addr];
if (pixel < 254)
if ((x&1) == 0)
pixel = texture[addr>>1];
byte shift = (byte)((addr&1));
byte pixel2 = (byte)((pixel >> (shift<<2)) & 15);
if (pixel2 != 15)
{
if (pixel != cachedPixel)
if (pixel2 != cachedPixel)
{
if (!remappedLayerIndices.TryGetValue( pixel, out remappedPixel ))
if (!remappedLayerIndices.TryGetValue( pixel2, out remappedPixel ))
{
if (remappedIndexCounter < 253) // 254 is reserved for no layer match, 255 is ray hit with triangle.
if (remappedIndexCounter < 13) // 15 is reserved for not found, so 0-14 are valid.
{
remappedIndexCounter++;
remappedPixel = (byte)remappedIndexCounter;
remappedLayerIndices.Add( pixel, remappedPixel );
remappedLayerIndices.Add( pixel2, remappedPixel );
}
else remappedPixel = 0;
else remappedPixel = 15; // Reserved for invalid.
}
cachedPixel = pixel;
cachedPixel = pixel2;
}
texture[addr] = remappedPixel;
} // leave unfound or unhit pixels on their original value.
UnityEngine.Debug.Assert( remappedPixel < 15 );
}
else
{
remappedPixel = 15;
cachedPixel = 15;
}
// Data in texture is not zero anymore, so must check if is even, then just set, otherwise OR-add it.
if (shift==0)
texture[addr>>1] = remappedPixel;
else
texture[addr>>1] |= (byte)(remappedPixel << 4);
addr++;
}
}
UnityEngine.Debug.Assert(remappedIndexCounter <= 254, "Exceeded layer count." );
UnityEngine.Debug.Assert( remappedIndexCounter <= 15, "Exceeded layer count." ); // Invalid pixel is not added to map, so max must be 15, not 16.
UnityEngine.Debug.Log( "Render to texture took " + sw.ElapsedMilliseconds );
return texture;
}
}
public static class VectorTileLoader
}
public static class VectorTileLoader
{
public static VectorTile LoadFromUrl( string url, bool autoStart=true )
public static VectorTile LoadFromUrl( string url, bool autoStart = true )
{
VectorTile tile = new VectorTile();
tile.request = UnityWebRequest.Get( url );
......@@ -452,5 +472,5 @@ namespace Wander
}
return tile;
}
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment