/// <summary> /// Calculates 4 vectors required to draw the pixel block on terrain /// </summary> /// <param name = "col" > Column retrieved from DataCube</param> /// <param name = "row" > Row retrieved from DataCube</param> /// <remarks> /// Returns corners in Unity coordinates /// </remarks> Vector2[] CalculateCorners(float col, float row) { Vector2[,] coordCube = DataCube.coordCube; int dataHeight = coordCube.GetLength(1); int dataWidth = coordCube.GetLength(0); // Pixel indexing is addressed between indices, so 0-1 refers to pixel 1. // Last pixel can be indexed by addressing second to last indice. int selectedRow = Mathf.RoundToInt(Mathf.Clamp(row, 1, dataHeight - 2)); int selectedCol = Mathf.RoundToInt(Mathf.Clamp(col, 1, dataWidth - 2)); // Find nearest point from user selection corresponding to 4 square regions from // center point. Think with respect to satellite long/lat, // which pixel are we looking at with respect to user selection? // Each region is averaged out to encompass full surrounding pixels to which // values are passed onto raycasting based on where the pixel block will be located // due to change in region because of origin difference per terrain. Vector2[] corners = new Vector2[4]; corners[0] = (coordCube[selectedCol, selectedRow] + coordCube[selectedCol - 1, selectedRow - 1] + coordCube[selectedCol - 1, selectedRow] + coordCube[selectedCol, selectedRow - 1]) / 4; corners[1] = (coordCube[selectedCol, selectedRow] + coordCube[selectedCol + 1, selectedRow - 1] + coordCube[selectedCol + 1, selectedRow] + coordCube[selectedCol, selectedRow - 1]) / 4; corners[2] = (coordCube[selectedCol, selectedRow] + coordCube[selectedCol + 1, selectedRow + 1] + coordCube[selectedCol + 1, selectedRow] + coordCube[selectedCol, selectedRow + 1]) / 4; corners[3] = (coordCube[selectedCol, selectedRow] + coordCube[selectedCol - 1, selectedRow + 1] + coordCube[selectedCol - 1, selectedRow] + coordCube[selectedCol, selectedRow + 1]) / 4; for (int i = 0; i < 4; i++) { corners[i] = CoordinateEquations.latlongToUnity(corners[i]); } return(corners); }
void Update() { //going from unity mars latlon to unity coords Vector2 init_unitycoords = CoordinateEquations.latlongToUnity(initial_longitude, initial_latitude); Vector2 final_unitycoords = CoordinateEquations.latlongToUnity(final_longitude, final_latitude); float y = (initial_altitudeKm - marsRadKm) * 1000; initial_position = new Vector3(init_unitycoords.x, y, init_unitycoords.y); final_position = new Vector3(final_unitycoords.x, y, final_unitycoords.y); }
/// <summary> /// Reads in the lat long, converts to unity x z and draws resulting path /// </summary> private void LoadData() { //Read in the latitude and longitude coords of rover traversal points TextAsset traversalLong = Resources.Load("traversal_long") as TextAsset; TextAsset traversalLat = Resources.Load("traversal_lat") as TextAsset; //turn the text of each into an array- each element is a string lat/long string[] longLines = traversalLong.text.Split('\n'); string[] latLines = traversalLat.text.Split('\n'); //number of lat/long coords int dataLen = longLines.Length; lineRenderer.positionCount = dataLen; //will hold float values- this step converts the string lat long to floats float[] longFloats = new float[dataLen]; float[] latFloats = new float[dataLen]; for (int i = 0; i < dataLen; i++) { longFloats[i] = float.Parse(longLines[i]); latFloats[i] = float.Parse(latLines[i]); } //convert lat/long to unity coords float[] unityXCoords = new float[dataLen]; float[] unityZCoords = new float[dataLen]; for (int i = 0; i < dataLen; i++) { Vector2 unityCoords = CoordinateEquations.latlongToUnity(latFloats[i], longFloats[i]); //TODO- need to make sure this method is correct! unityXCoords[i] = unityCoords.x; unityZCoords[i] = unityCoords.y; } // interpolate coordinate data by multiplier int multiplier = 15; Vector2[] interpUnityCoords = new Vector2[dataLen * multiplier]; for (int i = 0; i < dataLen - 1; i++) { interpUnityCoords[i * multiplier] = new Vector2(unityXCoords[i], unityZCoords[i]); for (int k = 1; k < multiplier; k++) { interpUnityCoords[i * multiplier + k] = Vector2.Lerp(interpUnityCoords[i * multiplier], new Vector2(unityXCoords[i + 1], unityZCoords[i + 1]), k / (float)multiplier); } } interpUnityCoords[(dataLen - 1) * multiplier] = new Vector2(unityXCoords[dataLen - 1], unityZCoords[dataLen - 1]); //draw lines based on unity coords int interpDataLen = dataLen * multiplier; lineRenderer.SetVertexCount(interpDataLen); Vector3[] points = new Vector3[interpDataLen]; for (int i = 0; i < interpDataLen; i++) { Ray r = new Ray(interpUnityCoords[i].x * Vector3.right + Vector3.up * 1000 + interpUnityCoords[i].y * Vector3.forward, Vector3.down); RaycastHit hitinfo; int terrainLayerMask = 1 << TerrainManager.terrainLayer; //cast rays only against colliders in layer "terrain" if (Physics.Raycast(r, out hitinfo, Mathf.Infinity, terrainLayerMask)) { points[i] = hitinfo.point + Vector3.up * .1f; } else { if (i > 0) { points[i] = new Vector3(interpUnityCoords[i].x, points[i - 1].y, interpUnityCoords[i].y); } else { points[i] = new Vector3(interpUnityCoords[i].x, -5f, interpUnityCoords[i].y); } } } lineRenderer.SetPositions(points); }
// Update is called once per frame void Update() { Vector2 unityXZ = CoordinateEquations.latlongToUnity(latlong); transform.position = new Vector3(unityXZ.x, transform.position.y, unityXZ.y); }