From 5c6e1b958acf89e49cc0122b3e3d3094d8dcd848 Mon Sep 17 00:00:00 2001 From: Owen Kaluza Date: Tue, 7 Jan 2025 16:34:25 +1100 Subject: [PATCH 1/4] Support clip with planes in earth_shader --- src/accessvis/data/earth_shader.frag | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/accessvis/data/earth_shader.frag b/src/accessvis/data/earth_shader.frag index b56e0a7..1217134 100644 --- a/src/accessvis/data/earth_shader.frag +++ b/src/accessvis/data/earth_shader.frag @@ -93,6 +93,9 @@ vec3 rgb2hsv(vec3 c) void main(void) { + //Clip planes in X/Y/Z + if (any(lessThan(vVertex, uClipMin)) || any(greaterThan(vVertex, uClipMax))) discard; + float alpha = 1.0; //fColour.a; float mask = 0.0; vec4 tColour = texture(uTexture, vTexCoord); From 76d9b7b3f9ffe294f96f9db49370a028d267c0d2 Mon Sep 17 00:00:00 2001 From: Owen Kaluza Date: Tue, 7 Jan 2025 16:35:57 +1100 Subject: [PATCH 2/4] Add lonlat_to_3D prefer lon,lat,height coord order Keep old function for back compatibility --- src/accessvis/earth.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/accessvis/earth.py b/src/accessvis/earth.py index 047a7f8..4efca1b 100644 --- a/src/accessvis/earth.py +++ b/src/accessvis/earth.py @@ -222,19 +222,32 @@ def paste_image(fn, xpos, ypos, out): out[yoff : yoff + col.shape[1], xoff : xoff + col.shape[0]] = col -def latlon_to_3D(lat, lon, alt=0): +def lonlat_to_3D(lon, lat, alt=0): """ Convert lat/lon coord to 3D coordinate for visualisation Uses simple spherical earth rather than true ellipse see http://www.mathworks.de/help/toolbox/aeroblks/llatoecefposition.html https://stackoverflow.com/a/20360045 """ - return latlon_to_3D_true(lat, lon, alt, flattening=0.0) + return lonlat_to_3D_true(lon, lat, alt, flattening=0.0) -def latlon_to_3D_true(lat, lon, alt=0, flattening=1.0 / 298.257223563): +def latlon_to_3D(lat, lon, alt=0, flattening=0.0): """ - Convert lat/lon coord to 3D coordinate for visualisation + Convert lon/lat coord to 3D coordinate for visualisation + + Provided for backwards compatibility as main function now reverses arg order of + (lat, lon) to (lon, lat) + """ + return lonlat_to_3D_true(lon, lat, alt, flattening) + + +def lonlat_to_3D_true(lon, lat, alt=0, flattening=1.0 / 298.257223563): + """ + Convert lon/lat coord to 3D coordinate for visualisation + Now using longitude, latitude, altitude order for more natural argument order + longitude=x, latitude=y, altitude=z + Uses flattening factor for elliptical earth see http://www.mathworks.de/help/toolbox/aeroblks/llatoecefposition.html https://stackoverflow.com/a/20360045 From 11ff68ee15636c15d99c7ed03cab7d84d35096df Mon Sep 17 00:00:00 2001 From: Owen Kaluza Date: Tue, 7 Jan 2025 16:37:20 +1100 Subject: [PATCH 3/4] Added camera class for animation --- src/accessvis/earth.py | 55 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/accessvis/earth.py b/src/accessvis/earth.py index 4efca1b..11e89f1 100644 --- a/src/accessvis/earth.py +++ b/src/accessvis/earth.py @@ -1248,6 +1248,61 @@ def lookat(lv, pos, lookat=None, up=None): lv.translation(tr) +class Camera: + lv = None + + def __init__(self, lv): + self.lv = lv + + def look_at(self, pos, at=None, up=None): + lookat(self.lv, pos, at, up) + + def lerpto(self, pos, L): + # Lerp using current camera orientation as start point + pos0 = self.lv.camera(quiet=True) + return self.lerp(pos0, pos) + + def lerp(self, pos0, pos1, L): + """ + Linearly Interpolate between two camera positions/orientations and + set the camera to the resulting position/orientation + """ + final = {} + for key in ["translate", "rotate", "focus"]: + val0 = np.array(pos0[key]) + val1 = np.array(pos1[key]) + res = val0 + (val1 - val0) * L + if len(res) > 3: + # Normalise quaternion + res = res / np.linalg.norm(res) + final[key] = res.tolist() + + self.lv.camera(final) + + def flyto(self, pos, steps, stop=False): + # Fly using current camera orientation as start point + pos0 = self.lv.camera(quiet=True) + return self.fly(pos0, pos, steps, stop) + + def fly(self, pos0, pos1, steps, stop=False): + # self.lv.translation(*tr0) + # self.lv.rotation(*rot0) + self.lv.camera(pos0) + self.lv.render() + + for i in range(steps): + if stop and i > stop: + break + L = i / (steps - 1) + self.lerp(pos0, pos1, L) + self.lv.render() + + def pause(self, frames=50): + # Render pause + for i in range(frames): + self.lv.render() + + def sun_light( time=None, now=False, From ee09adc50585e9c51b501fae2b03d2ec8692cce1 Mon Sep 17 00:00:00 2001 From: Owen Kaluza Date: Tue, 21 Jan 2025 12:04:29 +1100 Subject: [PATCH 4/4] Removed, this will go in lavavu instead --- src/accessvis/earth.py | 100 ----------------------------------------- 1 file changed, 100 deletions(-) diff --git a/src/accessvis/earth.py b/src/accessvis/earth.py index 11e89f1..4502dcb 100644 --- a/src/accessvis/earth.py +++ b/src/accessvis/earth.py @@ -1203,106 +1203,6 @@ def vector_align(v1, v2, lvformat=True): return qr -def lookat(lv, pos, lookat=None, up=None): - """ - Set the camera with a position coord and lookat coord - - Parameters - ---------- - lv : lavavu.Viewer - The viewer object - pos : list/numpy.ndarray - Camera position in world coords - lookat : list/numpy.ndarray - Look at position in world coords, defaults to model origin - up : list/numpy.ndarray - Up vector, defaults to Y axis [0,1,0] - """ - - # Use the origin from viewer if no target provided - if lookat is None: - lookat = lv["focus"] - else: - lv["focus"] = lookat - - # Default to Y-axis up vector - if up is None: - up = np.array([0, 1, 0]) - - # Calculate the rotation matrix - heading = np.array(pos) - np.array(lookat) - zd = normalise(heading) - xd = normalise(np.cross(up, zd)) - yd = normalise(np.cross(zd, xd)) - q = quat.from_rotation_matrix(np.array([xd, yd, zd])) - q = q.normalized() - - # Apply the rotation - lv.rotation(q.x, q.y, q.z, q.w) - - # Translate back by heading vector length in Z - # (model origin in lavavu takes care of lookat offset) - tr = [0, 0, -magnitude(np.array(pos) - np.array(lookat))] - - # Apply translation - lv.translation(tr) - - -class Camera: - lv = None - - def __init__(self, lv): - self.lv = lv - - def look_at(self, pos, at=None, up=None): - lookat(self.lv, pos, at, up) - - def lerpto(self, pos, L): - # Lerp using current camera orientation as start point - pos0 = self.lv.camera(quiet=True) - return self.lerp(pos0, pos) - - def lerp(self, pos0, pos1, L): - """ - Linearly Interpolate between two camera positions/orientations and - set the camera to the resulting position/orientation - """ - final = {} - for key in ["translate", "rotate", "focus"]: - val0 = np.array(pos0[key]) - val1 = np.array(pos1[key]) - res = val0 + (val1 - val0) * L - if len(res) > 3: - # Normalise quaternion - res = res / np.linalg.norm(res) - final[key] = res.tolist() - - self.lv.camera(final) - - def flyto(self, pos, steps, stop=False): - # Fly using current camera orientation as start point - pos0 = self.lv.camera(quiet=True) - return self.fly(pos0, pos, steps, stop) - - def fly(self, pos0, pos1, steps, stop=False): - # self.lv.translation(*tr0) - # self.lv.rotation(*rot0) - self.lv.camera(pos0) - self.lv.render() - - for i in range(steps): - if stop and i > stop: - break - L = i / (steps - 1) - self.lerp(pos0, pos1, L) - self.lv.render() - - def pause(self, frames=50): - # Render pause - for i in range(frames): - self.lv.render() - - def sun_light( time=None, now=False,