feat: add more features to the room, open/close window interaction
This commit is contained in:
Binary file not shown.
Binary file not shown.
BIN
public/room.fbx
BIN
public/room.fbx
Binary file not shown.
29
src/App.tsx
29
src/App.tsx
@@ -6,19 +6,21 @@ import {
|
|||||||
type ThreeEvent,
|
type ThreeEvent,
|
||||||
useLoader,
|
useLoader,
|
||||||
} from "@react-three/fiber";
|
} from "@react-three/fiber";
|
||||||
import { OrbitControls } from "@react-three/drei";
|
import { OrbitControls, useAnimations } from "@react-three/drei";
|
||||||
import { FBXLoader } from "three/examples/jsm/Addons.js";
|
import { FBXLoader } from "three/examples/jsm/Addons.js";
|
||||||
import { Vector3 } from "three";
|
import { LoopOnce, Vector3 } from "three";
|
||||||
|
|
||||||
import "./App.css";
|
import "./App.css";
|
||||||
|
|
||||||
const Room = () => {
|
const Room = () => {
|
||||||
const controls = useRef<ComponentRef<typeof OrbitControls>>(null);
|
const controls = useRef<ComponentRef<typeof OrbitControls>>(null);
|
||||||
const room = useLoader(FBXLoader, "/room.fbx");
|
const room = useLoader(FBXLoader, "/room.fbx");
|
||||||
|
const { mixer } = useAnimations(room.animations, room);
|
||||||
const [focus, setFocus] = useState<string | null>(null);
|
const [focus, setFocus] = useState<string | null>(null);
|
||||||
|
|
||||||
const cameraPosition = useRef<Vector3 | null>(null);
|
const cameraPosition = useRef<Vector3 | null>(null);
|
||||||
const cameraTarget = useRef<Vector3>(new Vector3(0, 1, 0));
|
const cameraTarget = useRef<Vector3>(new Vector3(0, 1, 0));
|
||||||
|
const [windowState, setWindowState] = useState(false);
|
||||||
|
|
||||||
const { camera } = useThree();
|
const { camera } = useThree();
|
||||||
|
|
||||||
@@ -45,6 +47,28 @@ const Room = () => {
|
|||||||
|
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
|
if (e.object.name.includes("Window")) {
|
||||||
|
const clip = room.animations.find(
|
||||||
|
(x) => x.name === "LowerWindow|LowerWindowAction",
|
||||||
|
);
|
||||||
|
if (!clip) throw "no animation";
|
||||||
|
|
||||||
|
const action = mixer.clipAction(clip);
|
||||||
|
if (action.isRunning()) return;
|
||||||
|
action.clampWhenFinished = true;
|
||||||
|
action.setLoop(LoopOnce, 1);
|
||||||
|
action.timeScale = windowState ? -1 : 1;
|
||||||
|
if (windowState) {
|
||||||
|
action.paused = false;
|
||||||
|
action.time = action.getClip().duration;
|
||||||
|
} else {
|
||||||
|
action.reset();
|
||||||
|
}
|
||||||
|
action.play();
|
||||||
|
|
||||||
|
setWindowState(!windowState);
|
||||||
|
}
|
||||||
|
|
||||||
if (e.object.name.includes("Poster") && e.object.name !== focus) {
|
if (e.object.name.includes("Poster") && e.object.name !== focus) {
|
||||||
const objectPos = new Vector3();
|
const objectPos = new Vector3();
|
||||||
const objectDir = new Vector3();
|
const objectDir = new Vector3();
|
||||||
@@ -77,6 +101,7 @@ const Room = () => {
|
|||||||
<OrbitControls
|
<OrbitControls
|
||||||
ref={controls}
|
ref={controls}
|
||||||
target={[0, 1, 0]}
|
target={[0, 1, 0]}
|
||||||
|
minPolarAngle={Math.PI / 5}
|
||||||
maxPolarAngle={Math.PI / 2}
|
maxPolarAngle={Math.PI / 2}
|
||||||
enablePan={false}
|
enablePan={false}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user