Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 50 additions & 44 deletions src/components/CanvasGeometry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export function CanvasGeometry() {
},
})

const [texture, setTexture] = useState<THREE.DataTexture | THREE.Data3DTexture | null>(null)
const [texture, setTexture] = useState<THREE.DataTexture | THREE.Data3DTexture | null>(null) //Main Texture
const [shape, setShape] = useState<THREE.Vector3 | THREE.Vector3>(new THREE.Vector3(2, 2, 2))
const [timeSeriesLocs,setTimeSeriesLocs] = useState<TimeSeriesLocs>({uv:new THREE.Vector2(.5,.5), normal:new THREE.Vector3(0,0,1)})
const [valueScales,setValueScales] = useState({maxVal:1,minVal:-1})
Expand All @@ -57,7 +57,6 @@ export function CanvasGeometry() {
setColormap(GetColorMapTexture(colormap,cmap));
},[cmap, colormap])


useEffect(() => {
if (variable != "Default") {
//Need to add a check somewhere here to swap to 2D or 3D based on shape. Probably export two variables from GetArray
Expand All @@ -74,7 +73,6 @@ export function CanvasGeometry() {
console.error("Invalid texture type returned from ArrayToTexture");
setTexture(null);
}
// norrow down type before using it!
if (
typeof scaling === 'object' &&
'maxVal' in scaling &&
Expand All @@ -98,53 +96,61 @@ export function CanvasGeometry() {

return (
<>

<div className='canvas'>
<Canvas shadows
frameloop="demand"
>

<Center top position={[-1, 0, 1]}/>
{plotter == "volume" && <>
<DataCube volTexture={texture} shape={shape} colormap={colormap}/>
<mesh onClick={() => setShowTimeSeries(true)}>
<UVCube shape={shape} setTimeSeriesLocs={setTimeSeriesLocs}/>
</mesh>

</>}
{plotter == "point-cloud" && <PointCloud textures={{texture,colormap}} />}

<OrbitControls minPolarAngle={0} maxPolarAngle={Math.PI / 2} enablePan={false}/>
<Environment preset="city" />
{showTimeSeries && <>
<Center top position={[-1, 0, 1]}/>

{/* Volume Plots */}
{plotter == "volume" && <>
<DataCube volTexture={texture} shape={shape} colormap={colormap}/>
<mesh onClick={() => setShowTimeSeries(true)}>
<UVCube shape={shape} setTimeSeriesLocs={setTimeSeriesLocs}/>
</mesh>

<TimeSeries timeSeriesLocs={timeSeriesLocs} DSInfo={{variable:variable, storePath:storeURL}} scaling={{...valueScales,colormap}}/>
<Html
fullscreen
style={{
pointerEvents: 'none', // Prevents capturing mouse events
}}
</>}

{/* Point Clouds Plots */}
{plotter == "point-cloud" && <PointCloud textures={{texture,colormap}} />}


{/* Time Series Plots */}
{showTimeSeries && <>

<TimeSeries timeSeriesLocs={timeSeriesLocs} DSInfo={{variable:variable, storePath:storeURL}} scaling={{...valueScales,colormap}}/>
<Html
fullscreen
style={{
pointerEvents: 'none', // Prevents capturing mouse events
}}
>
{/* Stand in button to remove time-series stuff */}
<button style={{
position: 'absolute',
bottom: '100px',
right: '100px',
padding: '8px 16px',
backgroundColor: '#3498db',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
pointerEvents: 'auto'

}}
onClick={()=>setShowTimeSeries(false)}
>
<button style={{
position: 'absolute',
bottom: '100px',
right: '100px',
padding: '8px 16px',
backgroundColor: '#3498db',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
pointerEvents: 'auto'

}}
onClick={()=>setShowTimeSeries(false)}
>
Hide Time Series
</button>
</Html>

</>}
Hide Time Series
</button>
</Html>
</>}



<OrbitControls minPolarAngle={0} maxPolarAngle={Math.PI / 2} enablePan={false}/>
<Environment preset="city" />

</Canvas>
</div>
<Leva theme={lightTheme} />
Expand Down
71 changes: 33 additions & 38 deletions src/components/PlotObjects.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ interface DataCubeProps {
volTexture: THREE.Data3DTexture | THREE.DataTexture | null,
shape : THREE.Vector3,
colormap: THREE.DataTexture

}

interface PCProps {
Expand All @@ -27,8 +26,6 @@ interface PCProps {

export const DataCube = ({ volTexture, shape, colormap }: DataCubeProps ) => {
const meshRef = useRef<THREE.Mesh>(null);
// const materialRef = useRef<THREE.ShaderMaterial | null>(null);
// const { invalidate } = useThree();
const { threshold, steps, flip, xMax,xMin,yMax,yMin,zMax,zMin } = useControls({
threshold: {
value: 0, // Default value
Expand Down Expand Up @@ -94,25 +91,25 @@ export const DataCube = ({ volTexture, shape, colormap }: DataCubeProps ) => {

// We need to check if moving this outside of useMemo means it's creating a ton of materials. This was how it was done in THREE Journey when I was doing that, so I know it's not stricly speaking wrong
const shaderMaterial = new THREE.ShaderMaterial({
glslVersion: THREE.GLSL3,
uniforms: {
map: { value: volTexture },
cmap:{value: colormap},
cameraPos: { value: new THREE.Vector3() },
threshold: {value: threshold},
scale: {value: shape},
flatBounds:{value: new THREE.Vector4(xMin,xMax,yMin,yMax)},
vertBounds:{value: new THREE.Vector2(zMin,zMax)},
steps: { value: steps },
flip: {value: flip }
},
vertexShader,
fragmentShader,
transparent: true,
blending: THREE.NormalBlending,
depthWrite: false,
side: THREE.BackSide,
});
glslVersion: THREE.GLSL3,
uniforms: {
map: { value: volTexture },
cmap:{value: colormap},
cameraPos: { value: new THREE.Vector3() },
threshold: {value: threshold},
scale: {value: shape},
flatBounds:{value: new THREE.Vector4(xMin,xMax,yMin,yMax)},
vertBounds:{value: new THREE.Vector2(zMin,zMax)},
steps: { value: steps },
flip: {value: flip }
},
vertexShader,
fragmentShader,
transparent: true,
blending: THREE.NormalBlending,
depthWrite: false,
side: THREE.BackSide,
});

// Use geometry once, avoid recreating -- Using a sphere to avoid the weird angles you get with cube
const geometry = useMemo(() => new THREE.IcosahedronGeometry(4, 8), []);
Expand Down Expand Up @@ -142,8 +139,6 @@ export const UVCube = ({shape,setTimeSeriesLocs} : {shape:THREE.Vector3, setTime
normal
})
}


return (
<mesh scale={shape} onClick={TimeSeriesLocs}>
<boxGeometry args={[1, 1, 1]} />
Expand All @@ -168,7 +163,7 @@ export const PointCloud = ({textures} : {textures:PCProps} )=>{
}
}
)
// Extract data and shape from Data3DTexture
//Extract data and shape from Data3DTexture
const { data, width, height, depth } = useMemo(() => {
if (!(texture instanceof THREE.Data3DTexture)) {
console.warn('Provided texture is not a Data3DTexture');
Expand All @@ -188,15 +183,15 @@ export const PointCloud = ({textures} : {textures:PCProps} )=>{
const aspectRatio = width/height
let depthRatio = depth/height;
depthRatio = depthRatio > 10 ? 10: depthRatio;
// Generate grid points based on texture shape
//Generate grid points based on texture shape
for (let z = 0; z < depth; z++) {
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const index = x + y * width + z * width * height;
const value = (data as number[])[index] || 0;
// Skip zero or invalid values if needed
if (value > 0) {
// Normalize coordinates to [-0.5, 0.5] range
// Normalize coordinates acceptable range
const px = ((x / (width - 1)) - 0.5) * aspectRatio;
const py = (y / (height - 1)) - 0.5;
const pz = ((z / (depth - 1)) - 0.5) * depthRatio;
Expand All @@ -221,17 +216,17 @@ export const PointCloud = ({textures} : {textures:PCProps} )=>{


const shaderMaterial = new THREE.ShaderMaterial({
glslVersion: THREE.GLSL3,
uniforms: {
pointSize: {value: pointScale},
cmap: {value: colormap},
scalePoints:{value: scalePoints}
},
vertexShader:pointVert,
fragmentShader:pointFrag,
blending: THREE.NoBlending,
depthWrite: true,
});
glslVersion: THREE.GLSL3,
uniforms: {
pointSize: {value: pointScale},
cmap: {value: colormap},
scalePoints:{value: scalePoints}
},
vertexShader:pointVert,
fragmentShader:pointFrag,
blending: THREE.NoBlending,
depthWrite: true,
});

return (
<points geometry={geometry} material={shaderMaterial} />
Expand Down
Loading
Loading