private void Update3DMarkers() { if (OnlineMapsMarker3DManager.instance == null) { return; } if (control.cl == null) { return; } int zoom = map.zoom; double tlx, tly, brx, bry; map.GetCorners(out tlx, out tly, out brx, out bry); double ttlx, ttly, tbrx, tbry; map.projection.CoordinatesToTile(tlx, tly, zoom, out ttlx, out ttly); map.projection.CoordinatesToTile(brx, bry, zoom, out tbrx, out tbry); Bounds bounds = control.cl.bounds; float bestYScale = OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry); foreach (OnlineMapsMarker3D marker in OnlineMapsMarker3DManager.instance) { marker.Update(map, control, bounds, tlx, tly, brx, bry, zoom, ttlx, ttly, tbrx, tbry, bestYScale); } }
/// <summary> /// Updates marker instance. /// </summary> /// <param name="tlx">Longitude of top-left corner of the map</param> /// <param name="tly">Latitude of top-left corner of the map</param> /// <param name="brx">Longitude of bottom-right corner of the map</param> /// <param name="bry">Latitude of bottom-right corner of the map</param> /// <param name="zoom">Zoom of the map</param> public override void Update(double tlx, double tly, double brx, double bry, int zoom) { double ttlx, ttly, tbrx, tbry; map.GetTileCorners(out ttlx, out ttly, out tbrx, out tbry, zoom); float bestYScale = OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry); Update(control.meshFilter.sharedMesh.bounds, tlx, tly, brx, bry, zoom, ttlx, ttly, tbrx, tbry, bestYScale); }
/// <summary> /// Updates marker instance. /// </summary> /// <param name="tlx">Longitude of top-left corner of the map</param> /// <param name="tly">Latitude of top-left corner of the map</param> /// <param name="brx">Longitude of bottom-right corner of the map</param> /// <param name="bry">Latitude of bottom-right corner of the map</param> /// <param name="zoom">Zoom of the map</param> public override void Update(double tlx, double tly, double brx, double bry, int zoom) { double ttlx, ttly, tbrx, tbry; map.GetTileCorners(out ttlx, out ttly, out tbrx, out tbry, zoom); float bestYScale = OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry); Update(OnlineMaps.instance, OnlineMapsControlBase3D.instance, OnlineMapsControlBase3D.instance.cl.bounds, tlx, tly, brx, bry, zoom, ttlx, ttly, tbrx, tbry, bestYScale); }
private void UpdateCameraPosition() { if (rotation.x > maxRotationX) { rotation.x = maxRotationX; } else if (rotation.x < 0) { rotation.x = 0; } float rx = 90 - rotation.x; if (rx > 89.9) { rx = 89.9f; } double px = Math.Cos(rx * Mathf.Deg2Rad) * distance; double py = Math.Sin(rx * Mathf.Deg2Rad) * distance; double pz = Math.Cos(rotation.y * Mathf.Deg2Rad) * px; px = Math.Sin(rotation.y * Mathf.Deg2Rad) * px; Vector3 targetPosition = transform.position; Vector3 offset = new Vector3(sizeInScene.x / -2, 0, sizeInScene.y / 2); if (OnlineMapsElevationManagerBase.useElevation) { double tlx, tly, brx, bry; map.GetCorners(out tlx, out tly, out brx, out bry); float yScale = OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry); if (adjustTo == OnlineMapsCameraAdjust.maxElevationInArea) { offset.y = OnlineMapsElevationManagerBase.instance.GetMaxElevation(yScale); } else { offset.y = OnlineMapsElevationManagerBase.GetElevation(targetPosition.x, targetPosition.z, yScale, tlx, tly, brx, bry); } } offset.Scale(transform.lossyScale); targetPosition += transform.rotation * offset; Vector3 oldPosition = activeCamera.transform.position; Vector3 newPosition = transform.rotation * new Vector3((float)px, (float)py, (float)pz) + targetPosition; activeCamera.transform.position = newPosition; activeCamera.transform.LookAt(targetPosition); if (oldPosition != newPosition && OnCameraControl != null) { OnCameraControl(); } }
private void Update3DMarkers() { OnlineMapsMarker3DManager manager = control.marker3DManager; if (manager == null || !manager.enabled) { return; } if (control.cl == null) { return; } int zoom = map.zoom; double tlx, tly, brx, bry; map.GetCorners(out tlx, out tly, out brx, out bry); double ttlx, ttly, tbrx, tbry; map.projection.CoordinatesToTile(tlx, tly, zoom, out ttlx, out ttly); map.projection.CoordinatesToTile(brx, bry, zoom, out tbrx, out tbry); int maxX = 1 << zoom; bool isEntireWorld = map.buffer.renderState.width == maxX * OnlineMapsUtils.tileSize; if (isEntireWorld && Math.Abs(tlx - brx) < 180) { if (tlx < 0) { brx += 360; tbrx += maxX; } else { tlx -= 360; ttlx -= maxX; } } Bounds bounds = control.meshFilter.sharedMesh.bounds; float bestYScale = OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry); for (int i = manager.Count - 1; i >= 0; i--) { OnlineMapsMarker3D marker = manager[i]; if (marker.manager == null) { marker.manager = manager; } marker.Update(bounds, tlx, tly, brx, bry, zoom, ttlx, ttly, tbrx, tbry, bestYScale); } }
private void Update() { double lookProgress = progress + 0.001; double tiltProgress = progress + 0.001; Point position = GetPointByProgress(progress); Point lookPosition = GetPointByProgress(lookProgress); Point tiltPosition = GetPointByProgress(tiltProgress); speed += accelerationCurve.Evaluate(speed / maxSpeed) * Time.deltaTime; if (speed > lookPosition.relativeSpeed * maxSpeed) { speed = lookPosition.relativeSpeed * maxSpeed; } double offset = Time.deltaTime * speed / 3600; progress += offset / totalDistance; double p1x, p1y, p2x, p2y; map.projection.CoordinatesToTile(position.longitude, position.latitude, map.zoom, out p1x, out p1y); map.projection.CoordinatesToTile(lookPosition.longitude, lookPosition.latitude, map.zoom, out p2x, out p2y); targetRotation = (float)OnlineMapsUtils.Angle2D(p1x, p1y, p2x, p2y); map.projection.CoordinatesToTile(tiltPosition.longitude, tiltPosition.latitude, map.zoom, out p2x, out p2y); float tiltRotation = (float)OnlineMapsUtils.Angle2D(p1x, p1y, p2x, p2y); tilt = tiltRotation - airplane.transform.rotation.eulerAngles.y; Vector3 p = OnlineMapsTileSetControl.instance.GetWorldPosition(position.longitude, position.latitude); altitude = position.relativeAltitude * maxAltitude; float elevation = OnlineMapsElevationManagerBase.GetUnscaledElevation(p.x, p.z); p.x = -1024; float zoom = altitudeZoomCurve.Evaluate(altitude / maxAltitude); p.y = Mathf.Max(altitude, elevation) * OnlineMapsElevationManagerBase.GetBestElevationYScale(); p.z = 1024; airplane.transform.position = p; airplane.transform.rotation = Quaternion.Euler(0, Mathf.LerpAngle(airplane.transform.rotation.eulerAngles.y, targetRotation, Time.deltaTime), 0); float s = 1 / Mathf.Pow(2, 15 - map.floatZoom); transform.localScale = new Vector3(s, s, s); internalGO.transform.localRotation = Quaternion.Euler(tilt, 0, 0); map.SetPositionAndZoom(position.longitude, position.latitude, zoom); OnlineMapsCameraOrbit.instance.rotation = new Vector2(OnlineMapsCameraOrbit.instance.rotation.x, airplane.transform.rotation.eulerAngles.y + 90); }
/// <summary> /// Converts geographical coordinates to position in world space with elevation. /// </summary> /// <param name="lng">Longitude</param> /// <param name="lat">Laatitude</param> /// <param name="tlx">Top-left longitude.</param> /// <param name="tly">Top-left latitude.</param> /// <param name="brx">Bottom-right longitude.</param> /// <param name="bry">Bottom-right latitude.</param> /// <returns>Position in world space.</returns> public Vector3 GetWorldPositionWithElevation(double lng, double lat, double tlx, double tly, double brx, double bry) { double mx, my; GetPosition(lng, lat, out mx, out my); mx = -mx / map.width * sizeInScene.x; my = my / map.height * sizeInScene.y; float y = OnlineMapsElevationManagerBase.GetElevation(mx, my, OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry), tlx, tly, brx, bry); Vector3 offset = transform.rotation * new Vector3((float)mx, y, (float)my); offset.Scale(map.transform.lossyScale); return(map.transform.position + offset); }
private void Start() { map = OnlineMaps.instance; control = OnlineMapsTileSetControl.instance; elevationManager = OnlineMapsElevationManagerBase.instance; double tlx, tly, brx, bry; map.GetCorners(out tlx, out tly, out brx, out bry); Vector3 position = control.GetWorldPosition(map.position); position.y = altitude; if (elevationManager != null) { position.y *= OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry) * elevationManager.scale; } gameObject.transform.position = position; map.GetPosition(out px, out py); }
public override Vector2 GetScreenPosition(double lng, double lat) { double px, py; GetPosition(lng, lat, out px, out py); px /= map.buffer.renderState.width; py /= map.buffer.renderState.height; double cpx = -sizeInScene.x * px; double cpy = sizeInScene.y * py; double tlx, tly, brx, bry; map.GetCorners(out tlx, out tly, out brx, out bry); float elevationScale = OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry); float elevation = OnlineMapsElevationManagerBase.GetElevation(cpx, cpy, elevationScale, tlx, tly, brx, bry); Vector3 worldPos = transform.position + transform.rotation * new Vector3((float)(cpx * transform.lossyScale.x), elevation * transform.lossyScale.y, (float)(cpy * transform.lossyScale.z)); Camera cam = activeCamera != null? activeCamera: Camera.main; return(cam.WorldToScreenPoint(worldPos)); }
void Update() { const float maxTilt = 50; if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A)) { tilt -= Time.deltaTime * tiltSpeed * maxTilt; } else if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D)) { tilt += Time.deltaTime * tiltSpeed * maxTilt; } else if (tilt != 0) { float tiltOffset = Time.deltaTime * tiltSpeed * maxTilt; if (Mathf.Abs(tilt) > tiltOffset) { tilt -= tiltOffset * Mathf.Sign(tilt); } else { tilt = 0; } } tilt = Mathf.Clamp(tilt, -maxTilt, maxTilt); container.transform.localRotation = Quaternion.Euler(tilt, 0, 0); if (Math.Abs(tilt) > float.Epsilon) { transform.Rotate(Vector3.up, tilt * rotateSpeed * Time.deltaTime); } double tlx, tly, brx, bry, dx, dy; map.GetTopLeftPosition(out tlx, out tly); map.GetBottomRightPosition(out brx, out bry); OnlineMapsUtils.DistanceBetweenPoints(tlx, tly, brx, bry, out dx, out dy); double mx = (brx - tlx) / dx; double my = (tly - bry) / dy; double v = (double)speed * Time.deltaTime / 3600.0; double ox = mx * v * Math.Cos(transform.rotation.eulerAngles.y * OnlineMapsUtils.Deg2Rad); double oy = my * v * Math.Sin((360 - transform.rotation.eulerAngles.y) * OnlineMapsUtils.Deg2Rad); px += ox; py += oy; map.SetPosition(px, py); Vector3 pos = transform.position; pos.y = altitude; if (elevationManager != null) { pos.y *= OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry) * elevationManager.scale; } transform.position = pos; Camera.main.transform.position = transform.position - transform.rotation * cameraOffset; Camera.main.transform.LookAt(transform); }
protected void InitLineMesh(IEnumerable points, OnlineMapsTileSetControl control, ref List <Vector3> vertices, ref List <Vector3> normals, ref List <int> triangles, ref List <Vector2> uv, float width, bool closed = false, bool optimize = true) { map.buffer.GetCorners(out tlx, out tly, out brx, out bry); if (brx < tlx) { brx += 360; } float zoomCoof = map.zoomCoof; List <Vector2> localPoints = GetLocalPoints(points, closed, optimize); List <Vector2> activePoints = new List <Vector2>(localPoints.Count); int maxX = 1 << map.zoom; float maxSize = maxX * OnlineMapsUtils.tileSize * control.sizeInScene.x / map.width; float halfSize = maxSize / 2; float lastPointX = 0; float lastPointY = 0; float sizeX = control.sizeInScene.x / zoomCoof; float sizeY = control.sizeInScene.y / zoomCoof; bestElevationYScale = OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry); if (vertices == null) { vertices = new List <Vector3>(Mathf.Max(Mathf.NextPowerOfTwo(localPoints.Count * 4), 32)); } else { vertices.Clear(); } if (normals == null) { normals = new List <Vector3>(vertices.Capacity); } else { normals.Clear(); } if (triangles == null) { triangles = new List <int>(Mathf.Max(Mathf.NextPowerOfTwo(localPoints.Count * 6), 32)); } else { triangles.Clear(); } if (uv == null) { uv = new List <Vector2>(vertices.Capacity); } else { uv.Clear(); } Vector2[] intersections = new Vector2[4]; bool needExtraPoint = false; float extraX = 0, extraY = 0; for (int i = 0; i < localPoints.Count; i++) { Vector2 p = localPoints[i]; float px = p.x; float py = p.y; if (needExtraPoint) { activePoints.Add(new Vector2(extraX, extraY)); float ox = extraX - lastPointX; if (ox > halfSize) { lastPointX += maxSize; } else if (ox < -halfSize) { lastPointX -= maxSize; } activePoints.Add(new Vector2(lastPointX, lastPointY)); needExtraPoint = false; } if (i > 0 && checkMapBoundaries) { int countIntersections = 0; float ox = px - lastPointX; while (Math.Abs(ox) > halfSize) { if (ox < 0) { px += maxSize; ox += maxSize; } else if (ox > 0) { px -= maxSize; ox -= maxSize; } } float crossTopX, crossTopY, crossLeftX, crossLeftY, crossBottomX, crossBottomY, crossRightX, crossRightY; bool hasCrossTop = OnlineMapsUtils.LineIntersection(lastPointX, lastPointY, px, py, 0, 0, sizeX, 0, out crossTopX, out crossTopY); bool hasCrossBottom = OnlineMapsUtils.LineIntersection(lastPointX, lastPointY, px, py, 0, sizeY, sizeX, sizeY, out crossBottomX, out crossBottomY); bool hasCrossLeft = OnlineMapsUtils.LineIntersection(lastPointX, lastPointY, px, py, 0, 0, 0, sizeY, out crossLeftX, out crossLeftY); bool hasCrossRight = OnlineMapsUtils.LineIntersection(lastPointX, lastPointY, px, py, sizeX, 0, sizeX, sizeY, out crossRightX, out crossRightY); if (hasCrossTop) { intersections[0] = new Vector2(crossTopX, crossTopY); countIntersections++; } if (hasCrossBottom) { intersections[countIntersections] = new Vector2(crossBottomX, crossBottomY); countIntersections++; } if (hasCrossLeft) { intersections[countIntersections] = new Vector2(crossLeftX, crossLeftY); countIntersections++; } if (hasCrossRight) { intersections[countIntersections] = new Vector2(crossRightX, crossRightY); countIntersections++; } if (countIntersections == 1) { activePoints.Add(intersections[0]); } else if (countIntersections == 2) { Vector2 lastPoint = new Vector2(lastPointX, lastPointY); int minIndex = (lastPoint - intersections[0]).sqrMagnitude < (lastPoint - intersections[1]).sqrMagnitude? 0: 1; activePoints.Add(intersections[minIndex]); activePoints.Add(intersections[1 - minIndex]); } if (hasCrossLeft) { needExtraPoint = OnlineMapsUtils.LineIntersection(lastPointX + maxSize, lastPointY, px + maxSize, py, sizeX, 0, sizeX, sizeY, out extraX, out extraY); } else if (hasCrossRight) { needExtraPoint = OnlineMapsUtils.LineIntersection(lastPointX - maxSize, lastPointY, px - maxSize, py, 0, 0, 0, sizeY, out extraX, out extraY); } } if (!checkMapBoundaries || px >= 0 && py >= 0 && px <= sizeX && py <= sizeY) { activePoints.Add(new Vector2(px, py)); } else if (activePoints.Count > 0) { DrawActivePoints(control, ref activePoints, ref vertices, ref normals, ref triangles, ref uv, width); } lastPointX = px; lastPointY = py; } if (needExtraPoint) { activePoints.Add(new Vector2(extraX, extraY)); float ox = extraX - lastPointX; if (ox > halfSize) { lastPointX += maxSize; } else if (ox < -halfSize) { lastPointX -= maxSize; } activePoints.Add(new Vector2(lastPointX, lastPointY)); } if (activePoints.Count > 0) { DrawActivePoints(control, ref activePoints, ref vertices, ref normals, ref triangles, ref uv, width); } }
private void OnDrawMarkers() { if (markersGameObjects == null) { InitMarkersMesh(0); } double tlx, tly, brx, bry; map.GetCorners(out tlx, out tly, out brx, out bry); if (brx < tlx) { brx += 360; } int zoom = map.buffer.renderState.zoom; int maxX = 1 << zoom; double tx, ty; map.projection.CoordinatesToTile(tlx, tly, zoom, out tx, out ty); float yScale = OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry); OnlineMapsControlBaseDynamicMesh tileset = control as OnlineMapsControlBaseDynamicMesh; float cx = -tileset.sizeInScene.x / map.buffer.renderState.width; float cy = tileset.sizeInScene.y / map.buffer.renderState.height; if (usedMarkers == null) { usedMarkers = new List <FlatMarker>(32); } else { for (int i = 0; i < usedMarkers.Count; i++) { usedMarkers[i].Dispose(); } usedMarkers.Clear(); } List <Texture> usedTextures = new List <Texture>(32) { OnlineMapsMarkerManager.instance.defaultTexture }; List <List <int> > usedTexturesMarkerIndex = new List <List <int> >(32) { new List <int>(32) }; int usedMarkersCount = 0; Bounds tilesetBounds = new Bounds( new Vector3(tileset.sizeInScene.x / -2, 0, tileset.sizeInScene.y / 2), new Vector3(tileset.sizeInScene.x, 0, tileset.sizeInScene.y)); IEnumerable <OnlineMapsMarker> markers = OnlineMapsMarkerManager.instance.Where(delegate(OnlineMapsMarker marker) { if (!marker.enabled || !marker.range.InRange(zoom)) { return(false); } if (OnCheckMarker2DVisibility != null) { if (!OnCheckMarker2DVisibility(marker)) { return(false); } } else if (control.checkMarker2DVisibility == OnlineMapsTilesetCheckMarker2DVisibility.pivot) { double mx, my; marker.GetPosition(out mx, out my); bool a = my > tly || my < bry || ( (mx <tlx || mx> brx) && (mx + 360 < tlx || mx + 360 > brx) && (mx - 360 < tlx || mx - 360 > brx) ); if (a) { return(false); } } return(true); }); float[] offsets = null; bool useOffsetY = false; int index = 0; if (markerComparer != null) { markers = markers.OrderBy(m => m, markerComparer); } else { markers = markers.OrderBy(m => { double mx, my; m.GetPosition(out mx, out my); return(90 - my); }); useOffsetY = OnGetFlatMarkerOffsetY != null; if (useOffsetY) { int countMarkers = markers.Count(); SortedMarker[] sortedMarkers = new SortedMarker[countMarkers]; foreach (OnlineMapsMarker marker in markers) { sortedMarkers[index++] = new SortedMarker { marker = marker, offset = OnGetFlatMarkerOffsetY(marker) }; } offsets = new float[countMarkers]; OnlineMapsMarker[] nMarkers = new OnlineMapsMarker[countMarkers]; int i = 0; foreach (SortedMarker sm in sortedMarkers.OrderBy(m => m.offset)) { nMarkers[i] = sm.marker; offsets[i] = sm.offset; i++; sm.Dispose(); } markers = nMarkers; } } if (markersVertices == null) { markersVertices = new List <Vector3>(64); } else { markersVertices.Clear(); } Vector3 tpos = control.transform.position; foreach (Mesh mesh in markersMeshes) { mesh.Clear(); } float zoomCoof = map.buffer.renderState.zoomCoof; Matrix4x4 matrix = new Matrix4x4(); int meshIndex = 0; index = -1; foreach (OnlineMapsMarker marker in markers) { index++; double fx, fy; marker.GetTilePosition(out fx, out fy); Vector2 offset = marker.GetAlignOffset(); offset *= marker.scale; fx = (fx - tx) / zoomCoof; if (fx < 0) { fx += maxX; } else if (fx > maxX) { fx -= maxX; } fx = fx * OnlineMapsUtils.tileSize - offset.x; fy = (fy - ty) / zoomCoof * OnlineMapsUtils.tileSize - offset.y; if (marker.texture == null) { marker.texture = OnlineMapsMarkerManager.instance.defaultTexture; marker.Init(); } float markerWidth = marker.texture.width * marker.scale; float markerHeight = marker.texture.height * marker.scale; float rx1 = (float)(fx * cx); float ry1 = (float)(fy * cy); float rx2 = (float)((fx + markerWidth) * cx); float ry2 = (float)((fy + markerHeight) * cy); Vector3 center = new Vector3((float)((fx + offset.x) * cx), 0, (float)((fy + offset.y) * cy)); Vector3 p1 = new Vector3(rx1 - center.x, 0, ry1 - center.z); Vector3 p2 = new Vector3(rx2 - center.x, 0, ry1 - center.z); Vector3 p3 = new Vector3(rx2 - center.x, 0, ry2 - center.z); Vector3 p4 = new Vector3(rx1 - center.x, 0, ry2 - center.z); float angle = Mathf.Repeat(marker.rotation, 1) * 360; if (Math.Abs(angle) > float.Epsilon) { matrix.SetTRS(Vector3.zero, Quaternion.Euler(0, angle, 0), Vector3.one); p1 = matrix.MultiplyPoint(p1) + center; p2 = matrix.MultiplyPoint(p2) + center; p3 = matrix.MultiplyPoint(p3) + center; p4 = matrix.MultiplyPoint(p4) + center; } else { p1 += center; p2 += center; p3 += center; p4 += center; } if (control.checkMarker2DVisibility == OnlineMapsTilesetCheckMarker2DVisibility.bounds) { Vector3 markerCenter = (p2 + p4) / 2; Vector3 markerSize = p4 - p2; if (!tilesetBounds.Intersects(new Bounds(markerCenter, markerSize))) { continue; } } float y = OnlineMapsElevationManagerBase.GetElevation((rx1 + rx2) / 2, (ry1 + ry2) / 2, yScale, tlx, tly, brx, bry); float yOffset = useOffsetY ? offsets[index] : 0; p1.y = p2.y = p3.y = p4.y = y + yOffset; int vIndex = markersVertices.Count; markersVertices.Add(p1); markersVertices.Add(p2); markersVertices.Add(p3); markersVertices.Add(p4); usedMarkers.Add(new FlatMarker(marker, p1 + tpos, p2 + tpos, p3 + tpos, p4 + tpos)); if (OnGenerateMarkerVertices != null) { OnGenerateMarkerVertices(marker, markersVertices, vIndex); } if (marker.texture == OnlineMapsMarkerManager.instance.defaultTexture) { usedTexturesMarkerIndex[0].Add(usedMarkersCount); } else { int textureIndex = usedTextures.IndexOf(marker.texture); if (textureIndex != -1) { usedTexturesMarkerIndex[textureIndex].Add(usedMarkersCount); } else { usedTextures.Add(marker.texture); usedTexturesMarkerIndex.Add(new List <int>(32)); usedTexturesMarkerIndex[usedTexturesMarkerIndex.Count - 1].Add(usedMarkersCount); } } usedMarkersCount++; if (usedMarkersCount == 16250) { SetMarkersMesh(usedMarkersCount, usedTextures, usedTexturesMarkerIndex, meshIndex); meshIndex++; markersVertices.Clear(); usedMarkersCount = 0; usedTextures.Clear(); usedTextures.Add(OnlineMapsMarkerManager.instance.defaultTexture); usedTexturesMarkerIndex.Clear(); usedTexturesMarkerIndex.Add(new List <int>(32)); } } SetMarkersMesh(usedMarkersCount, usedTextures, usedTexturesMarkerIndex, meshIndex); }
public float GetBestElevationYScale(double tlx, double tly, double brx, double bry) { return(OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry)); }
public float GetBestElevationYScale(Vector2 topLeftPosition, Vector2 bottomRightPosition) { return(OnlineMapsElevationManagerBase.GetBestElevationYScale(topLeftPosition.x, topLeftPosition.y, bottomRightPosition.x, bottomRightPosition.y)); }
/// <summary> /// Updates camera position /// </summary> public void UpdateCameraPosition() { if (rotation.x > maxRotationX) { rotation.x = maxRotationX; } else if (rotation.x < 0) { rotation.x = 0; } float rx = 90 - rotation.x; if (rx > 89.9) { rx = 89.9f; } double px = Math.Cos(rx * Mathf.Deg2Rad) * distance; double py = Math.Sin(rx * Mathf.Deg2Rad) * distance; double pz = Math.Cos(rotation.y * Mathf.Deg2Rad) * px; px = Math.Sin(rotation.y * Mathf.Deg2Rad) * px; Vector3 targetPosition; if (adjustTo == OnlineMapsCameraAdjust.gameObject && adjustToGameObject != null) { targetPosition = adjustToGameObject.transform.position; } else { targetPosition = map.transform.position; Vector3 offset = new Vector3(sizeInScene.x / -2, 0, sizeInScene.y / 2); if (OnlineMapsElevationManagerBase.useElevation) { double tlx, tly, brx, bry; map.GetCorners(out tlx, out tly, out brx, out bry); float yScale = OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry); if (adjustTo == OnlineMapsCameraAdjust.maxElevationInArea) { offset.y = OnlineMapsElevationManagerBase.instance.GetMaxElevation(yScale); } else if (adjustTo == OnlineMapsCameraAdjust.averageCenter) { float ox = sizeInScene.x / 64; float oz = sizeInScene.y / 64; offset.y = OnlineMapsElevationManagerBase.GetElevation(targetPosition.x, targetPosition.z, yScale, tlx, tly, brx, bry) * 3; offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x - ox, targetPosition.z - oz, yScale, tlx, tly, brx, bry) * 2; offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x, targetPosition.z - oz, yScale, tlx, tly, brx, bry) * 2; offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x + ox, targetPosition.z - oz, yScale, tlx, tly, brx, bry) * 2; offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x + ox, targetPosition.z, yScale, tlx, tly, brx, bry) * 2; offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x + ox, targetPosition.z + oz, yScale, tlx, tly, brx, bry) * 2; offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x, targetPosition.z + oz, yScale, tlx, tly, brx, bry) * 2; offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x - ox, targetPosition.z + oz, yScale, tlx, tly, brx, bry) * 2; offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x - ox, targetPosition.z, yScale, tlx, tly, brx, bry) * 2; ox *= 2; oz *= 2; offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x - ox, targetPosition.z - oz, yScale, tlx, tly, brx, bry); offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x, targetPosition.z - oz, yScale, tlx, tly, brx, bry); offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x + ox, targetPosition.z - oz, yScale, tlx, tly, brx, bry); offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x + ox, targetPosition.z, yScale, tlx, tly, brx, bry); offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x + ox, targetPosition.z + oz, yScale, tlx, tly, brx, bry); offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x, targetPosition.z + oz, yScale, tlx, tly, brx, bry); offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x - ox, targetPosition.z + oz, yScale, tlx, tly, brx, bry); offset.y += OnlineMapsElevationManagerBase.GetElevation(targetPosition.x - ox, targetPosition.z, yScale, tlx, tly, brx, bry); offset.y /= 27; } else { offset.y = OnlineMapsElevationManagerBase.GetElevation(targetPosition.x, targetPosition.z, yScale, tlx, tly, brx, bry); } } offset.Scale(map.transform.lossyScale); targetPosition += map.transform.rotation * offset; } Vector3 oldPosition = activeCamera.transform.position; Vector3 newPosition = map.transform.rotation * new Vector3((float)px, (float)py, (float)pz) + targetPosition; activeCamera.transform.position = newPosition; activeCamera.transform.LookAt(targetPosition); if (control.isMapDrag) { control.UpdateLastPosition(); } if (oldPosition != newPosition && OnCameraControl != null) { OnCameraControl(); } }
private void OnDrawMarkers() { if (markersGameObjects == null) { InitMarkersMesh(0); } if (markerBillboards == null) { markerBillboards = new Dictionary <int, OnlineMapsMarkerBillboard>(); } double tlx, tly, brx, bry; map.GetCorners(out tlx, out tly, out brx, out bry); if (brx < tlx) { brx += 360; } int maxX = 1 << map.buffer.renderState.zoom; double px, py; map.projection.CoordinatesToTile(tlx, tly, map.zoom, out px, out py); float yScale = OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry); Bounds mapBounds = control.cl.bounds; Vector3 positionOffset = control.transform.position - mapBounds.min; Vector3 size = mapBounds.size; size = control.transform.rotation * size; if (!control.resultIsTexture) { positionOffset.x -= size.x; } float zoomCoof = map.buffer.renderState.zoomCoof; foreach (KeyValuePair <int, OnlineMapsMarkerBillboard> billboard in markerBillboards) { billboard.Value.used = false; } foreach (OnlineMapsMarker marker in OnlineMapsMarkerManager.instance) { if (!marker.enabled || !marker.range.InRange(map.zoom)) { continue; } double mx, my; marker.GetPosition(out mx, out my); if (!((mx > tlx && mx < brx || mx + 360 > tlx && mx + 360 < brx || mx - 360 > tlx && mx - 360 < brx) && my < tly && my > bry)) { continue; } int markerHashCode = marker.GetHashCode(); OnlineMapsMarkerBillboard markerBillboard; if (!markerBillboards.ContainsKey(markerHashCode)) { markerBillboard = OnlineMapsMarkerBillboard.Create(marker); markerBillboard.transform.parent = markersGameObjects[0].transform; markerBillboard.gameObject.layer = markersGameObjects[0].layer; markerBillboards.Add(markerHashCode, markerBillboard); } else { markerBillboard = markerBillboards[markerHashCode]; } if (markerBillboard == null) { continue; } float sx = size.x / map.buffer.renderState.width * marker2DSize * marker.scale; float sz = size.z / map.buffer.renderState.height * marker2DSize * marker.scale; float s = Mathf.Max(sx, sz); #if UNITY_5_2 markerBillboard.transform.localScale = new Vector3(-s, s, s); #else markerBillboard.transform.localScale = new Vector3(s, s, s); #endif double mpx, mpy; map.projection.CoordinatesToTile(mx, my, map.buffer.renderState.zoom, out mpx, out mpy); mpx = OnlineMapsUtils.Repeat(mpx - px, 0, maxX); mpy -= py; float x = (float)(-mpx / map.width * OnlineMapsUtils.tileSize * size.x / zoomCoof + positionOffset.x); float z = (float)(mpy / map.height * OnlineMapsUtils.tileSize * size.z / zoomCoof - positionOffset.z); float y = OnlineMapsElevationManagerBase.instance != null?OnlineMapsElevationManagerBase.GetElevation(x, z, yScale, tlx, tly, brx, bry) : 0; markerBillboard.transform.localPosition = control.transform.rotation * new Vector3(x, y, z); markerBillboard.used = true; } List <int> keysForRemove = new List <int>(); foreach (KeyValuePair <int, OnlineMapsMarkerBillboard> billboard in markerBillboards) { if (!billboard.Value.used) { billboard.Value.Dispose(); keysForRemove.Add(billboard.Key); } } foreach (int key in keysForRemove) { markerBillboards.Remove(key); } }
private void UpdateMapMesh() { int zoom = map.buffer.renderState.zoom; int w1 = map.buffer.renderState.width / OnlineMapsUtils.tileSize; int h1 = map.buffer.renderState.height / OnlineMapsUtils.tileSize; int subMeshVX = 1; int subMeshVZ = 1; if (OnlineMapsElevationManagerBase.isActive) { if (w1 < elevationResolution) { subMeshVX = elevationResolution % w1 == 0 ? elevationResolution / w1 : elevationResolution / w1 + 1; } if (h1 < elevationResolution) { subMeshVZ = elevationResolution % h1 == 0 ? elevationResolution / h1 : elevationResolution / h1 + 1; } } float zoomScale = 1 - map.buffer.renderState.zoomScale / 2; double subMeshSizeX = sizeInScene.x / w1; double subMeshSizeY = sizeInScene.y / h1; double tlx, tly, brx, bry; map.buffer.GetCorners(out tlx, out tly, out brx, out bry); double px = map.buffer.renderState.longitude; double py = map.buffer.renderState.latitude; //map.GetPosition(out px, out py); double tlpx, tlpy; map.projection.CoordinatesToTile(px, py, zoom, out tlpx, out tlpy); double posX = tlpx - bufferPosition.x; double posY = tlpy - bufferPosition.y; posX -= w1 / 2d * zoomScale; posY -= h1 / 2d * zoomScale; int maxX = 1 << zoom; if (posX >= maxX) { posX -= maxX; } else if (posX < 0) { posX += maxX; } subMeshSizeX /= zoomScale; subMeshSizeY /= zoomScale; double startPosX = subMeshSizeX * posX; double startPosZ = -subMeshSizeY * posY; float yScale = OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry); int w = w1 + 2; int h = h1 + 2; Material[] materials = rendererInstance.materials; if (vertices.Length != w * h * (subMeshVX + 1) * (subMeshVZ + 1)) { ReinitMapMesh(); materials = rendererInstance.materials; } Material fMaterial = materials[0]; bool hasTraffic = fMaterial.HasProperty("_TrafficTex"); bool hasOverlayBack = fMaterial.HasProperty("_OverlayBackTex"); bool hasOverlayBackAlpha = fMaterial.HasProperty("_OverlayBackAlpha"); bool hasOverlayFront = fMaterial.HasProperty("_OverlayFrontTex"); bool hasOverlayFrontAlpha = fMaterial.HasProperty("_OverlayFrontAlpha"); float minY = float.PositiveInfinity; float maxY = float.NegativeInfinity; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { UpdateMapSubMesh( x, y, w, h, subMeshSizeX, subMeshSizeY, subMeshVX, subMeshVZ, startPosX, startPosZ, yScale, tlx, tly, brx, bry, materials, ref minY, ref maxY, hasTraffic, hasOverlayBack, hasOverlayBackAlpha, hasOverlayFront, hasOverlayFrontAlpha ); } } tilesetMesh.vertices = vertices; tilesetMesh.uv = uv; tilesetMesh.RecalculateBounds(); if (OnlineMapsElevationManagerBase.isActive || firstUpdate) { if (meshCollider != null) { if (firstUpdate || elevationManager.zoomRange.InRange(zoom)) { colliderWithElevation = true; if (colliderType == OnlineMapsColliderType.fullMesh) { if (meshCollider.sharedMesh != null) { OnlineMapsUtils.Destroy(meshCollider.sharedMesh); } meshCollider.sharedMesh = Instantiate(tilesetMesh) as Mesh; } else { UpdateSimpleMeshCollider(yScale, tlx, tly, brx, bry); } } else if (colliderWithElevation) { colliderWithElevation = false; if (colliderType == OnlineMapsColliderType.fullMesh) { if (meshCollider.sharedMesh != null) { OnlineMapsUtils.Destroy(meshCollider.sharedMesh); } meshCollider.sharedMesh = Instantiate(tilesetMesh) as Mesh; } else { UpdateSimpleMeshCollider(yScale, tlx, tly, brx, bry); } } } else if (boxCollider != null) { boxCollider.center = new Vector3(-sizeInScene.x / 2, (minY + maxY) / 2, sizeInScene.y / 2); boxCollider.size = new Vector3(sizeInScene.x, colliderType == OnlineMapsColliderType.box ? maxY - minY : 0, sizeInScene.y); } firstUpdate = false; } if (OnMeshUpdated != null) { OnMeshUpdated(); } }
/// <summary> /// Creates a new building, based on Open Street Map. /// </summary> /// <param name="container">Reference to OnlineMapsBuildings.</param> /// <param name="way">Way of building.</param> /// <param name="nodes">Nodes obtained from Open Street Maps.</param> /// <returns>Building instance.</returns> public static OnlineMapsBuildingBase Create(OnlineMapsBuildings container, OnlineMapsOSMWay way, Dictionary <string, OnlineMapsOSMNode> nodes) { if (CheckIgnoredBuildings(way)) { return(null); } if (usedNodes == null) { usedNodes = new List <OnlineMapsOSMNode>(32); } else { usedNodes.Clear(); } way.GetNodes(nodes, usedNodes); List <Vector3> points = GetLocalPoints(usedNodes); if (points.Count < 3) { return(null); } if (points[0] == points[points.Count - 1]) { points.RemoveAt(points.Count - 1); } if (points.Count < 3) { return(null); } for (int i = 0; i < points.Count; i++) { int prev = i - 1; if (prev < 0) { prev = points.Count - 1; } int next = i + 1; if (next >= points.Count) { next = 0; } float a1 = OnlineMapsUtils.Angle2D(points[prev], points[i]); float a2 = OnlineMapsUtils.Angle2D(points[i], points[next]); if (Mathf.Abs(a1 - a2) < 5) { points.RemoveAt(i); i--; } } if (points.Count < 3) { return(null); } Vector4 cp = new Vector4(float.MaxValue, float.MaxValue, float.MinValue, float.MinValue); for (int i = 0; i < points.Count; i++) { Vector3 point = points[i]; if (point.x < cp.x) { cp.x = point.x; } if (point.z < cp.y) { cp.y = point.z; } if (point.x > cp.z) { cp.z = point.x; } if (point.z > cp.w) { cp.w = point.z; } } Vector3 centerPoint = new Vector3((cp.z + cp.x) / 2, 0, (cp.y + cp.w) / 2); for (int i = 0; i < points.Count; i++) { points[i] -= centerPoint; } bool generateWall = true; if (way.HasTagKey("building")) { string buildingType = way.GetTagValue("building"); if (buildingType == "roof") { generateWall = false; } } float baseHeight = 15; float roofHeight = 0; OnlineMapsBuildingMaterial material = GetRandomMaterial(container); Vector2 scale = Vector2.one; if (defaultShader == null) { defaultShader = Shader.Find("Diffuse"); } GameObject houseGO = CreateGameObject(way.id); MeshRenderer renderer = houseGO.AddComponent <MeshRenderer>(); MeshFilter meshFilter = houseGO.AddComponent <MeshFilter>(); OnlineMapsBuildingBuiltIn building = houseGO.AddComponent <OnlineMapsBuildingBuiltIn>(); building.way = way; building.nodes = new List <OnlineMapsOSMNode>(usedNodes); houseGO.transform.localPosition = centerPoint; houseGO.transform.localRotation = Quaternion.Euler(Vector3.zero); houseGO.transform.localScale = Vector3.one; if (material != null) { if (material.wall != null) { building.wallMaterial = Instantiate(material.wall) as Material; } else { building.wallMaterial = new Material(defaultShader); } if (material.roof != null) { building.roofMaterial = Instantiate(material.roof) as Material; } else { building.roofMaterial = new Material(defaultShader); } scale = material.scale; } else { if (defaultWallMaterial == null) { defaultWallMaterial = new Material(defaultShader); } if (defaultRoofMaterial == null) { defaultRoofMaterial = new Material(defaultShader); } building.wallMaterial = Instantiate(defaultWallMaterial) as Material; building.roofMaterial = Instantiate(defaultRoofMaterial) as Material; } RoofType roofType = RoofType.flat; AnalizeHouseTags(container, way, ref building.wallMaterial, ref building.roofMaterial, ref baseHeight); AnalizeHouseRoofType(way, ref baseHeight, ref roofType, ref roofHeight); building.mesh = new Mesh { name = way.id }; meshFilter.sharedMesh = building.mesh; renderer.sharedMaterials = new [] { building.wallMaterial, building.roofMaterial }; Vector2 centerCoords = Vector2.zero; float minCX = float.MaxValue, minCY = float.MaxValue, maxCX = float.MinValue, maxCY = float.MinValue; foreach (OnlineMapsOSMNode node in usedNodes) { Vector2 nodeCoords = node; centerCoords += nodeCoords; if (nodeCoords.x < minCX) { minCX = nodeCoords.x; } if (nodeCoords.y < minCY) { minCY = nodeCoords.y; } if (nodeCoords.x > maxCX) { maxCX = nodeCoords.x; } if (nodeCoords.y > maxCY) { maxCY = nodeCoords.y; } } building.id = way.id; building.initialZoom = OnlineMaps.instance.buffer.lastState.floatZoom; building.centerCoordinates = new Vector2((maxCX + minCX) / 2, (maxCY + minCY) / 2); building.boundsCoords = new Bounds(building.centerCoordinates, new Vector3(maxCX - minCX, maxCY - minCY)); int wallVerticesCount = (points.Count + 1) * 2; int roofVerticesCount = points.Count; int verticesCount = wallVerticesCount + roofVerticesCount; int countTriangles = wallVerticesCount * 3; if (vertices == null) { vertices = new List <Vector3>(verticesCount); } else { vertices.Clear(); } if (uvs == null) { uvs = new List <Vector2>(verticesCount); } else { uvs.Clear(); } if (wallTriangles == null) { wallTriangles = new List <int>(countTriangles); } else { wallTriangles.Clear(); } if (roofTriangles == null) { roofTriangles = new List <int>(); } else { roofTriangles.Clear(); } double tlx, tly, brx, bry; OnlineMaps.instance.buffer.GetCorners(out tlx, out tly, out brx, out bry); baseHeight *= OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry) * OnlineMapsBuildings.instance.heightScale; if (generateWall) { building.CreateHouseWall(points, baseHeight, building.wallMaterial, scale); } building.CreateHouseRoof(points, baseHeight, roofHeight, roofType); if (building.hasErrors) { OnlineMapsUtils.Destroy(building.gameObject); return(null); } building.mesh.vertices = vertices.ToArray(); building.mesh.uv = uvs.ToArray(); building.mesh.subMeshCount = 2; building.mesh.SetTriangles(wallTriangles.ToArray(), 0); building.mesh.SetTriangles(roofTriangles.ToArray(), 1); building.mesh.RecalculateBounds(); building.mesh.RecalculateNormals(); if (container.generateColliders) { building.buildingCollider = houseGO.AddComponent <MeshCollider>(); (building.buildingCollider as MeshCollider).sharedMesh = building.mesh; } return(building); }
/// <summary> /// Updates marker instance. /// </summary> /// <param name="map">Reference to the map</param> /// <param name="control">Reference to the control</param> /// <param name="bounds">Bounds of the map mesh</param> /// <param name="tlx">Longitude of top-left corner of the map</param> /// <param name="tly">Latitude of top-left corner of the map</param> /// <param name="brx">Longitude of bottom-right corner of the map</param> /// <param name="bry">Latitude of bottom-right corner of the map</param> /// <param name="zoom">Zoom of the map</param> /// <param name="ttlx">Tile X of top-left corner of the map</param> /// <param name="ttly">Tile Y of top-left corner of the map</param> /// <param name="tbrx">Tile X of bottom-right corner of the map</param> /// <param name="tbry">Tile Y of bottom-right corner of the map</param> /// <param name="bestYScale">Best y scale for current map view</param> public void Update(OnlineMaps map, OnlineMapsControlBase3D control, Bounds bounds, double tlx, double tly, double brx, double bry, int zoom, double ttlx, double ttly, double tbrx, double tbry, float bestYScale) { if (!enabled) { return; } if (instance == null) { Init(map.transform); } if (!range.InRange(zoom)) { visible = false; } else if (OnCheckMapBoundaries != null) { visible = OnCheckMapBoundaries(); } else if (checkMapBoundaries) { if (latitude > tly || latitude < bry) { visible = false; } else if (tlx < brx && (longitude < tlx || longitude > brx)) { visible = false; } else if (tlx > brx && longitude < tlx && longitude > brx) { visible = false; } else { visible = true; } } else { visible = true; } if (!visible) { return; } if (_prefab != prefab) { Reinit(tlx, tly, brx, bry, zoom); } double mx, my; map.projection.CoordinatesToTile(longitude, latitude, zoom, out mx, out my); int maxX = 1 << zoom; double sx = tbrx - ttlx; double mpx = mx - ttlx; if (sx < 0) { sx += maxX; } if (checkMapBoundaries) { if (mpx < 0) { mpx += maxX; } else if (mpx > maxX) { mpx -= maxX; } } else { double dx1 = Math.Abs(mpx - ttlx); double dx2 = Math.Abs(mpx - tbrx); double dx3 = Math.Abs(mpx - tbrx + maxX); if (dx1 > dx2 && dx1 > dx3) { mpx += maxX; } } double px = mpx / sx; double pz = (ttly - my) / (ttly - tbry); _relativePosition = new Vector3((float)px, 0, (float)pz); OnlineMapsTileSetControl tsControl = control as OnlineMapsTileSetControl; if (tsControl != null) { px = -tsControl.sizeInScene.x / 2 - (px - 0.5) * tsControl.sizeInScene.x; pz = tsControl.sizeInScene.y / 2 + (pz - 0.5) * tsControl.sizeInScene.y; } else { Vector3 center = bounds.center; Vector3 size = bounds.size; px = center.x - (px - 0.5) * size.x / map.transform.lossyScale.x - map.transform.position.x; pz = center.z + (pz - 0.5) * size.z / map.transform.lossyScale.z - map.transform.position.z; } Vector3 oldPosition = instance.transform.localPosition; float y = 0; if (altitude.HasValue) { float yScale = OnlineMapsElevationManagerBase.GetBestElevationYScale(tlx, tly, brx, bry); y = altitude.Value; if (altitudeType == OnlineMapsAltitudeType.relative && tsControl != null) { y += OnlineMapsElevationManagerBase.GetUnscaledElevation(px, pz, tlx, tly, brx, bry); } y *= yScale; if (tsControl != null) { if (OnlineMapsElevationManagerBase.instance.bottomMode == OnlineMapsElevationBottomMode.minValue) { y -= OnlineMapsElevationManagerBase.instance.minValue * bestYScale; } y *= OnlineMapsElevationManagerBase.instance.scale; } } else if (tsControl != null) { y = OnlineMapsElevationManagerBase.GetElevation(px, pz, bestYScale, tlx, tly, brx, bry); } Vector3 newPosition = new Vector3((float)px, y, (float)pz); if (sizeType == SizeType.meters) { double dx, dy; OnlineMapsUtils.DistanceBetweenPoints(tlx, tly, brx, bry, out dx, out dy); dx = tsControl.sizeInScene.x / dx / 1000; dy = tsControl.sizeInScene.y / dy / 1000; double d = (dx + dy) / 2 * scale; float fd = (float)d; instance.transform.localScale = new Vector3(fd, fd, fd); } if (oldPosition != newPosition) { instance.transform.localPosition = newPosition; } }