Skip to content

Commit

Permalink
tried to implement crosshair but fail miserably
Browse files Browse the repository at this point in the history
  • Loading branch information
paoloose committed Dec 6, 2024
1 parent 34fdef4 commit 3bbc674
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 9 deletions.
6 changes: 5 additions & 1 deletion app/src/pages/Gallery3D/Experience.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export const Experience = ({ gallery, onLoad }: ExperienceProps) => {
key={slot.ref}
imageUrl={res || "/assets/empty_slot.png"}
vertices={slot.v}
title={slot.title}
description={slot.description}
/>
);
}
Expand All @@ -52,6 +54,8 @@ export const Experience = ({ gallery, onLoad }: ExperienceProps) => {
position={slot.v[0]}
glbUrl={res ?? "/assets/3d/invisible.glb"}
rotation={[0, Math.PI / 4, 0]}
title={slot.title}
description={slot.description}
scale={[slot.props.scale, slot.props.scale, slot.props.scale] as any}
rotate={slot.props.rotate as boolean}
/>
Expand Down Expand Up @@ -81,6 +85,7 @@ export const Experience = ({ gallery, onLoad }: ExperienceProps) => {
{/* <Ground /> */}
<Ecctrl
type='dynamic'
mode="CameraBasedMovement" // character's rotation will follow camera's rotation in this mode
animated={false}
camCollision={false} // disable camera collision detect (useless in FP mode)
camInitDis={-0.01}
Expand All @@ -96,7 +101,6 @@ export const Experience = ({ gallery, onLoad }: ExperienceProps) => {
springK={0.3}
autoBalanceSpringK={0.3}
position={[0, 2, 0]}
mode="CameraBasedMovement" // character's rotation will follow camera's rotation in this mode
>
<BallCollider args={[0.8]} />
</Ecctrl>
Expand Down
31 changes: 28 additions & 3 deletions app/src/pages/Gallery3D/components/gallery/DynamicPainting.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { useMemo } from "react";
import { useTexture } from "@react-three/drei";
import * as THREE from 'three';
import { useExperienceStore } from "@/stores/useExperienceStore";

export function DynamicPainting({ imageUrl, vertices }: { imageUrl: string; vertices: readonly (readonly number[])[] }) {
type DynamicPaintingProps = {
imageUrl: string;
vertices: readonly (readonly number[])[];
title?: string;
description?: string;
};

export function DynamicPainting({ imageUrl, vertices, title, description }: DynamicPaintingProps) {
const texture = useTexture(imageUrl);

// Define a geometry using the provided vertices
Expand Down Expand Up @@ -32,8 +40,25 @@ export function DynamicPainting({ imageUrl, vertices }: { imageUrl: string; vert

return (
<>
<mesh geometry={geometry}>
<meshBasicMaterial map={texture} side={THREE.DoubleSide} />
<mesh
geometry={geometry}
onPointerMove={() => {
}}
onPointerEnter={() => {
useExperienceStore.setState({
hovering: {
title: title ?? '',
description: description ?? '',
}
})
}}
onPointerLeave={() => {
useExperienceStore.setState({
hovering: null
})
}}
>
<meshBasicMaterial map={texture} side={THREE.DoubleSide} visible />
</mesh>
</>
);
Expand Down
18 changes: 18 additions & 0 deletions app/src/pages/Gallery3D/components/gallery/DynamicSculpture.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@ import { useMemo, useRef } from "react";
import { useGLTF } from "@react-three/drei";
import { useFrame } from "@react-three/fiber";
import * as THREE from "three";
import { useExperienceStore } from "@/stores/useExperienceStore";

interface DynamicSculptureProps {
glbUrl: string;
position: readonly [number, number, number];
rotation: [number, number, number];
scale?: readonly [number, number, number];
rotate?: boolean;
title?: string;
description?: string;
}

export function DynamicSculpture({
glbUrl,
position,
rotation,
scale = [1, 1, 1],
title,
description,
rotate = false,
}: DynamicSculptureProps) {
const { scene: model } = useGLTF(glbUrl);
Expand All @@ -34,6 +39,19 @@ export function DynamicSculpture({
position={[position[0], position[1] + 1.9, position[2]]}
rotation={rotation}
scale={[.8, .8, .8]}
onPointerEnter={() => {
useExperienceStore.setState({
hovering: {
title: title ?? '',
description: description ?? '',
}
})
}}
onPointerLeave={() => {
useExperienceStore.setState({
hovering: null
})
}}
>
<primitive object={copiedModel} />
</group>
Expand Down
2 changes: 1 addition & 1 deletion app/src/pages/Gallery3D/components/gallery/Scene.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useLoader } from '@react-three/fiber';
import { RigidBody } from '@react-three/rapier';
import { useEffect, useRef } from 'react';
import { useEffect } from 'react';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';

type SceneRoomProps = {
Expand Down
24 changes: 20 additions & 4 deletions app/src/pages/Gallery3D/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import { AppIcon } from '@/components/AppIcon';
import { createXRStore, XR } from '@react-three/xr';
import { EcctrlJoystick } from 'ecctrl';
import { useFinePointer } from '@/hooks/useFinePointer';
import { IconBadgeVr, IconMaximize, IconMaximizeOff } from '@tabler/icons-react';
import { IconBadgeVr, IconCrosshair, IconMaximize, IconMaximizeOff } from '@tabler/icons-react';
import { useFullscreen } from '@mantine/hooks';
import { useExperienceStore } from '@/stores/useExperienceStore';
import { Ray } from 'three';
import * as THREE from 'three';

type Gallery3DProps = {
gallery: string;
Expand All @@ -20,6 +23,8 @@ export const Gallery3D = ({ gallery, withTopOffset }: Gallery3DProps) => {
const [loading, setLoading] = useState(true);
const hasMouse = useFinePointer();
const { ref, toggle, fullscreen } = useFullscreen();
const dontShowTopOffset = !withTopOffset || fullscreen;
const hovering = useExperienceStore((s) => s.hovering);

useEffect(() => {
document.body.style.backgroundColor = '#000';
Expand All @@ -34,7 +39,7 @@ export const Gallery3D = ({ gallery, withTopOffset }: Gallery3DProps) => {
{
(!hasMouse && !loading) && (
<>
<Button size='compact-sm' onClick={() => store.enterVR()} style={{ height: 32, position: 'absolute', zIndex: 69, top: withTopOffset ? 78 : 8, left: '3.5rem' }}>
<Button size='compact-sm' onClick={() => store.enterVR()} style={{ height: 32, position: 'absolute', zIndex: 69, top: dontShowTopOffset ? 8 : 78, left: '3.5rem' }}>
<IconBadgeVr />
</Button>
<EcctrlJoystick />
Expand All @@ -43,15 +48,26 @@ export const Gallery3D = ({ gallery, withTopOffset }: Gallery3DProps) => {
}
{
!loading && (
<Button size='compact-sm' onClick={() => toggle()} style={{ height: 32, position: 'absolute', zIndex: 69, top: withTopOffset ? 78 : 8, left: 8 }}>
<Button size='compact-sm' onClick={() => toggle()} style={{ height: 32, position: 'absolute', zIndex: 69, top: dontShowTopOffset ? 8 : 78, left: 8 }}>
{
fullscreen ? <IconMaximizeOff /> : <IconMaximize />
}
</Button>
)
}
<div id='crosshair' style={{ position: 'absolute', zIndex: 69, top: '50%', left: '50%', transform: 'translate(-50%, -50%)', opacity: 0.4, pointerEvents: 'none' }}>
<IconCrosshair />
</div>
{
hovering?.title && (
<div style={{ position: 'absolute', zIndex: 69, bottom: 60, left: '50%', transform: 'translateX(-50%)', padding: '12px', backgroundColor: 'rgba(0,0,0,.5)', borderRadius: '8px' }}>
<Text size='xl' fw={700} c='white'>{hovering.title}</Text>
<Text size='sm' c='white'>{hovering.description}</Text>
</div>
)
}
<Canvas
camera={{ fov: 70 }}
camera={{ fov: 60 }}
onPointerDown={(e) => {
if (e.pointerType === 'mouse') {
(e.target as HTMLCanvasElement).requestPointerLock();
Expand Down
17 changes: 17 additions & 0 deletions app/src/stores/useExperienceStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { create } from 'zustand';

type HoveringInformation = {
title: string;
description: string;
};

interface ExperienceStoreState {
// Represents a sidebar element being dragged.
hovering: HoveringInformation | null,
}

export const useExperienceStore = create<ExperienceStoreState>()(
(set, get) => ({
hovering: null,
}),
);

0 comments on commit 3bbc674

Please sign in to comment.