dx
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
/* INFINITY CODE 2013-2019 */
|
||||
/* http://www.infinity-code.com */
|
||||
|
||||
#if BUILDR2
|
||||
using System.Collections.Generic;
|
||||
using BuildR2;
|
||||
#endif
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public class RealWorldTerrainBuildR2Material
|
||||
{
|
||||
#if BUILDR2
|
||||
public Facade applyFacade;
|
||||
public Surface roofSurface;
|
||||
public Roof.Types roofType = Roof.Types.Flat;
|
||||
public List<Facade> facades;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c28a4517ca6c5c469273a4fffa52a46
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,18 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
#if BUILDR3
|
||||
using BuildRCities;
|
||||
#endif
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
public class RealWorldTerrainBuildR3Material
|
||||
{
|
||||
#if BUILDR3
|
||||
public FacadeAsset wallFacade;
|
||||
public DynamicTextureAsset roofTexture;
|
||||
public Roof.Types roofType;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 434cc2378df29a74299c7f3a3dd96dd7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
/* INFINITY CODE 2013-2019 */
|
||||
/* http://www.infinity-code.com */
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains basic information about BuildR building.
|
||||
/// </summary>
|
||||
[AddComponentMenu("")]
|
||||
public class RealWorldTerrainBuildRBuilding : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2c1d10b35fec2c4a824c7d1cc6dd498
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,456 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains basic information about the building.
|
||||
/// </summary>
|
||||
[AddComponentMenu("")]
|
||||
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
|
||||
public class RealWorldTerrainBuilding : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The height of the walls.
|
||||
/// </summary>
|
||||
public float baseHeight;
|
||||
|
||||
/// <summary>
|
||||
/// Array of base vertices.
|
||||
/// </summary>
|
||||
public Vector3[] baseVertices;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to RealWorldTerrainContainer instance.
|
||||
/// </summary>
|
||||
public RealWorldTerrainContainer container;
|
||||
|
||||
/// <summary>
|
||||
/// ID of the building
|
||||
/// </summary>
|
||||
public string id;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that roof normals is inverted.
|
||||
/// </summary>
|
||||
public bool invertRoof;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that walls normals is inverted.
|
||||
/// </summary>
|
||||
public bool invertWall;
|
||||
|
||||
/// <summary>
|
||||
/// Height of roof.
|
||||
/// </summary>
|
||||
public float roofHeight;
|
||||
|
||||
/// <summary>
|
||||
/// Type of roof.
|
||||
/// </summary>
|
||||
public RealWorldTerrainRoofType roofType;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to generate the wall?
|
||||
/// </summary>
|
||||
public bool generateWall;
|
||||
|
||||
/// <summary>
|
||||
/// Material of the roof.
|
||||
/// </summary>
|
||||
public Material roofMaterial;
|
||||
|
||||
/// <summary>
|
||||
/// The scale of the roof texture's UV coordinates.
|
||||
/// </summary>
|
||||
public Vector2 roofUVScale = Vector2.one;
|
||||
|
||||
/// <summary>
|
||||
/// The starting height for the building.
|
||||
/// </summary>
|
||||
public float startHeight = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Size of a tile texture in meters.
|
||||
/// </summary>
|
||||
public Vector2 tileSize = new Vector2(30, 30);
|
||||
|
||||
/// <summary>
|
||||
/// Offset of the UV coordinates.
|
||||
/// </summary>
|
||||
public Vector2 uvOffset = Vector2.zero;
|
||||
|
||||
/// <summary>
|
||||
/// Material of the wall.
|
||||
/// </summary>
|
||||
public Material wallMaterial;
|
||||
|
||||
private MeshFilter _meshFilter;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to MeshFilter of the building.
|
||||
/// </summary>
|
||||
public MeshFilter meshFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_meshFilter == null) _meshFilter = GetComponent<MeshFilter>();
|
||||
return _meshFilter;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reference to MeshFilter of roof.
|
||||
/// </summary>
|
||||
[Obsolete("Use meshFilter instead.")]
|
||||
public MeshFilter roof
|
||||
{
|
||||
get { return meshFilter; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reference to MeshFilter of wall.
|
||||
/// </summary>
|
||||
[Obsolete("Use meshFilter instead.")]
|
||||
public MeshFilter wall
|
||||
{
|
||||
get { return meshFilter; }
|
||||
}
|
||||
|
||||
private void CreateRoofDome(List<Vector3> vertices, List<int> triangles)
|
||||
{
|
||||
Vector3 roofTopPoint = Vector3.zero;
|
||||
roofTopPoint = vertices.Aggregate(roofTopPoint, (current, point) => current + point) / vertices.Count;
|
||||
roofTopPoint.y = (baseHeight + roofHeight) * container.scale.y;
|
||||
int vIndex = vertices.Count;
|
||||
|
||||
for (int i = 0; i < vertices.Count; i++)
|
||||
{
|
||||
int p1 = i;
|
||||
int p2 = i + 1;
|
||||
if (p2 >= vertices.Count) p2 -= vertices.Count;
|
||||
|
||||
triangles.AddRange(new[] { p1, p2, vIndex });
|
||||
}
|
||||
|
||||
vertices.Add(roofTopPoint);
|
||||
}
|
||||
|
||||
private void CreateRoofMesh(List<Vector3> vertices, out List<Vector2> uv, out List<int> triangles)
|
||||
{
|
||||
List<Vector2> roofPoints = CreateRoofVertices(vertices);
|
||||
triangles = CreateRoofTriangles(vertices, roofPoints);
|
||||
|
||||
if (invertRoof) triangles.Reverse();
|
||||
|
||||
float minX = float.MaxValue;
|
||||
float minZ = float.MaxValue;
|
||||
float maxX = float.MinValue;
|
||||
float maxZ = float.MinValue;
|
||||
|
||||
float maxDistance = 0;
|
||||
int maxDistanceIndex = -1;
|
||||
int nextIndex = -1;
|
||||
|
||||
for (int i = 0; i < vertices.Count; i++)
|
||||
{
|
||||
Vector3 v = vertices[i];
|
||||
if (v.x < minX) minX = v.x;
|
||||
if (v.z < minZ) minZ = v.z;
|
||||
if (v.x > maxX) maxX = v.x;
|
||||
if (v.z > maxZ) maxZ = v.z;
|
||||
|
||||
nextIndex = i + 1;
|
||||
if (nextIndex >= vertices.Count) nextIndex = 0;
|
||||
|
||||
float distance = (v - vertices[nextIndex]).sqrMagnitude;
|
||||
if (distance > maxDistance)
|
||||
{
|
||||
maxDistance = distance;
|
||||
maxDistanceIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
nextIndex = maxDistanceIndex + 1;
|
||||
if (nextIndex >= vertices.Count) nextIndex = 0;
|
||||
|
||||
Vector3 v1 = vertices[maxDistanceIndex];
|
||||
Vector3 v2 = vertices[nextIndex];
|
||||
float angle = 360 - RealWorldTerrainMath.Angle2D(v1, v2);
|
||||
|
||||
float centerX = (minX + maxX) / 2;
|
||||
float centerZ = (minZ + maxZ) / 2;
|
||||
|
||||
Matrix4x4 matrix = Matrix4x4.TRS(new Vector3(centerX, 0, centerZ), Quaternion.Euler(0, -angle, 0), Vector3.one);
|
||||
Bounds bounds = new Bounds();
|
||||
foreach (Vector3 v in vertices)
|
||||
{
|
||||
Vector3 v1t = matrix.MultiplyPoint(v);
|
||||
bounds.Encapsulate(v1t);
|
||||
}
|
||||
|
||||
Vector2 roofScale = roofUVScale;
|
||||
if (roofScale.x == 0) roofScale.x = 0.001f;
|
||||
if (roofScale.y == 0) roofScale.y = 0.001f;
|
||||
|
||||
uv = new List<Vector2>();
|
||||
foreach (Vector3 v in vertices)
|
||||
{
|
||||
Vector3 v1t = matrix.MultiplyPoint(v);
|
||||
Vector2 uv1 = new Vector2(v1t.x / roofUVScale.x, v1t.z / roofUVScale.y);
|
||||
uv.Add(uv1);
|
||||
}
|
||||
}
|
||||
|
||||
private List<int> CreateRoofTriangles(List<Vector3> vertices, List<Vector2> roofPoints)
|
||||
{
|
||||
List<int> triangles = new List<int>();
|
||||
if (roofType == RealWorldTerrainRoofType.flat)
|
||||
{
|
||||
int[] trs = RealWorldTerrainTriangulator.Triangulate(roofPoints);
|
||||
if (trs != null) triangles.AddRange(trs);
|
||||
}
|
||||
else if (roofType == RealWorldTerrainRoofType.dome)
|
||||
{
|
||||
CreateRoofDome(vertices, triangles);
|
||||
}
|
||||
return triangles;
|
||||
}
|
||||
|
||||
private List<Vector2> CreateRoofVertices(List<Vector3> vertices)
|
||||
{
|
||||
Vector3[] targetVertices = new Vector3[baseVertices.Length];
|
||||
Array.Copy(baseVertices, targetVertices, baseVertices.Length);
|
||||
|
||||
if (container.prefs.buildingBottomMode == RealWorldTerrainBuildingBottomMode.followTerrain)
|
||||
{
|
||||
Vector3 tp = transform.position;
|
||||
RealWorldTerrainItem terrainItem = container.GetItemByWorldPosition(baseVertices[0] + tp);
|
||||
if (terrainItem != null)
|
||||
{
|
||||
TerrainData t = terrainItem.terrainData;
|
||||
|
||||
Vector3 offset = tp - terrainItem.transform.position;
|
||||
|
||||
for (int i = 0; i < targetVertices.Length; i++)
|
||||
{
|
||||
Vector3 v = targetVertices[i];
|
||||
Vector3 localPos = offset + v;
|
||||
float y = t.GetInterpolatedHeight(localPos.x / t.size.x, localPos.z / t.size.z);
|
||||
v.y = terrainItem.transform.position.y + y - tp.y;
|
||||
targetVertices[i] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Vector2> roofPoints = new List<Vector2>();
|
||||
float topPoint = targetVertices.Max(v => v.y) + baseHeight * container.scale.y;
|
||||
foreach (Vector3 p in targetVertices)
|
||||
{
|
||||
Vector3 tv = new Vector3(p.x, topPoint, p.z);
|
||||
Vector2 rp = new Vector2(p.x, p.z);
|
||||
|
||||
vertices.Add(tv);
|
||||
roofPoints.Add(rp);
|
||||
}
|
||||
|
||||
return roofPoints;
|
||||
}
|
||||
|
||||
private void CreateWallMesh(List<Vector3> vertices, List<Vector2> uv, out List<int> triangles)
|
||||
{
|
||||
List<Vector3> wv = new List<Vector3>();
|
||||
List<Vector2> wuv = new List<Vector2>();
|
||||
bool reversed = CreateWallVertices(wv, wuv);
|
||||
if (invertWall) reversed = !reversed;
|
||||
triangles = CreateWallTriangles(wv, vertices.Count, reversed);
|
||||
vertices.AddRange(wv);
|
||||
uv.AddRange(wuv);
|
||||
}
|
||||
|
||||
private List<int> CreateWallTriangles(List<Vector3> vertices, int offset, bool reversed)
|
||||
{
|
||||
List<int> triangles = new List<int>();
|
||||
for (int i = 0; i < vertices.Count / 4; i++)
|
||||
{
|
||||
int p1 = i * 4;
|
||||
int p2 = i * 4 + 2;
|
||||
int p3 = i * 4 + 3;
|
||||
int p4 = i * 4 + 1;
|
||||
|
||||
if (p2 >= vertices.Count) p2 -= vertices.Count;
|
||||
if (p3 >= vertices.Count) p3 -= vertices.Count;
|
||||
|
||||
p1 += offset;
|
||||
p2 += offset;
|
||||
p3 += offset;
|
||||
p4 += offset;
|
||||
|
||||
if (reversed)
|
||||
{
|
||||
triangles.AddRange(new[] { p1, p4, p3, p1, p3, p2 });
|
||||
}
|
||||
else
|
||||
{
|
||||
triangles.AddRange(new[] { p2, p3, p1, p3, p4, p1 });
|
||||
}
|
||||
}
|
||||
return triangles;
|
||||
}
|
||||
|
||||
private bool CreateWallVertices(List<Vector3> vertices, List<Vector2> uv)
|
||||
{
|
||||
Vector3[] targetVertices = new Vector3[baseVertices.Length];
|
||||
Array.Copy(baseVertices, targetVertices, baseVertices.Length);
|
||||
|
||||
if (container.prefs.buildingBottomMode == RealWorldTerrainBuildingBottomMode.followTerrain)
|
||||
{
|
||||
Vector3 tp = transform.position;
|
||||
RealWorldTerrainItem terrainItem = container.GetItemByWorldPosition(baseVertices[0] + tp);
|
||||
if (terrainItem != null)
|
||||
{
|
||||
TerrainData t = terrainItem.terrainData;
|
||||
|
||||
Vector3 offset = tp - terrainItem.transform.position;
|
||||
|
||||
for (int i = 0; i < targetVertices.Length; i++)
|
||||
{
|
||||
Vector3 v = targetVertices[i];
|
||||
Vector3 localPos = offset + v;
|
||||
float y = t.GetInterpolatedHeight(localPos.x / t.size.x, localPos.z / t.size.z);
|
||||
v.y = terrainItem.transform.position.y + y - tp.y;
|
||||
targetVertices[i] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float topPoint = targetVertices.Max(v => v.y) + baseHeight * container.scale.y;
|
||||
|
||||
float startY = startHeight * container.scale.y;
|
||||
float offsetY = startY < 0 ? startY : 0;
|
||||
|
||||
for (int i = 0; i < targetVertices.Length; i++)
|
||||
{
|
||||
Vector3 p1 = targetVertices[i];
|
||||
Vector3 p2 = i < targetVertices.Length - 1 ? targetVertices[i + 1] : targetVertices[0];
|
||||
if (p1.y < startY) p1.y = startY;
|
||||
if (p2.y < startY) p2.y = startY;
|
||||
p1.y += offsetY;
|
||||
p2.y += offsetY;
|
||||
vertices.Add(p1);
|
||||
vertices.Add(new Vector3(p1.x, topPoint, p1.z));
|
||||
vertices.Add(p2);
|
||||
vertices.Add(new Vector3(p2.x, topPoint, p2.z));
|
||||
}
|
||||
|
||||
float totalDistance = 0;
|
||||
float bottomPoint = float.MaxValue;
|
||||
|
||||
for (int i = 0; i < vertices.Count / 4; i++)
|
||||
{
|
||||
int i1 = Mathf.RoundToInt(Mathf.Repeat(i * 4, vertices.Count));
|
||||
int i2 = Mathf.RoundToInt(Mathf.Repeat((i + 1) * 4, vertices.Count));
|
||||
Vector3 v1 = vertices[i1];
|
||||
Vector3 v2 = vertices[i2];
|
||||
v1.y = v2.y = 0;
|
||||
totalDistance += (v1 - v2).magnitude;
|
||||
if (bottomPoint > targetVertices[i].y) bottomPoint = targetVertices[i].y;
|
||||
}
|
||||
|
||||
Vector3 lv1 = vertices[vertices.Count - 4];
|
||||
Vector3 lv2 = vertices[0];
|
||||
lv1.y = lv2.y = 0;
|
||||
totalDistance += (lv1 - lv2).magnitude;
|
||||
|
||||
float currentDistance = 0;
|
||||
float nextU = 0;
|
||||
float uMul = totalDistance / tileSize.x;
|
||||
float vMax = topPoint / tileSize.y;
|
||||
float vMinMul = container.scale.y * tileSize.y;
|
||||
|
||||
for (int i = 0; i < vertices.Count / 4; i++)
|
||||
{
|
||||
int i1 = Mathf.RoundToInt(Mathf.Repeat(i * 4, vertices.Count));
|
||||
int i2 = Mathf.RoundToInt(Mathf.Repeat((i + 1) * 4, vertices.Count));
|
||||
float curU = nextU;
|
||||
uv.Add(new Vector2(curU * uMul + uvOffset.x, (vertices[i * 4].y - bottomPoint) / vMinMul + uvOffset.y));
|
||||
uv.Add(new Vector2(curU * uMul + uvOffset.x, vMax + uvOffset.y));
|
||||
|
||||
Vector3 v1 = vertices[i1];
|
||||
Vector3 v2 = vertices[i2];
|
||||
v1.y = v2.y = 0;
|
||||
currentDistance += (v1 - v2).magnitude;
|
||||
nextU = currentDistance / totalDistance;
|
||||
|
||||
uv.Add(new Vector2(nextU * uMul + uvOffset.x, (vertices[i * 4 + 2].y - bottomPoint) / vMinMul + uvOffset.y));
|
||||
uv.Add(new Vector2(nextU * uMul + uvOffset.x, vMax + uvOffset.y));
|
||||
}
|
||||
|
||||
int southIndex = -1;
|
||||
float southZ = float.MaxValue;
|
||||
|
||||
for (int i = 0; i < targetVertices.Length; i++)
|
||||
{
|
||||
if (targetVertices[i].z < southZ)
|
||||
{
|
||||
southZ = targetVertices[i].z;
|
||||
southIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
int prevIndex = southIndex - 1;
|
||||
if (prevIndex < 0) prevIndex = targetVertices.Length - 1;
|
||||
|
||||
int nextIndex = southIndex + 1;
|
||||
if (nextIndex >= targetVertices.Length) nextIndex = 0;
|
||||
|
||||
float angle1 = RealWorldTerrainMath.Angle2D(targetVertices[southIndex], targetVertices[nextIndex]);
|
||||
float angle2 = RealWorldTerrainMath.Angle2D(targetVertices[southIndex], targetVertices[prevIndex]);
|
||||
|
||||
return angle1 < angle2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates the building mesh.
|
||||
/// </summary>
|
||||
public void Generate()
|
||||
{
|
||||
Mesh mesh;
|
||||
if (meshFilter.sharedMesh != null) mesh = meshFilter.sharedMesh;
|
||||
else
|
||||
{
|
||||
mesh = new Mesh();
|
||||
mesh.name = "Building " + id;
|
||||
mesh.subMeshCount = 2;
|
||||
meshFilter.sharedMesh = mesh;
|
||||
}
|
||||
|
||||
List<Vector3> vertices = new List<Vector3>();
|
||||
List<Vector2> uv;
|
||||
List<int> roofTriangles;
|
||||
List<int> wallTriangles = null;
|
||||
|
||||
CreateRoofMesh(vertices, out uv, out roofTriangles);
|
||||
if (generateWall) CreateWallMesh(vertices, uv, out wallTriangles);
|
||||
|
||||
mesh.SetVertices(vertices);
|
||||
mesh.SetUVs(0, uv);
|
||||
mesh.SetTriangles(roofTriangles, 0);
|
||||
if (generateWall) mesh.SetTriangles(wallTriangles, 1);
|
||||
|
||||
mesh.RecalculateNormals();
|
||||
mesh.RecalculateBounds();
|
||||
|
||||
GetComponent<MeshRenderer>().materials = new[]
|
||||
{
|
||||
roofMaterial,
|
||||
wallMaterial,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c16844aceaeec04999e14ee80b7b8e2
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,169 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is added to the resulting container.\n
|
||||
/// It contains all information about terrains.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[AddComponentMenu("")]
|
||||
public class RealWorldTerrainContainer : RealWorldTerrainMonoBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Billboard start.
|
||||
/// </summary>
|
||||
public float billboardStart = 50;
|
||||
|
||||
/// <summary>
|
||||
/// Detail density.
|
||||
/// </summary>
|
||||
public float detailDensity = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Detail distance.
|
||||
/// </summary>
|
||||
public float detailDistance = 80;
|
||||
|
||||
/// <summary>
|
||||
/// The folder in the project where located terrains.
|
||||
/// </summary>
|
||||
public string folder;
|
||||
|
||||
/// <summary>
|
||||
/// Count of terrains.
|
||||
/// </summary>
|
||||
public RealWorldTerrainVector2i terrainCount;
|
||||
|
||||
/// <summary>
|
||||
/// Title
|
||||
/// </summary>
|
||||
public string title;
|
||||
|
||||
/// <summary>
|
||||
/// Tree distance.
|
||||
/// </summary>
|
||||
public float treeDistance = 2000;
|
||||
|
||||
/// <summary>
|
||||
/// The array of elements that belong to the current process of generation.
|
||||
/// </summary>
|
||||
public RealWorldTerrainItem[] terrains;
|
||||
|
||||
/// <summary>
|
||||
/// Gets all instances of RealWorldTerrainContainer.
|
||||
/// </summary>
|
||||
/// <returns>Instances of RealWorldTerrainContainer</returns>
|
||||
public static RealWorldTerrainContainer[] GetInstances()
|
||||
{
|
||||
return RealWorldTerrainUtils.FindObjectsOfType<RealWorldTerrainContainer>();
|
||||
}
|
||||
|
||||
public override RealWorldTerrainItem GetItemByWorldPosition(Vector3 worldPosition)
|
||||
{
|
||||
for (int i = 0; i < terrains.Length; i++)
|
||||
{
|
||||
RealWorldTerrainItem item = terrains[i];
|
||||
if (item == null) continue;
|
||||
Bounds b = new Bounds(item.bounds.center, item.bounds.size);
|
||||
if (b.min.x <= worldPosition.x && b.min.z <= worldPosition.z && b.max.x >= worldPosition.x && b.max.z >= worldPosition.z)
|
||||
{
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public override bool GetWorldPosition(double lng, double lat, out Vector3 worldPosition)
|
||||
{
|
||||
worldPosition = new Vector3();
|
||||
|
||||
if (!Contains(lng, lat))
|
||||
{
|
||||
Debug.Log("Wrong coordinates");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (terrains == null || terrains.Length == 0) return false;
|
||||
|
||||
double mx, my;
|
||||
RealWorldTerrainGeo.LatLongToMercat(lng, lat, out mx, out my);
|
||||
|
||||
double lX = RealWorldTerrainMath.Clamp((mx - leftMercator) / (rightMercator - leftMercator), 0, 1);
|
||||
double lZ = RealWorldTerrainMath.Clamp(1 - (my - topMercator) / (bottomMercator - topMercator), 0, 1);
|
||||
|
||||
Bounds cb = new Bounds(bounds.center, bounds.size);
|
||||
|
||||
double x = cb.size.x * lX + cb.min.x;
|
||||
double z = cb.size.z * lZ + cb.min.z;
|
||||
|
||||
if (prefs.resultType == RealWorldTerrainResultType.terrain)
|
||||
{
|
||||
Terrain terrain = null;
|
||||
for (int i = 0; i < terrains.Length; i++)
|
||||
{
|
||||
RealWorldTerrainItem item = terrains[i];
|
||||
Bounds b = new Bounds(item.bounds.center, item.bounds.size);
|
||||
if (b.min.x <= x && b.min.z <= z && b.max.x >= x && b.max.z >= z)
|
||||
{
|
||||
terrain = item.terrain;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (terrain == null) return false;
|
||||
|
||||
double ix = (x - terrain.gameObject.transform.position.x) / terrain.terrainData.size.x;
|
||||
double iz = (z - terrain.gameObject.transform.position.z) / terrain.terrainData.size.z;
|
||||
double y = terrain.terrainData.GetInterpolatedHeight((float)ix, (float)iz) + terrain.gameObject.transform.position.y;
|
||||
|
||||
worldPosition.x = (float)x;
|
||||
worldPosition.y = (float)y;
|
||||
worldPosition.z = (float)z;
|
||||
}
|
||||
else if (prefs.resultType == RealWorldTerrainResultType.mesh)
|
||||
{
|
||||
bool success = false;
|
||||
for (int i = 0; i < terrains.Length; i++)
|
||||
{
|
||||
RealWorldTerrainItem item = terrains[i];
|
||||
Bounds b = new Bounds(item.bounds.center, item.bounds.size);
|
||||
if (b.min.x <= x && b.min.z <= z && b.max.x >= x && b.max.z >= z)
|
||||
{
|
||||
float y = 0;
|
||||
RaycastHit[] hits = Physics.RaycastAll(new Vector3((float)x, item.bounds.max.y + 10, (float)z), Vector3.down, float.MaxValue);
|
||||
foreach (RaycastHit hit in hits)
|
||||
{
|
||||
if (hit.transform.gameObject.GetComponentInParent<RealWorldTerrainItem>() != null)
|
||||
{
|
||||
y = hit.point.y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
worldPosition.x = (float)x;
|
||||
worldPosition.y = y;
|
||||
worldPosition.z = (float)z;
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool GetWorldPosition(Vector2 coordinates, out Vector3 worldPosition)
|
||||
{
|
||||
return GetWorldPosition(coordinates.x, coordinates.y, out worldPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 35746522d0c34a74e98f963412f0defe
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
//[CreateAssetMenu(fileName = "Documentation.asset", menuName = "Create Documentation")]
|
||||
public class RealWorldTerrainDocumentation : ScriptableObject
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09989ac6b1998df44bfdcd195082f28d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
public class RealWorldTerrainDynamicBuilding : RealWorldTerrainBuilding
|
||||
{
|
||||
private void Awake()
|
||||
{
|
||||
if (baseVertices != null) Generate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dab7fa385164831489cb84458fd83811
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
/* INFINITY CODE 2013-2019 */
|
||||
/* http://www.infinity-code.com */
|
||||
|
||||
using InfinityCode.RealWorldTerrain.Webservices.Results;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
[AddComponentMenu("")]
|
||||
public class RealWorldTerrainGeocodingObject:MonoBehaviour
|
||||
{
|
||||
public RealWorldTerrainGoogleGeocodingResult info;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9430c68e8cd249549a66febd545c986f
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,227 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
/// <summary>
|
||||
/// This class is added to each created terrains.\n
|
||||
/// It contains all information about the terrain.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[AddComponentMenu("")]
|
||||
public class RealWorldTerrainItem : RealWorldTerrainMonoBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Reference to RealWorldTerrainContainer instance.
|
||||
/// </summary>
|
||||
public RealWorldTerrainContainer container;
|
||||
|
||||
/// <summary>
|
||||
/// X index.
|
||||
/// </summary>
|
||||
public int x;
|
||||
|
||||
/// <summary>
|
||||
/// Y index.
|
||||
/// </summary>
|
||||
public int y;
|
||||
|
||||
/// <summary>
|
||||
/// Reversed Y index (ry = countY - y - 1).
|
||||
/// </summary>
|
||||
public int ry;
|
||||
|
||||
public bool needUpdate = false;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to MeshFilter, if result is mesh.
|
||||
/// </summary>
|
||||
public MeshFilter meshFilter;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to Terrain, if result is terrain.
|
||||
/// </summary>
|
||||
public Terrain terrain;
|
||||
|
||||
/// <summary>
|
||||
/// Refetence to texture
|
||||
/// </summary>
|
||||
public Texture2D texture
|
||||
{
|
||||
get
|
||||
{
|
||||
if (prefs.resultType == RealWorldTerrainResultType.terrain)
|
||||
{
|
||||
#if !RTP
|
||||
|
||||
if (terrainData == null || terrainData.terrainLayers.Length == 0) return null;
|
||||
TerrainLayer sp = terrainData.terrainLayers[0];
|
||||
return sp != null? sp.diffuseTexture: null;
|
||||
#else
|
||||
ReliefTerrain reliefTerrain = GetComponent<ReliefTerrain>();
|
||||
if (reliefTerrain == null)
|
||||
{
|
||||
|
||||
if (terrainData == null || terrainData.terrainLayers.Length == 0) return null;
|
||||
TerrainLayer sp = terrainData.terrainLayers[0];
|
||||
return sp.diffuseTexture;
|
||||
}
|
||||
return reliefTerrain.ColorGlobal;
|
||||
#endif
|
||||
}
|
||||
MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
|
||||
if (meshRenderer == null)
|
||||
{
|
||||
meshRenderer = GetComponentInChildren<MeshRenderer>();
|
||||
if (meshRenderer == null) return null;
|
||||
}
|
||||
return meshRenderer.sharedMaterial != null? meshRenderer.sharedMaterial.mainTexture as Texture2D: null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (prefs.resultType == RealWorldTerrainResultType.terrain)
|
||||
{
|
||||
#if !RTP
|
||||
if (terrainData == null) return;
|
||||
|
||||
TerrainLayer[] tls = terrainData.terrainLayers;
|
||||
if (tls.Length == 0) return;
|
||||
if (tls[0] == null)
|
||||
{
|
||||
tls[0] = new TerrainLayer
|
||||
{
|
||||
tileSize = new Vector2(terrainData.size.x, terrainData.size.z)
|
||||
};
|
||||
#if UNITY_EDITOR
|
||||
string path = container.folder + terrain.name + ".terrainlayer";
|
||||
AssetDatabase.CreateAsset(tls[0], path);
|
||||
AssetDatabase.Refresh();
|
||||
tls[0] = AssetDatabase.LoadAssetAtPath<TerrainLayer>(path);
|
||||
#endif
|
||||
}
|
||||
tls[0].diffuseTexture = value;
|
||||
terrainData.terrainLayers = tls;
|
||||
#else
|
||||
ReliefTerrain reliefTerrain = GetComponent<ReliefTerrain>();
|
||||
if (reliefTerrain == null) return;
|
||||
reliefTerrain.ColorGlobal = value;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
|
||||
if (meshRenderer != null) meshRenderer.sharedMaterial.mainTexture = value;
|
||||
else
|
||||
{
|
||||
foreach (MeshRenderer mr in GetComponentsInChildren<MeshRenderer>())
|
||||
{
|
||||
mr.sharedMaterial.mainTexture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets TerrainData.
|
||||
/// </summary>
|
||||
public TerrainData terrainData
|
||||
{
|
||||
get
|
||||
{
|
||||
return terrain != null? terrain.terrainData: null;
|
||||
}
|
||||
}
|
||||
|
||||
public float GetHeightmapValueByMercator(double mx, double my)
|
||||
{
|
||||
float rx = (float) ((mx - leftMercator) / (rightMercator - leftMercator));
|
||||
float ry = (float) ((my - topMercator) / (bottomMercator - topMercator));
|
||||
return terrainData.GetInterpolatedHeight(rx, 1 - ry);
|
||||
}
|
||||
|
||||
public override RealWorldTerrainItem GetItemByWorldPosition(Vector3 worldPosition)
|
||||
{
|
||||
return container.GetItemByWorldPosition(worldPosition);
|
||||
}
|
||||
|
||||
public override bool GetWorldPosition(double lng, double lat, out Vector3 worldPosition)
|
||||
{
|
||||
worldPosition = new Vector3();
|
||||
|
||||
if (!Contains(lng, lat))
|
||||
{
|
||||
Debug.Log("Wrong coordinates");
|
||||
return false;
|
||||
}
|
||||
|
||||
Bounds b = new Bounds(bounds.center, bounds.size);
|
||||
|
||||
double mx, my;
|
||||
RealWorldTerrainGeo.LatLongToMercat(lng, lat, out mx, out my);
|
||||
|
||||
double lX = RealWorldTerrainMath.Clamp((mx - leftMercator) / width, 0, 1);
|
||||
double lZ = RealWorldTerrainMath.Clamp(1 - (my - topMercator) / height, 0, 1);
|
||||
|
||||
double px = b.size.x * lX + b.min.x;
|
||||
double pz = b.size.z * lZ + b.min.z;
|
||||
|
||||
if (prefs.resultType == RealWorldTerrainResultType.terrain)
|
||||
{
|
||||
Terrain tr = terrain;
|
||||
if (tr == null) return false;
|
||||
|
||||
TerrainData tData = terrainData;
|
||||
Vector3 tSize = tData.size;
|
||||
Vector3 position = transform.position;
|
||||
if (position.x > px || position.z > pz || position.x + tSize.x < px || position.z + tSize.z < pz)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
double ix = (px - terrain.gameObject.transform.position.x) / tData.size.x;
|
||||
double iz = (pz - terrain.gameObject.transform.position.z) / tData.size.z;
|
||||
double py = tData.GetInterpolatedHeight((float)ix, (float)iz) + position.y;
|
||||
|
||||
worldPosition.x = (float)px;
|
||||
worldPosition.y = (float)py;
|
||||
worldPosition.z = (float)pz;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (b.min.x <= px && b.min.z <= pz && b.max.x >= px && b.max.z >= pz)
|
||||
{
|
||||
float y = 0;
|
||||
RaycastHit[] hits = Physics.RaycastAll(new Vector3((float)px, bounds.max.y + 10, (float)pz), Vector3.down, float.MaxValue);
|
||||
foreach (RaycastHit hit in hits)
|
||||
{
|
||||
if (hit.transform.gameObject.GetComponentInParent<RealWorldTerrainItem>() != null)
|
||||
{
|
||||
y = hit.point.y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
worldPosition.x = (float)px;
|
||||
worldPosition.y = y;
|
||||
worldPosition.z = (float)pz;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool GetWorldPosition(Vector2 coordinates, out Vector3 worldPosition)
|
||||
{
|
||||
return GetWorldPosition(coordinates.x, coordinates.y, out worldPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc9fccbe3f9587140a1e1601f0e73d70
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,474 @@
|
||||
/* INFINITY CODE */
|
||||
/* https://infinity-code.com */
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains all the information about the terrain and Real World Terrain settings.
|
||||
/// </summary>
|
||||
public abstract class RealWorldTerrainMonoBase : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies whether to generate grass on the terrain.
|
||||
/// </summary>
|
||||
public bool generateGrass;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether rivers have been generated on the terrain.
|
||||
/// </summary>
|
||||
public bool generatedRivers;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to generate roads on the terrain.
|
||||
/// </summary>
|
||||
public bool generateRoads;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to create textures
|
||||
/// </summary>
|
||||
public bool generateTextures;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to generate trees on the terrain.
|
||||
/// </summary>
|
||||
public bool generateTrees;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to create buildings
|
||||
/// </summary>
|
||||
public bool generatedBuildings;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to create grass
|
||||
/// </summary>
|
||||
public bool generatedGrass;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to create textures
|
||||
/// </summary>
|
||||
public bool generatedTextures;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether to create trees
|
||||
/// </summary>
|
||||
public bool generatedTrees;
|
||||
|
||||
/// <summary>
|
||||
/// Maximal value of elevation
|
||||
/// </summary>
|
||||
public double maxElevation;
|
||||
|
||||
/// <summary>
|
||||
/// Minimal value of elevation
|
||||
/// </summary>
|
||||
public double minElevation;
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the preferences
|
||||
/// </summary>
|
||||
public RealWorldTerrainPrefsBase prefs;
|
||||
|
||||
/// <summary>
|
||||
/// Scale of terrains
|
||||
/// </summary>
|
||||
public Vector3 scale;
|
||||
|
||||
/// <summary>
|
||||
/// Size of terrains in world units
|
||||
/// </summary>
|
||||
public Vector3 size;
|
||||
|
||||
/// <summary>
|
||||
/// Top latitude
|
||||
/// </summary>
|
||||
public double topLatitude;
|
||||
|
||||
/// <summary>
|
||||
/// Top latitude in Mercator projection (0-1)
|
||||
/// </summary>
|
||||
public double topMercator;
|
||||
|
||||
/// <summary>
|
||||
/// Left longitude
|
||||
/// </summary>
|
||||
public double leftLongitude;
|
||||
|
||||
/// <summary>
|
||||
/// Left longitude in Mercator projection (0-1)
|
||||
/// </summary>
|
||||
public double leftMercator;
|
||||
|
||||
/// <summary>
|
||||
/// Bottom latitude
|
||||
/// </summary>
|
||||
public double bottomLatitude;
|
||||
|
||||
/// <summary>
|
||||
/// Bottom latitude in Mercator projection (0-1)
|
||||
/// </summary>
|
||||
public double bottomMercator;
|
||||
|
||||
/// <summary>
|
||||
/// Right longitude
|
||||
/// </summary>
|
||||
public double rightLongitude;
|
||||
|
||||
/// <summary>
|
||||
/// Right longitude in Mercator projection (0-1)
|
||||
/// </summary>
|
||||
public double rightMercator;
|
||||
|
||||
/// <summary>
|
||||
/// Width. Right longitude - left longitude
|
||||
/// </summary>
|
||||
public double width;
|
||||
|
||||
/// <summary>
|
||||
/// Height. Top latitude - bottom latitude
|
||||
/// </summary>
|
||||
public double height;
|
||||
|
||||
#if BUILDR2
|
||||
public List<RealWorldTerrainBuildR2Material> buildR2Facades;
|
||||
#endif
|
||||
|
||||
private Dictionary<string, object> customFields;
|
||||
|
||||
/// <summary>
|
||||
/// The width of the terrain in Mercator projection units.
|
||||
/// </summary>
|
||||
public double mercatorWidth;
|
||||
|
||||
/// <summary>
|
||||
/// The height of the terrain in Mercator projection units.
|
||||
/// </summary>
|
||||
public double mercatorHeight;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value associated with the specified key in the custom fields.
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the value to get or set.</param>
|
||||
/// <returns>The value associated with the specified key.</returns>
|
||||
public object this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (customFields == null) return null;
|
||||
object value;
|
||||
if (!customFields.TryGetValue(key, out value)) return null;
|
||||
return value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (customFields == null) customFields = new Dictionary<string, object>();
|
||||
if (value != null) customFields[key] = value;
|
||||
else customFields.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bounds of the terrain.
|
||||
/// </summary>
|
||||
public Bounds bounds
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Bounds(transform.position + size / 2, size);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear custom fields.
|
||||
/// </summary>
|
||||
public void ClearCustomFields()
|
||||
{
|
||||
customFields = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the coordinate in terrain area.
|
||||
/// </summary>
|
||||
/// <param name="coordinates">Coordinate</param>
|
||||
/// <returns>True - coordinate in area, False - otherwise.</returns>
|
||||
public bool Contains(Vector2 coordinates)
|
||||
{
|
||||
return Contains(coordinates.x, coordinates.y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the coordinate in terrain area.
|
||||
/// </summary>
|
||||
/// <param name="lng">Longitude</param>
|
||||
/// <param name="lat">Latitude</param>
|
||||
/// <returns>True - coordinate in area, False - otherwise.</returns>
|
||||
public bool Contains(double lng, double lat)
|
||||
{
|
||||
return leftLongitude <= lng && rightLongitude >= lng && topLatitude >= lat && bottomLatitude <= lat;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get altitude by location (coordinates).
|
||||
/// </summary>
|
||||
/// <param name="lng">Longitude</param>
|
||||
/// <param name="lat">Latitude</param>
|
||||
/// <returns>Altitude (meters)</returns>
|
||||
public double GetAltitudeByCoordinates(double lng, double lat)
|
||||
{
|
||||
if (!Contains(lng, lat)) return 0;
|
||||
|
||||
Vector3 worldPosition;
|
||||
GetWorldPosition(lng, lat, out worldPosition);
|
||||
|
||||
Bounds b = new Bounds(bounds.center, bounds.size);
|
||||
Vector3 offset = worldPosition - b.min;
|
||||
|
||||
if (prefs.resultType == RealWorldTerrainResultType.terrain)
|
||||
{
|
||||
RealWorldTerrainItem currentItem = GetItemByWorldPosition(worldPosition);
|
||||
return offset.y / currentItem.terrainData.size.y * (currentItem.maxElevation - currentItem.minElevation);
|
||||
}
|
||||
|
||||
return worldPosition.y / b.size.y * (maxElevation - minElevation) + minElevation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get altitude by location (coordinates).
|
||||
/// </summary>
|
||||
/// <param name="lng">Longitude</param>
|
||||
/// <param name="lat">Latitude</param>
|
||||
/// <returns>Altitude (meters)</returns>
|
||||
[Obsolete("Use GetAltitudeByCoordinates")]
|
||||
public double GetAltitudeByLocation(double lng, double lat)
|
||||
{
|
||||
return GetAltitudeByCoordinates(lng, lat);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get altitude by Unity World Position.
|
||||
/// </summary>
|
||||
/// <param name="worldPosition">Unity World Position</param>
|
||||
/// <returns>Altitude (meters)</returns>
|
||||
public double GetAltitudeByWorldPosition(Vector3 worldPosition)
|
||||
{
|
||||
Bounds b = new Bounds(bounds.center, bounds.size);
|
||||
Vector3 offset = worldPosition - b.min;
|
||||
|
||||
if (offset.x < 0 || offset.z < 0) return 0;
|
||||
if (offset.x > b.size.x || offset.z > b.size.z) return 0;
|
||||
|
||||
if (prefs.resultType == RealWorldTerrainResultType.terrain)
|
||||
{
|
||||
RealWorldTerrainItem currentItem = GetItemByWorldPosition(worldPosition);
|
||||
return offset.y / currentItem.terrainData.size.y * (currentItem.maxElevation - currentItem.minElevation);
|
||||
}
|
||||
|
||||
return worldPosition.y / b.size.y * (maxElevation - minElevation) + minElevation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get coordinates under mouse cursor
|
||||
/// </summary>
|
||||
/// <param name="coordinates">Geographical coordinates</param>
|
||||
/// <param name="cam">Camera</param>
|
||||
/// <returns>True - success, False - otherwise</returns>
|
||||
public bool GetCoordinatesUnderCursor(out Vector2 coordinates, Camera cam = null)
|
||||
{
|
||||
return GetCoordinatesByScreenPosition(Input.mousePosition, out coordinates, cam);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the screen coordinates into geographic coordinates.
|
||||
/// </summary>
|
||||
/// <param name="screenPosition">Position in screen space</param>
|
||||
/// <param name="coordinates">Geographic coordinates</param>
|
||||
/// <param name="cam">Camera</param>
|
||||
/// <returns>True - screen coordinates on terrains, False - otherwise</returns>
|
||||
public bool GetCoordinatesByScreenPosition(Vector2 screenPosition, out Vector2 coordinates, Camera cam = null)
|
||||
{
|
||||
if (cam == null) cam = Camera.main;
|
||||
coordinates = Vector2.zero;
|
||||
|
||||
RaycastHit[] hits = Physics.RaycastAll(cam.ScreenPointToRay(screenPosition));
|
||||
for (int i = 0; i < hits.Length; i++)
|
||||
{
|
||||
RaycastHit hit = hits[i];
|
||||
if (hit.collider is TerrainCollider || hit.collider is MeshCollider)
|
||||
{
|
||||
RealWorldTerrainItem item = hit.transform.GetComponent<RealWorldTerrainItem>();
|
||||
if (item != null) return GetCoordinatesByWorldPosition(hit.point, out coordinates);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the screen coordinates into geographic coordinates.
|
||||
/// </summary>
|
||||
/// <param name="screenPosition">Position in screen space</param>
|
||||
/// <param name="longitude">Longitude</param>
|
||||
/// <param name="latitude">Latitude</param>
|
||||
/// <param name="altitude">Altitude</param>
|
||||
/// <param name="cam">Camera</param>
|
||||
/// <returns>True - screen coordinates on terrains, False - otherwise</returns>
|
||||
public bool GetCoordinatesByScreenPosition(Vector2 screenPosition, out double longitude, out double latitude, out double altitude, Camera cam = null)
|
||||
{
|
||||
if (cam == null) cam = Camera.main;
|
||||
longitude = latitude = altitude = 0;
|
||||
|
||||
RaycastHit[] hits = Physics.RaycastAll(cam.ScreenPointToRay(screenPosition));
|
||||
for (int i = 0; i < hits.Length; i++)
|
||||
{
|
||||
RaycastHit hit = hits[i];
|
||||
if (hit.collider is TerrainCollider || hit.collider is MeshCollider)
|
||||
{
|
||||
RealWorldTerrainItem item = hit.transform.GetComponent<RealWorldTerrainItem>();
|
||||
if (item != null) return GetCoordinatesByWorldPosition(hit.point, out longitude, out latitude, out altitude);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the world coordinates into geographic coordinates.
|
||||
/// </summary>
|
||||
/// <param name="worldPosition">Position in Unity World Space</param>
|
||||
/// <param name="coordinates">Geographic coordinates</param>
|
||||
/// <returns>True - world coordinates on terrains, False - otherwise</returns>
|
||||
public bool GetCoordinatesByWorldPosition(Vector3 worldPosition, out Vector2 coordinates)
|
||||
{
|
||||
coordinates = new Vector2();
|
||||
double lng, lat;
|
||||
bool result = GetCoordinatesByWorldPosition(worldPosition, out lng, out lat);
|
||||
coordinates.x = (float)lng;
|
||||
coordinates.y = (float)lat;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the world coordinates into geographic coordinates.
|
||||
/// </summary>
|
||||
/// <param name="worldPosition">Position in Unity World Space</param>
|
||||
/// <param name="longitude">Longitude</param>
|
||||
/// <param name="latitude">Latitude</param>
|
||||
/// <returns>True - world coordinates on terrains, False - otherwise</returns>
|
||||
public bool GetCoordinatesByWorldPosition(Vector3 worldPosition, out double longitude, out double latitude)
|
||||
{
|
||||
Bounds b = new Bounds(bounds.center, bounds.size);
|
||||
|
||||
double wrx = (worldPosition.x - b.min.x) / b.size.x;
|
||||
double wrz = (b.max.z - worldPosition.z) / b.size.z;
|
||||
|
||||
double px = (rightMercator - leftMercator) * wrx + leftMercator;
|
||||
double pz = (bottomMercator - topMercator) * wrz + topMercator;
|
||||
|
||||
RealWorldTerrainGeo.MercatToLatLong(px, pz, out longitude, out latitude);
|
||||
return b.Contains(worldPosition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the world coordinates into geographic coordinates.
|
||||
/// </summary>
|
||||
/// <param name="worldPosition">Position in Unity World Space</param>
|
||||
/// <param name="longitude">Longitude</param>
|
||||
/// <param name="latitude">Latitude</param>
|
||||
/// <param name="altitude">Altitude</param>
|
||||
/// <returns>True - world coordinates on terrains, False - otherwise</returns>
|
||||
public bool GetCoordinatesByWorldPosition(Vector3 worldPosition, out double longitude, out double latitude, out double altitude)
|
||||
{
|
||||
altitude = 0;
|
||||
|
||||
Bounds b = new Bounds(bounds.center, bounds.size);
|
||||
|
||||
double wrx = (worldPosition.x - b.min.x) / b.size.x;
|
||||
double wrz = (b.max.z - worldPosition.z) / b.size.z;
|
||||
|
||||
double px1 = (rightMercator - leftMercator) * wrx + leftMercator;
|
||||
double pz = (bottomMercator - topMercator) * wrz + topMercator;
|
||||
|
||||
RealWorldTerrainGeo.MercatToLatLong(px1, pz, out longitude, out latitude);
|
||||
|
||||
if (b.min.x > worldPosition.x || b.max.x < worldPosition.x || b.min.z > worldPosition.z || b.max.z < worldPosition.z)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector3 offset = worldPosition - b.min;
|
||||
|
||||
if (prefs.resultType == RealWorldTerrainResultType.terrain)
|
||||
{
|
||||
RealWorldTerrainItem currentItem = GetItemByWorldPosition(worldPosition);
|
||||
altitude = (offset.y + currentItem.transform.position.y) / currentItem.terrainData.size.y * (currentItem.maxElevation - currentItem.minElevation) + currentItem.minElevation;
|
||||
}
|
||||
else
|
||||
{
|
||||
altitude = worldPosition.y / b.size.y * (maxElevation - minElevation) + minElevation;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get RealWorldTerrainItem by Unity World Position.
|
||||
/// </summary>
|
||||
/// <param name="worldPosition">Position in Unity World Space</param>
|
||||
/// <returns>Instance of RealWorldTerrainItem</returns>
|
||||
public abstract RealWorldTerrainItem GetItemByWorldPosition(Vector3 worldPosition);
|
||||
|
||||
/// <summary>
|
||||
/// Get Unity World Position by geographic coordinates.
|
||||
/// </summary>
|
||||
/// <param name="lng">Longitude</param>
|
||||
/// <param name="lat">Latitde</param>
|
||||
/// <param name="worldPosition">Position in Unity World Space</param>
|
||||
/// <returns>True - success, False - otherwise</returns>
|
||||
public abstract bool GetWorldPosition(double lng, double lat, out Vector3 worldPosition);
|
||||
|
||||
/// <summary>
|
||||
/// Get Unity World Position by geographic coordinates.
|
||||
/// </summary>
|
||||
/// <param name="lng">Longitude</param>
|
||||
/// <param name="lat">Latitude</param>
|
||||
/// <param name="altitude">Altitude</param>
|
||||
/// <param name="worldPosition">Position in Unity World Space</param>
|
||||
/// <returns>True - success, False - otherwise</returns>
|
||||
public bool GetWorldPosition(double lng, double lat, double altitude, out Vector3 worldPosition)
|
||||
{
|
||||
bool result = GetWorldPosition(lng, lat, out worldPosition);
|
||||
if (result) worldPosition.y = (float)(bounds.size.y * ((altitude - minElevation) / (maxElevation - minElevation)));
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Unity World Position by geographic coordinates.
|
||||
/// </summary>
|
||||
/// <param name="coordinates">Geographic coordinates</param>
|
||||
/// <param name="worldPosition">Position in Unity World Space</param>
|
||||
/// <returns></returns>
|
||||
public abstract bool GetWorldPosition(Vector2 coordinates, out Vector3 worldPosition);
|
||||
|
||||
public void SetCoordinates(double x1, double y1, double x2, double y2, double tlx, double tly, double brx, double bry)
|
||||
{
|
||||
leftMercator = x1;
|
||||
topMercator = y1;
|
||||
rightMercator = x2;
|
||||
bottomMercator = y2;
|
||||
|
||||
leftLongitude = tlx;
|
||||
rightLongitude = brx;
|
||||
topLatitude = tly;
|
||||
bottomLatitude = bry;
|
||||
|
||||
width = rightLongitude - leftLongitude;
|
||||
height = bottomLatitude - topLatitude;
|
||||
|
||||
mercatorWidth = rightMercator - leftMercator;
|
||||
mercatorHeight = bottomMercator - topMercator;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6036b77012379cd4f817092bdac723e1
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,45 @@
|
||||
/* INFINITY CODE 2013-2019 */
|
||||
/* http://www.infinity-code.com */
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
/// <summary>
|
||||
/// Class of POI instance.
|
||||
/// </summary>
|
||||
public class RealWorldTerrainPOIItem : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// The title of the POI.
|
||||
/// </summary>
|
||||
public string title;
|
||||
|
||||
/// <summary>
|
||||
/// Longitude.
|
||||
/// </summary>
|
||||
public double x;
|
||||
|
||||
/// <summary>
|
||||
/// Latitude.
|
||||
/// </summary>
|
||||
public double y;
|
||||
|
||||
/// <summary>
|
||||
/// Altitude
|
||||
/// </summary>
|
||||
public float altitude;
|
||||
|
||||
/// <summary>
|
||||
/// Sets POI prefs.
|
||||
/// </summary>
|
||||
/// <param name="poi">Reference to POI.</param>
|
||||
public void SetPrefs(RealWorldTerrainPOI poi)
|
||||
{
|
||||
title = poi.title;
|
||||
x = poi.x;
|
||||
y = poi.y;
|
||||
altitude = poi.altitude;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 374f4970e8d22fd42a12bb3c64287f73
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
/* INFINITY CODE 2013-2019 */
|
||||
/* http://www.infinity-code.com */
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace InfinityCode.RealWorldTerrain
|
||||
{
|
||||
[AddComponentMenu("")]
|
||||
public class RealWorldTerrainRoadArchitectNode : MonoBehaviour
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0dffe5af2a2b3ff44b95e808bdbab653
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
Reference in New Issue
Block a user