From bbd45bedc80e5ca7b07a56f17e6c0a0f61d34652 Mon Sep 17 00:00:00 2001 From: Jeran Date: Wed, 22 Apr 2026 09:45:50 +0200 Subject: [PATCH 1/8] First Square Locations Commit. Need to test with sub-extents --- src/components/plots/FlatMap.tsx | 7 +- src/components/plots/Sphere.tsx | 7 +- src/components/plots/TransectMeshes.tsx | 85 +++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 src/components/plots/TransectMeshes.tsx diff --git a/src/components/plots/FlatMap.tsx b/src/components/plots/FlatMap.tsx index a5909fe1..9d86eca7 100644 --- a/src/components/plots/FlatMap.tsx +++ b/src/components/plots/FlatMap.tsx @@ -13,7 +13,7 @@ import { coarsenFlatArray, GetCurrentArray, GetTimeSeries, parseUVCoords, deg2ra import { evaluate_cmap } from 'js-colormaps-es'; import { useCoordBounds } from '@/hooks/useCoordBounds'; import { GetFrag } from '../textures'; - +import { SquareMeshes } from './TransectMeshes'; interface InfoSettersProps{ setLoc: React.Dispatch>; setShowInfo: React.Dispatch>; @@ -138,7 +138,9 @@ const FlatMap = ({textures, infoSetters} : {textures : THREE.DataTexture[] | THR const tsID = `${dimCoords[0]}_${dimCoords[1]}` const tsObj = { color:evaluate_cmap(getColorIdx()/10,"Paired"), - data:tempTS + data:tempTS, + normal, + uv: tsUV, } incrementColorIdx(); updateTimeSeries({ [tsID] : tsObj}) @@ -203,6 +205,7 @@ const FlatMap = ({textures, infoSetters} : {textures : THREE.DataTexture[] | THR return ( <> + + selectTS && HandleTimeSeries(e)}/> diff --git a/src/components/plots/TransectMeshes.tsx b/src/components/plots/TransectMeshes.tsx new file mode 100644 index 00000000..1ebb9ed7 --- /dev/null +++ b/src/components/plots/TransectMeshes.tsx @@ -0,0 +1,85 @@ +import React, {useMemo} from 'react' +import * as THREE from 'three' +import { usePlotStore } from '@/GlobalStates/PlotStore' +import { useGlobalStore } from '@/GlobalStates/GlobalStore' +import { useShallow } from 'zustand/shallow' +import { deg2rad } from '@/utils/HelperFuncs' +import { useCoordBounds } from '@/hooks/useCoordBounds' + +function remapToXYZ(uv: THREE.Vector2, latBounds: number[], lonBounds: number[]): THREE.Vector3 { + const u = 1 - uv.x; + const v = uv.y; + const lon = u * (deg2rad(lonBounds[1]) - deg2rad(lonBounds[0])) + deg2rad(lonBounds[0]); + const lat = v * (deg2rad(latBounds[1]) - deg2rad(latBounds[0])) + deg2rad(latBounds[0]); + return new THREE.Vector3( + Math.cos(lat) * Math.cos(lon), + Math.sin(lat), + Math.cos(lat) * Math.sin(lon) + ); +} + +export const SquareMeshes = () => { + const {timeSeries, dataShape, shape} = useGlobalStore(useShallow(state=>({ + timeSeries:state.timeSeries, + dataShape: state.dataShape, + shape: state.shape + }))) + const {plotType} = usePlotStore(useShallow(state=>({ + plotType: state.plotType + }))) + const {lonBounds, latBounds} = useCoordBounds() + const meshes: THREE.Mesh[] = useMemo(() =>{ + const meshes = [] + const circum = 2*Math.PI; + const dataLen = dataShape.length; + const xSteps = dataShape[dataLen-1]; + const ySteps = dataShape[dataLen-2]; + const normedXExtent = (lonBounds[1]-lonBounds[0])/360 + const normedYExtent = (latBounds[1]-latBounds[0])/180 + const yScale = circum/2/ySteps * normedYExtent; + const isSphere = plotType == "sphere"; + let xScale = circum/xSteps * normedXExtent; + const aspect = shape.x/shape.y; + + for (const [tsID, tsObj] of Object.entries(timeSeries)){ + const {normal, uv, color} = tsObj + if (normal.z != 1) break; // Flat versions only do time. Skip all of these. + let geometry = new THREE.PlaneGeometry(xScale, yScale) + // Color from 0-255 to 0-1 range + const thisColor = color.map((c: number) => Math.pow((c/255), 2.2)) // Gamma correct the color for better visibility + const material = new THREE.MeshBasicMaterial({color: new THREE.Color(...thisColor)}) + const mesh = new THREE.Mesh(geometry, material) + let position: THREE.Vector3; + const uvX = (Math.floor(uv.x * xSteps)+0.5)/xSteps; + const uvY = (Math.floor(uv.y * ySteps)+0.5)/ySteps; + if (isSphere){ + const xScaler = Math.cos((uvY - 0.5) * Math.PI); + position = remapToXYZ(new THREE.Vector2(uvX, uvY), latBounds, lonBounds) + // Rotate the plane where position is also normal vector + mesh.lookAt(position.x*2, position.y*2, position.z*2) + geometry.scale(xScaler, 1, 1) + } + else{ + const posX = (uvX-0.5)*2; + const posY = (uvY-0.5)*aspect/2; + position = new THREE.Vector3(posX, posY, 0.1) + geometry.scale(0.25,0.25,1) + } + mesh.position.set(position.x, position.y, position.z) + meshes.push(mesh) + } + return meshes + }, [timeSeries, plotType, latBounds, lonBounds]) + + return ( + <> + {meshes.map((mesh, idx) => )} + + ) +} + +export const ColumnMeshes = () => { + return ( +
TransectMeshes
+ ) +} From a64c2343cb43f05e3922922a37dbbaddff8b45ab Mon Sep 17 00:00:00 2001 From: Jeran Date: Fri, 8 May 2026 13:59:21 +0200 Subject: [PATCH 2/8] stash column progress --- src/components/plots/TransectMeshes.tsx | 49 ++++++++++++++++++++----- src/utils/ExportCanvas.tsx | 2 - 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/components/plots/TransectMeshes.tsx b/src/components/plots/TransectMeshes.tsx index 1ebb9ed7..ca39eb49 100644 --- a/src/components/plots/TransectMeshes.tsx +++ b/src/components/plots/TransectMeshes.tsx @@ -1,4 +1,4 @@ -import React, {useMemo} from 'react' +import React, {useEffect, useMemo} from 'react' import * as THREE from 'three' import { usePlotStore } from '@/GlobalStates/PlotStore' import { useGlobalStore } from '@/GlobalStates/GlobalStore' @@ -39,14 +39,14 @@ export const SquareMeshes = () => { const yScale = circum/2/ySteps * normedYExtent; const isSphere = plotType == "sphere"; let xScale = circum/xSteps * normedXExtent; - const aspect = shape.x/shape.y; + const aspect = shape.y/shape.x; for (const [tsID, tsObj] of Object.entries(timeSeries)){ const {normal, uv, color} = tsObj - if (normal.z != 1) break; // Flat versions only do time. Skip all of these. + if (normal.z != 1) break; // It should never be, but just in case, flat versions only do time. Skip all of these. let geometry = new THREE.PlaneGeometry(xScale, yScale) // Color from 0-255 to 0-1 range - const thisColor = color.map((c: number) => Math.pow((c/255), 2.2)) // Gamma correct the color for better visibility + const thisColor = color.map((c: number) => Math.pow((c/255), 2.2)) // Gamma correct the color const material = new THREE.MeshBasicMaterial({color: new THREE.Color(...thisColor)}) const mesh = new THREE.Mesh(geometry, material) let position: THREE.Vector3; @@ -61,7 +61,7 @@ export const SquareMeshes = () => { } else{ const posX = (uvX-0.5)*2; - const posY = (uvY-0.5)*aspect/2; + const posY = (uvY-0.5)*aspect; position = new THREE.Vector3(posX, posY, 0.1) geometry.scale(0.25,0.25,1) } @@ -72,14 +72,45 @@ export const SquareMeshes = () => { }, [timeSeries, plotType, latBounds, lonBounds]) return ( - <> - {meshes.map((mesh, idx) => )} - + <> + {meshes.map((mesh, idx) => )} + ) } export const ColumnMeshes = () => { + const {timeSeries, dataShape, shape} = useGlobalStore(useShallow(state=>({ + timeSeries:state.timeSeries, + dataShape: state.dataShape, + shape: state.shape + }))) + const {plotType} = usePlotStore(useShallow(state=>({ + plotType: state.plotType + }))) + + const meshes: THREE.Mesh[] = useMemo(()=>{ + const meshes: THREE.Mesh[] = [] + const dataLen = dataShape.length; + const xSteps = dataShape[dataLen-1]; + const ySteps = dataShape[dataLen-2]; + for (const [tsID, tsObj] of Object.entries(timeSeries)){ + const {normal, uv, color} = tsObj + const uvX = (Math.floor(uv.x * xSteps)+0.5)/xSteps; + const uvY = (Math.floor(uv.y * ySteps)+0.5)/ySteps; + let geometry = new THREE.BoxGeometry() + + } + return meshes + + },[timeSeries, plotType]) + + useEffect(() =>{ + const aspect = shape.y/shape.x; + const depth = shape.z/shape.x; + },[meshes]) return ( -
TransectMeshes
+ <> + {meshes.map((mesh, idx) => )} + ) } diff --git a/src/utils/ExportCanvas.tsx b/src/utils/ExportCanvas.tsx index c9bb1603..ca963885 100644 --- a/src/utils/ExportCanvas.tsx +++ b/src/utils/ExportCanvas.tsx @@ -12,8 +12,6 @@ import { lerp } from 'three/src/math/MathUtils.js'; import { FFmpeg } from '@ffmpeg/ffmpeg'; import { deg2rad } from './HelperFuncs'; - - const DrawText = ( //Context and cbarlocs ctx: CanvasRenderingContext2D, From 76fb02d3388e1c8aceef67ee5bbf25d02a25811d Mon Sep 17 00:00:00 2001 From: Jeran Date: Wed, 13 May 2026 17:03:09 +0200 Subject: [PATCH 3/8] fixed 2d starting 3D --- src/components/plots/DataCube.tsx | 2 ++ src/components/plots/TransectMeshes.tsx | 32 ++++++++++++++----------- src/components/plots/UVCube.tsx | 2 ++ 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/components/plots/DataCube.tsx b/src/components/plots/DataCube.tsx index a5cf9c05..bc97a87a 100644 --- a/src/components/plots/DataCube.tsx +++ b/src/components/plots/DataCube.tsx @@ -8,6 +8,7 @@ import { invalidate, useFrame } from '@react-three/fiber'; import { deg2rad } from '@/utils/HelperFuncs'; import { useCoordBounds } from '@/hooks/useCoordBounds'; import { UVCube } from '@/components/plots' +import { ColumnMeshes } from './TransectMeshes'; interface DataCubeProps { volTexture: THREE.Data3DTexture[] | THREE.DataTexture[] | null, @@ -110,6 +111,7 @@ export const DataCube = ({ volTexture }: DataCubeProps ) => { }) return ( + diff --git a/src/components/plots/TransectMeshes.tsx b/src/components/plots/TransectMeshes.tsx index ca39eb49..3c8d4111 100644 --- a/src/components/plots/TransectMeshes.tsx +++ b/src/components/plots/TransectMeshes.tsx @@ -3,7 +3,7 @@ import * as THREE from 'three' import { usePlotStore } from '@/GlobalStates/PlotStore' import { useGlobalStore } from '@/GlobalStates/GlobalStore' import { useShallow } from 'zustand/shallow' -import { deg2rad } from '@/utils/HelperFuncs' +import { deg2rad, parseUVCoords } from '@/utils/HelperFuncs' import { useCoordBounds } from '@/hooks/useCoordBounds' function remapToXYZ(uv: THREE.Vector2, latBounds: number[], lonBounds: number[]): THREE.Vector3 { @@ -30,21 +30,17 @@ export const SquareMeshes = () => { const {lonBounds, latBounds} = useCoordBounds() const meshes: THREE.Mesh[] = useMemo(() =>{ const meshes = [] - const circum = 2*Math.PI; const dataLen = dataShape.length; const xSteps = dataShape[dataLen-1]; const ySteps = dataShape[dataLen-2]; const normedXExtent = (lonBounds[1]-lonBounds[0])/360 const normedYExtent = (latBounds[1]-latBounds[0])/180 - const yScale = circum/2/ySteps * normedYExtent; const isSphere = plotType == "sphere"; - let xScale = circum/xSteps * normedXExtent; const aspect = shape.y/shape.x; - - for (const [tsID, tsObj] of Object.entries(timeSeries)){ + for (const [_tsID, tsObj] of Object.entries(timeSeries)){ const {normal, uv, color} = tsObj if (normal.z != 1) break; // It should never be, but just in case, flat versions only do time. Skip all of these. - let geometry = new THREE.PlaneGeometry(xScale, yScale) + let geometry = new THREE.PlaneGeometry(1, 1) // Color from 0-255 to 0-1 range const thisColor = color.map((c: number) => Math.pow((c/255), 2.2)) // Gamma correct the color const material = new THREE.MeshBasicMaterial({color: new THREE.Color(...thisColor)}) @@ -53,24 +49,27 @@ export const SquareMeshes = () => { const uvX = (Math.floor(uv.x * xSteps)+0.5)/xSteps; const uvY = (Math.floor(uv.y * ySteps)+0.5)/ySteps; if (isSphere){ + const circum = 2*Math.PI; + const xScale = circum/xSteps * normedXExtent; + const yScale = circum/2/ySteps * normedYExtent; const xScaler = Math.cos((uvY - 0.5) * Math.PI); position = remapToXYZ(new THREE.Vector2(uvX, uvY), latBounds, lonBounds) // Rotate the plane where position is also normal vector mesh.lookAt(position.x*2, position.y*2, position.z*2) - geometry.scale(xScaler, 1, 1) + geometry.scale(xScale*xScaler, yScale, 1) } else{ + const sqScale = 2/xSteps const posX = (uvX-0.5)*2; - const posY = (uvY-0.5)*aspect; - position = new THREE.Vector3(posX, posY, 0.1) - geometry.scale(0.25,0.25,1) + const posY = (uvY-0.5)*2*aspect; + position = new THREE.Vector3(posX, posY, 0.001) + geometry.scale(sqScale,sqScale,1) } mesh.position.set(position.x, position.y, position.z) meshes.push(mesh) } return meshes }, [timeSeries, plotType, latBounds, lonBounds]) - return ( <> {meshes.map((mesh, idx) => )} @@ -93,10 +92,15 @@ export const ColumnMeshes = () => { const dataLen = dataShape.length; const xSteps = dataShape[dataLen-1]; const ySteps = dataShape[dataLen-2]; + const zSteps = dataShape[dataLen-3]; for (const [tsID, tsObj] of Object.entries(timeSeries)){ const {normal, uv, color} = tsObj - const uvX = (Math.floor(uv.x * xSteps)+0.5)/xSteps; - const uvY = (Math.floor(uv.y * ySteps)+0.5)/ySteps; + + if (Math.abs(normal.z) == 1) { + const newX = (Math.floor(newV.x * xSteps)+0.5)/xSteps; + const newY = (Math.floor(newV.y * ySteps)+0.5)/ySteps; + } + let geometry = new THREE.BoxGeometry() } diff --git a/src/components/plots/UVCube.tsx b/src/components/plots/UVCube.tsx index c31db838..301caa68 100644 --- a/src/components/plots/UVCube.tsx +++ b/src/components/plots/UVCube.tsx @@ -122,6 +122,8 @@ export const UVCube = ( {scale} : {scale?:THREE.Vector3} )=>{ const tsID = `${dimCoords[0]}_${dimCoords[1]}` const tsObj = { color:evaluate_cmap(getColorIdx()/10,"Paired"), + normal, + uv, data:tempTS } updateTimeSeries({ [tsID] : tsObj}) From 03b58703fc619681da1e095edd1a82f8faed586e Mon Sep 17 00:00:00 2001 From: Jeran Date: Fri, 15 May 2026 13:16:48 +0200 Subject: [PATCH 4/8] All meshes seemingly working. Time dimension doesn't work on pointcloud because it is multiplied by two in the the shader. Fixing will require additional work. Will leave for now --- src/components/plots/PointCloud.tsx | 19 +++-- src/components/plots/TransectMeshes.tsx | 70 +++++++++++++++---- .../textures/shaders/pointVertex.glsl | 10 +-- src/utils/HelperFuncs.ts | 2 + 4 files changed, 75 insertions(+), 26 deletions(-) diff --git a/src/components/plots/PointCloud.tsx b/src/components/plots/PointCloud.tsx index 2560d3bd..8b737081 100644 --- a/src/components/plots/PointCloud.tsx +++ b/src/components/plots/PointCloud.tsx @@ -7,6 +7,7 @@ import { useShallow } from 'zustand/shallow'; import { deg2rad } from '@/utils/HelperFuncs'; import { useCoordBounds } from '@/hooks/useCoordBounds'; import { UVCube } from './UVCube'; +import { ColumnMeshes } from './TransectMeshes'; interface PCProps { texture: THREE.Data3DTexture[] | null, @@ -137,10 +138,16 @@ export const PointCloud = ({textures} : {textures:PCProps} )=>{ uniforms.maskValue.value = maskValue } }, [pointSize, colormap, cOffset, cScale, valueRange, scalePoints, scaleIntensity, animProg, timeScale, xRange, yRange, fillValue, zRange, maskValue, lonBounds, latBounds]); - return ( - - - - - ); + const tsScale = dataShape[2]/500 + return ( + <> + + + + + + + + + ); } \ No newline at end of file diff --git a/src/components/plots/TransectMeshes.tsx b/src/components/plots/TransectMeshes.tsx index 3c8d4111..6d956a92 100644 --- a/src/components/plots/TransectMeshes.tsx +++ b/src/components/plots/TransectMeshes.tsx @@ -18,6 +18,51 @@ function remapToXYZ(uv: THREE.Vector2, latBounds: number[], lonBounds: number[]) ); } +function normalToPos(uv: THREE.Vector2, normal:THREE.Vector3, ratios:{depthRatio:number, aspectRatio:number}): THREE.Vector3{ + let posZ, posY, posX: number; + const {aspectRatio, depthRatio} = ratios; + if (Math.abs(normal.z) == 1){ + const flip = normal.z < 0; + const x = flip ? (1-uv.x)-0.5: (uv.x-0.5) + posX = x*2; + posY = (uv.y-0.5)*2*aspectRatio; + posZ = 0; + } else if (Math.abs(normal.y) == 1){ + const flip = normal.y > 0; + const y = flip ? (1-uv.y)-0.5: (uv.y-0.5) + posX = (uv.x-0.5)*2; + posY = 0; + posZ = y*Math.max(depthRatio,2); + } else { + const flip = normal.x > 0; + const x = flip ? (1-uv.x)-0.5: (uv.x-0.5) + posX = 0; + posY = (uv.y-0.5)*2*aspectRatio; + posZ = x*Math.max(depthRatio,2); + } + return new THREE.Vector3(posX, posY, posZ) +} + +function normalToScale(normal:THREE.Vector3, ratios:{depthRatio:number, aspectRatio:number}, steps:{xSteps:number, ySteps:number, zSteps:number}){ + let scaleZ, scaleY, scaleX: number; + const {xSteps,ySteps,zSteps} = steps; + const {aspectRatio, depthRatio} = ratios; + if (Math.abs(normal.z) == 1){ + scaleX = 2/xSteps; + scaleY = 2*aspectRatio/ySteps; + scaleZ = Math.max(depthRatio,2); + } else if (Math.abs(normal.y) == 1){ + scaleX = 2/xSteps; + scaleY = 2*aspectRatio; + scaleZ = 2*Math.max(depthRatio,2)/zSteps; + } else{ + scaleX = 2; + scaleY = 2*aspectRatio/ySteps; + scaleZ = 2*Math.max(depthRatio,2)/zSteps; + } + return new THREE.Vector3(scaleX, scaleY, scaleZ); +} + export const SquareMeshes = () => { const {timeSeries, dataShape, shape} = useGlobalStore(useShallow(state=>({ timeSeries:state.timeSeries, @@ -86,32 +131,31 @@ export const ColumnMeshes = () => { const {plotType} = usePlotStore(useShallow(state=>({ plotType: state.plotType }))) - + const meshes: THREE.Mesh[] = useMemo(()=>{ const meshes: THREE.Mesh[] = [] const dataLen = dataShape.length; const xSteps = dataShape[dataLen-1]; const ySteps = dataShape[dataLen-2]; const zSteps = dataShape[dataLen-3]; + const aspectRatio = dataShape[dataLen-2]/dataShape[dataLen-1] + const depthRatio = dataShape[dataLen-3]/dataShape[dataLen-1] for (const [tsID, tsObj] of Object.entries(timeSeries)){ const {normal, uv, color} = tsObj - - if (Math.abs(normal.z) == 1) { - const newX = (Math.floor(newV.x * xSteps)+0.5)/xSteps; - const newY = (Math.floor(newV.y * ySteps)+0.5)/ySteps; - } - - let geometry = new THREE.BoxGeometry() - + const position = normalToPos(uv, normal, {aspectRatio,depthRatio}) + const meshScale = normalToScale(normal, {aspectRatio, depthRatio}, {xSteps, ySteps, zSteps}) + const thisColor = color.map((c: number) => Math.pow((c/255), 2.2)) // Gamma correct the color + const material = new THREE.MeshBasicMaterial({color: new THREE.Color(...thisColor)}) + let geometry = new THREE.BoxGeometry(1,1,1) + geometry.scale(...meshScale.toArray()) + const mesh = new THREE.Mesh(geometry, material) + mesh.position.copy(position) + meshes.push(mesh) } return meshes },[timeSeries, plotType]) - useEffect(() =>{ - const aspect = shape.y/shape.x; - const depth = shape.z/shape.x; - },[meshes]) return ( <> {meshes.map((mesh, idx) => )} diff --git a/src/components/textures/shaders/pointVertex.glsl b/src/components/textures/shaders/pointVertex.glsl index 738c2842..b5108cdf 100644 --- a/src/components/textures/shaders/pointVertex.glsl +++ b/src/components/textures/shaders/pointVertex.glsl @@ -33,7 +33,7 @@ vec3 computePosition(int vertexID) { float px = (float(x) - (float(width)/2.)) / 500.; float py = (float(y) - (float(height)/2.)) / 500.; - float pz = (float(z) - (float(depth )/2.)) /500.; + float pz = (float(z) - (float(depth)/2.)) /500.; return vec3(px * 2.0, py * 2.0, pz * 2.0); } @@ -62,12 +62,11 @@ vec2 realCoords(vec2 uv){ } void main() { - vec2 testV = giveUV(gl_VertexID); - if (maskValue != 0 ){ + if (maskValue != 0 ){ // If using a mask, quick check if vertex is masked out before doing additional rendering vec2 newV = realCoords(giveUV(gl_VertexID)); float mask = texture(maskTexture, newV).r; bool cond = maskValue == 1 ? mask< 0.5 : mask>=0.5; - if (cond){ + if (cond){ // Masked out. Move off screen gl_Position = vec4(2.0, 2.0, 2.0, 1.0); return; } @@ -115,8 +114,5 @@ void main() { if (xCheck || zCheck || yCheck || fillCheck){ //Hide points that are clipped gl_Position = vec4(2.0, 2.0, 2.0, 1.0); } - - - } diff --git a/src/utils/HelperFuncs.ts b/src/utils/HelperFuncs.ts index f18a7ea4..e3df047a 100644 --- a/src/utils/HelperFuncs.ts +++ b/src/utils/HelperFuncs.ts @@ -130,6 +130,8 @@ export function parseUVCoords({normal,uv}:{normal:THREE.Vector3,uv:THREE.Vector2 return [uv.x, flipY ? 1-uv.y : uv.y, null] case normal.y === 1: return [1-uv.y, null, uv.x] + case normal.y === -1: + return [uv.y, null, uv.x] default: return [0,0,0] } From 21538e3f06270fb0aec243180f5ea61e99713208 Mon Sep 17 00:00:00 2001 From: Jeran Date: Fri, 15 May 2026 13:47:04 +0200 Subject: [PATCH 5/8] flipY on sphere fix --- src/components/plots/TransectMeshes.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/plots/TransectMeshes.tsx b/src/components/plots/TransectMeshes.tsx index 6d956a92..16d67956 100644 --- a/src/components/plots/TransectMeshes.tsx +++ b/src/components/plots/TransectMeshes.tsx @@ -64,10 +64,10 @@ function normalToScale(normal:THREE.Vector3, ratios:{depthRatio:number, aspectRa } export const SquareMeshes = () => { - const {timeSeries, dataShape, shape} = useGlobalStore(useShallow(state=>({ + const {timeSeries, dataShape, shape, flipY} = useGlobalStore(useShallow(state=>({ timeSeries:state.timeSeries, dataShape: state.dataShape, - shape: state.shape + shape: state.shape, flipY:state.flipY }))) const {plotType} = usePlotStore(useShallow(state=>({ plotType: state.plotType @@ -98,10 +98,14 @@ export const SquareMeshes = () => { const xScale = circum/xSteps * normedXExtent; const yScale = circum/2/ySteps * normedYExtent; const xScaler = Math.cos((uvY - 0.5) * Math.PI); - position = remapToXYZ(new THREE.Vector2(uvX, uvY), latBounds, lonBounds) + position = remapToXYZ(new THREE.Vector2(uvX, flipY ? 1-uvY : uvY), latBounds, lonBounds) // Rotate the plane where position is also normal vector - mesh.lookAt(position.x*2, position.y*2, position.z*2) + mesh.lookAt(position.x, position.y, position.z) + if (flipY) { // The fliping of the Y uv makes it think its looking backwards. So need to flip it back + geometry.scale(1, -1, 1) + } geometry.scale(xScale*xScaler, yScale, 1) + console.log(position) } else{ const sqScale = 2/xSteps From d2678750a50965a00fb287cdf30233051d48bff8 Mon Sep 17 00:00:00 2001 From: Jeran Date: Fri, 15 May 2026 14:06:03 +0200 Subject: [PATCH 6/8] Simplify --- src/components/plots/Sphere.tsx | 4 +++- src/components/plots/TransectMeshes.tsx | 8 +++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/plots/Sphere.tsx b/src/components/plots/Sphere.tsx index 2e39224c..a9eb589e 100644 --- a/src/components/plots/Sphere.tsx +++ b/src/components/plots/Sphere.tsx @@ -179,7 +179,9 @@ export const Sphere = ({textures} : {textures: THREE.Data3DTexture[] | THREE.Dat return ( <> - + + + selectTS && HandleTimeSeries(e)}/> diff --git a/src/components/plots/TransectMeshes.tsx b/src/components/plots/TransectMeshes.tsx index 16d67956..948b8a1e 100644 --- a/src/components/plots/TransectMeshes.tsx +++ b/src/components/plots/TransectMeshes.tsx @@ -89,6 +89,8 @@ export const SquareMeshes = () => { // Color from 0-255 to 0-1 range const thisColor = color.map((c: number) => Math.pow((c/255), 2.2)) // Gamma correct the color const material = new THREE.MeshBasicMaterial({color: new THREE.Color(...thisColor)}) + material.side = THREE.DoubleSide; // For flipY or to see it on otherside of sphere after clipping values + material.needsUpdate = true; const mesh = new THREE.Mesh(geometry, material) let position: THREE.Vector3; const uvX = (Math.floor(uv.x * xSteps)+0.5)/xSteps; @@ -98,14 +100,10 @@ export const SquareMeshes = () => { const xScale = circum/xSteps * normedXExtent; const yScale = circum/2/ySteps * normedYExtent; const xScaler = Math.cos((uvY - 0.5) * Math.PI); - position = remapToXYZ(new THREE.Vector2(uvX, flipY ? 1-uvY : uvY), latBounds, lonBounds) + position = remapToXYZ(new THREE.Vector2(uvX, uvY), latBounds, lonBounds) // Rotate the plane where position is also normal vector mesh.lookAt(position.x, position.y, position.z) - if (flipY) { // The fliping of the Y uv makes it think its looking backwards. So need to flip it back - geometry.scale(1, -1, 1) - } geometry.scale(xScale*xScaler, yScale, 1) - console.log(position) } else{ const sqScale = 2/xSteps From cd2d0bb121405de8cf1f328b8a68eac0c7604421 Mon Sep 17 00:00:00 2001 From: Jeran Date: Fri, 15 May 2026 14:09:15 +0200 Subject: [PATCH 7/8] insert PC into group --- src/components/plots/PointCloud.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/plots/PointCloud.tsx b/src/components/plots/PointCloud.tsx index 8b737081..dafeffa4 100644 --- a/src/components/plots/PointCloud.tsx +++ b/src/components/plots/PointCloud.tsx @@ -140,14 +140,13 @@ export const PointCloud = ({textures} : {textures:PCProps} )=>{ }, [pointSize, colormap, cOffset, cScale, valueRange, scalePoints, scaleIntensity, animProg, timeScale, xRange, yRange, fillValue, zRange, maskValue, lonBounds, latBounds]); const tsScale = dataShape[2]/500 return ( - <> - - - + + + - + ); } \ No newline at end of file From 3bb5b14e44a567fc90e57ab3045de277eab65bb5 Mon Sep 17 00:00:00 2001 From: Jeran Date: Fri, 15 May 2026 14:33:40 +0200 Subject: [PATCH 8/8] Add cleanup functions --- src/components/plots/TransectMeshes.tsx | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/components/plots/TransectMeshes.tsx b/src/components/plots/TransectMeshes.tsx index 948b8a1e..5f35d051 100644 --- a/src/components/plots/TransectMeshes.tsx +++ b/src/components/plots/TransectMeshes.tsx @@ -88,7 +88,7 @@ export const SquareMeshes = () => { let geometry = new THREE.PlaneGeometry(1, 1) // Color from 0-255 to 0-1 range const thisColor = color.map((c: number) => Math.pow((c/255), 2.2)) // Gamma correct the color - const material = new THREE.MeshBasicMaterial({color: new THREE.Color(...thisColor)}) + const material = new THREE.MeshBasicMaterial({color: new THREE.Color(...thisColor)}); material.side = THREE.DoubleSide; // For flipY or to see it on otherside of sphere after clipping values material.needsUpdate = true; const mesh = new THREE.Mesh(geometry, material) @@ -117,6 +117,15 @@ export const SquareMeshes = () => { } return meshes }, [timeSeries, plotType, latBounds, lonBounds]) + useEffect(() => { + return () => { + meshes.forEach(mesh => { + mesh.geometry.dispose() + //@ts-ignore TS thiunks this is a different material type + mesh.material.dispose() + }); + };}, [meshes] + ); return ( <> {meshes.map((mesh, idx) => )} @@ -157,7 +166,15 @@ export const ColumnMeshes = () => { return meshes },[timeSeries, plotType]) - + useEffect(() => { + return () => { + meshes.forEach(mesh => { + mesh.geometry.dispose() + //@ts-ignore TS thiunks this is a different material type + mesh.material.dispose() + }); + };}, [meshes] + ); return ( <> {meshes.map((mesh, idx) => )}