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

Can now rasterize instead of raytrace -> slightly faster.

parent 8526c5f3
No related branches found
No related tags found
No related merge requests found
using GluonGui.WorkspaceWindow.Views.WorkspaceExplorer.Configuration;
using Mapbox.Vector.Tile;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
......@@ -25,13 +27,17 @@ namespace Wander
public List<Vector2> maxs;
public List<float> denoms;
public void OptimizeForIsPointInTriangle()
public void OptimizeForIsPointInTriangle(bool calcDenoms)
{
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 );
if (calcDenoms)
{
denoms = new List<float>( vertices.Count / 3 );
}
for (int i = 0;i < vertices.Count;i += 3)
{
......@@ -55,10 +61,13 @@ namespace Wander
if (vertices[i+2].y > maxy) maxy = vertices[i+2].y;
maxs.Add( new Vector2( maxx, maxy ) );
// 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));
denominator = 1.0f / denominator;
denoms.Add( denominator );
if (calcDenoms)
{
// 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));
denominator = 1.0f / denominator;
denoms.Add( denominator );
}
}
}
}
......@@ -184,19 +193,44 @@ namespace Wander
return numFailedPolys;
}
public void OptimizeForPointIsInsideTriangle()
bool DoesPolygonLayerQualify( int layerIdx, int featureIdx )
{
var layer = layers[layerIdx];
var feature = layer.VectorTileFeatures[featureIdx];
if (feature.GeometryType != Tile.GeomType.Polygon)
return false;
var polygons = polygonLayers[layerIdx][featureIdx];
if (polygons.vertices.Count == 0)
return false;
if (feature.SelectedLayerIdx == 254)
return false;
if (feature.RelativeHeight != 0)
return false;
return true;
}
public void OptimizeForPointIsInsideTriangle(bool calcDenoms)
{
for (int i = 0;i < polygonLayers.Count;i++)
{
for (int j = 0;j < polygonLayers[i].Count;j++)
{
polygonLayers[i][j].OptimizeForIsPointInTriangle( true );
}
}
}
public void GenerateQuadTreeForRaytrace()
{
try
{
Stopwatch sw = new Stopwatch();
sw.Restart();
for (int i = 0;i < polygonLayers.Count;i++)
{
for (int j = 0;j < polygonLayers[i].Count;j++)
{
polygonLayers[i][j].OptimizeForIsPointInTriangle();
}
}
// Generate quadtree
List<QuadTreeNode> stack = new List<QuadTreeNode>();
......@@ -209,19 +243,7 @@ namespace Wander
var layer = layers[l];
for (int f = 0;f < layer.VectorTileFeatures.Count;f++)
{
var feature = layer.VectorTileFeatures[f];
if (feature.GeometryType != Tile.GeomType.Polygon)
continue;
var polygons = polygonLayers[l][f];
if (polygons.vertices.Count == 0)
continue;
if (feature.SelectedLayerIdx == 254)
continue;
if (feature.RelativeHeight != 0)
if (!DoesPolygonLayerQualify( l, f ))
continue;
var poly = polygonLayers[l][f];
......@@ -283,6 +305,27 @@ namespace Wander
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
float sign( Vector2 p1, Vector2 p2, Vector2 p3 )
{
return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);
}
public bool PointInTriangle( Vector2 pt, Vector2 v1, Vector2 v2, Vector2 v3 )
{
float d1, d2, d3;
bool has_neg, has_pos;
d1 = sign( pt, v1, v2 );
d2 = sign( pt, v2, v3 );
d3 = sign( pt, v3, v1 );
has_neg = (d1 < 0) || (d2 < 0) || (d3 < 0);
has_pos = (d1 > 0) || (d2 > 0) || (d3 > 0);
return !(has_neg && has_pos);
}
// Identify feature by specifying a (unique) index based on some criteria. This can very per
// vector tile provider.
public void IdentifyLayers( Func<VectorTileLayer, List<KeyValuePair<string, object>>, int> selectionCallback,
......@@ -312,7 +355,98 @@ namespace Wander
// 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.
public byte[] RenderToTextureSingle(
public byte[] RasterizeToTexture(
int resolution,
out List<Vector3Int> failedPixels,
ref bool cancelToken )
{
Stopwatch sw = new Stopwatch();
sw.Restart();
failedPixels = new List<Vector3Int>();
UnityEngine.Debug.Assert( 4096 % resolution == 0 );
UnityEngine.Debug.Assert( triangulated, "First call Triangulate." );
UnityEngine.Debug.Assert( layersIdentified, "Identify layers first." );
UnityEngine.Debug.Assert( resolution > 1, "Must be at least 2." );
byte [] texture = new byte[resolution*resolution/2];
int d = 4096 / resolution;
int shift = -1;
while (d!=0)
{
shift++;
d>>=1;
}
for (int l = 0; l < polygonLayers.Count;l++)
{
var layer = layers[l];
for (int f = 0;f < layer.VectorTileFeatures.Count;f++)
{
if (DoesPolygonLayerQualify( l, f ))
{
var poly = polygonLayers[l][f];
var vertices = poly.vertices;
var layerIdx = (byte)layers[l].VectorTileFeatures[f].SelectedLayerIdx;
for (int i = 0, t = 0;i < vertices.Count;i += 3, t++)
{
var min = poly.mins[t];
var max = poly.maxs[t];
int x1 = Mathf.FloorToInt( min.x );
int y1 = Mathf.FloorToInt( min.y );
int x2 = Mathf.FloorToInt( max.x );
int y2 = Mathf.FloorToInt( max.y );
x1 >>= shift;
y1 >>= shift;
x2 >>= shift;
y2 >>= shift;
if (x1 < 0) x1 = 0;
if (x1 >= resolution) x1 = resolution-1;
if (x2 < 0) x2 = 0;
if (x2 >= resolution) x2 = resolution-1;
if (y1 < 0) y1 = 0;
if (y1 >= resolution) y1 = resolution-1;
if (y2 < 0) y2 = 0;
if (y2 >= resolution) y2 = resolution-1;
for (int y = y1;y <= y2;y++) // texture space
{
for (int x = x1;x <= x2 && !cancelToken; x++)
{
int xk2 = x<<shift; // vector tile space
int yk2 = y<<shift;
if (PointInTriangle( new Vector2( xk2, yk2 ), poly.vertices[i], poly.vertices[i+1], poly.vertices[i+2] ))
{
var addr2 = (resolution - y -1)*resolution+x;
//var addr2 = (resolution* y)+x;
if (layerIdx > 15)
layerIdx = 15; // max layers 15 (15 is reserved, nothing was hit).
var shift2 = (addr2&1) << 2;
texture[addr2>>1] |= (byte)(layerIdx << shift2);
}
}
}
}
}
}
}
UnityEngine.Debug.Log( "Rasterize to texture took " + sw.ElapsedMilliseconds );
return texture;
}
// 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.
public byte[] RaytraceToTexture(
int resolution,
out List<Vector3Int> failedPixels,
ref bool cancelToken )
......@@ -377,9 +511,9 @@ namespace Wander
{
cachedTriIdx = ti;
var layerIdx = (byte)layers[l].VectorTileFeatures[f].SelectedLayerIdx;
//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).
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;
......@@ -407,7 +541,7 @@ namespace Wander
}
// UnityEngine.Debug.Log( "Render to texture took " + sw.ElapsedMilliseconds );
// UnityEngine.Debug.Log( "Raytrace texture took " + sw.ElapsedMilliseconds );
return texture;
}
......
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