Skip to content
Closed
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
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
"use client";

import { useRef, useMemo, useEffect, useState } from "react";
import React, { useRef, useEffect, useMemo, useState } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from "three";
import { FrameData } from "@/types/FrameData";
import { currentOtherVehicle } from "@/config/otherVehicleConfig";
import URDFLoader from "urdf-loader";
import { getInterpolatedFrame } from "@/utils/getInterpolatedFrame";

interface OtherVehicleProps {
id: string;
Expand All @@ -25,25 +26,22 @@ export default function OtherVehicle({ id, timeline, time }: OtherVehicleProps)

useEffect(() => {
const loader = new URDFLoader();

loader.load(
modelPath,
(robot) => {
robot.scale.set(scale[0], scale[1], scale[2]);
robot.rotation.set(rotation[0], rotation[1], rotation[2]);
robot.position.set(offset[0], offset[1], offset[2]);

robot.traverse((child) => {
if (child instanceof THREE.Mesh && child.material instanceof THREE.MeshStandardMaterial) {
if (
child instanceof THREE.Mesh &&
child.material instanceof THREE.MeshStandardMaterial
) {
child.material = child.material.clone();
child.material.color.set(bodyColor);
}
});

if (vehicleGroup.current) {
vehicleGroup.current.add(robot);
}

vehicleGroup.current.add(robot);
setIsLoaded(true);
},
undefined,
Expand All @@ -55,13 +53,10 @@ export default function OtherVehicle({ id, timeline, time }: OtherVehicleProps)

useFrame(() => {
if (!ref.current || timeline.length === 0) return;

const frame = timeline.find((f) => f.time >= time) ?? timeline.at(-1);
const frame = getInterpolatedFrame(timeline, time);
if (!frame) return;

targetPosition.set(frame.x, 0, frame.y);
ref.current.position.lerp(targetPosition, 0.2);

targetQuaternion.setFromEuler(new THREE.Euler(0, -frame.yaw, 0));
ref.current.quaternion.slerp(targetQuaternion, 0.2);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
"use client";

import { useRef, useMemo, useEffect, useState } from "react";
import React, { useRef, useMemo, useEffect, useState } from "react";
import { useFrame } from "@react-three/fiber";
import { Mesh, Object3D, MeshStandardMaterial } from "three";
import {
Mesh,
Object3D,
MeshStandardMaterial,
Vector3,
Quaternion,
Euler,
} from "three";
import { useGLTF } from "@react-three/drei";
import { FrameData } from "@/types/FrameData";
import { currentPedestrian } from "@/config/pedestrianConfig";
import { getInterpolatedFrame } from "@/utils/getInterpolatedFrame";

interface PedestrianProps {
id: string;
Expand All @@ -15,12 +23,15 @@ interface PedestrianProps {

export default function Pedestrian({ id, timeline, time }: PedestrianProps) {
const [mounted, setMounted] = useState(false);

const ref = useRef<Mesh>(null);

const { modelPath, scale, rotation, offset, bodyColor } = currentPedestrian;
const { scene } = useGLTF(modelPath);
const clonedScene = useMemo(() => scene.clone(true), [scene]);

const targetPosition = useMemo(() => new Vector3(), []);
const targetQuaternion = useMemo(() => new Quaternion(), []);

useEffect(() => {
setMounted(true);
}, []);
Expand All @@ -39,17 +50,14 @@ export default function Pedestrian({ id, timeline, time }: PedestrianProps) {

useFrame(() => {
if (!ref.current || timeline.length === 0) return;

const frame = timeline.find((f) => f.time >= time) ?? timeline.at(-1);
const frame = getInterpolatedFrame(timeline, time);
if (!frame) return;

ref.current.position.set(frame.x, 0, frame.y);
ref.current.rotation.y = -frame.yaw;
targetPosition.set(frame.x, 0, frame.y);
ref.current.position.lerp(targetPosition, 0.2);
targetQuaternion.setFromEuler(new Euler(0, -frame.yaw, 0));
ref.current.quaternion.slerp(targetQuaternion, 0.2);
});

const hasSpawned = timeline.length > 0 && timeline[0].time <= time;
if (!mounted || !hasSpawned) return null;

return (
<primitive
ref={ref as React.RefObject<Object3D>}
Expand All @@ -59,4 +67,4 @@ export default function Pedestrian({ id, timeline, time }: PedestrianProps) {
position={offset}
/>
);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
"use client";

import { useRef, useMemo, useEffect, useState } from "react";
import React, { useRef, useMemo, useEffect, useState } from "react";
import { useFrame } from "@react-three/fiber";
import { Mesh, Object3D, MeshStandardMaterial } from "three";
import {
Mesh,
Object3D,
MeshStandardMaterial,
Vector3,
Quaternion,
Euler,
} from "three";
import { useGLTF } from "@react-three/drei";
import { FrameData } from "@/types/FrameData";
import { currentTrafficCone } from "@/config/trafficConeConfig";
import { getInterpolatedFrame } from "@/utils/getInterpolatedFrame";

interface TrafficConeProps {
id: string;
Expand All @@ -15,12 +23,14 @@ interface TrafficConeProps {

export default function TrafficCone({ id, timeline, time }: TrafficConeProps) {
const [mounted, setMounted] = useState(false);

const ref = useRef<Mesh>(null);
const { modelPath, scale, rotation, offset, bodyColor } = currentTrafficCone;
const { scene } = useGLTF(modelPath);
const clonedScene = useMemo(() => scene.clone(true), [scene]);

const targetPosition = useMemo(() => new Vector3(), []);
const targetQuaternion = useMemo(() => new Quaternion(), []);

useEffect(() => {
setMounted(true);
}, []);
Expand All @@ -38,16 +48,15 @@ export default function TrafficCone({ id, timeline, time }: TrafficConeProps) {
}, [clonedScene, bodyColor]);

useFrame(() => {
const frame = timeline.find((f) => f.time >= time);
if (frame && ref.current) {
ref.current.position.set(frame.x, frame.z, frame.y);
ref.current.rotation.y = -frame.yaw;
}
if (!ref.current || timeline.length === 0) return;
const frame = getInterpolatedFrame(timeline, time);
if (!frame) return;
targetPosition.set(frame.x, frame.z, frame.y);
ref.current.position.lerp(targetPosition, 0.2);
targetQuaternion.setFromEuler(new Euler(0, -frame.yaw, 0));
ref.current.quaternion.slerp(targetQuaternion, 0.2);
});

const hasSpawned = timeline.length > 0 && timeline[0].time <= time;
if (!mounted || !hasSpawned) return null;

return (
<primitive
ref={ref as React.RefObject<Object3D>}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,40 @@
"use client";

import { useRef, useMemo, useEffect, useState } from "react";
import React, { useRef, useMemo, useEffect, useState } from "react";
import { useFrame } from "@react-three/fiber";
import { Mesh, Object3D, MeshStandardMaterial } from "three";
import {
Mesh,
Object3D,
MeshStandardMaterial,
Vector3,
Quaternion,
Euler,
} from "three";
import { useGLTF } from "@react-three/drei";
import { FrameData } from "@/types/FrameData";
import { currentTrafficLight } from "@/config/trafficLightConfig";
import { getInterpolatedFrame } from "@/utils/getInterpolatedFrame";

interface TrafficLightProps {
id: string;
timeline: FrameData[];
time: number;
}

export default function TrafficLight({ id, timeline, time }: TrafficLightProps) {
export default function TrafficLight({
id,
timeline,
time,
}: TrafficLightProps) {
const [mounted, setMounted] = useState(false);

const ref = useRef<Mesh>(null);
const { modelPath, scale, rotation, offset, bodyColor } = currentTrafficLight;
const { scene } = useGLTF(modelPath);
const clonedScene = useMemo(() => scene.clone(true), [scene]);

const targetPosition = useMemo(() => new Vector3(), []);
const targetQuaternion = useMemo(() => new Quaternion(), []);

useEffect(() => {
setMounted(true);
}, []);
Expand All @@ -38,16 +52,15 @@ export default function TrafficLight({ id, timeline, time }: TrafficLightProps)
}, [clonedScene, bodyColor]);

useFrame(() => {
const frame = timeline.find((f) => f.time >= time);
if (frame && ref.current) {
ref.current.position.set(frame.x, frame.z, frame.y);
ref.current.rotation.y = -frame.yaw;
}
if (!ref.current || timeline.length === 0) return;
const frame = getInterpolatedFrame(timeline, time);
if (!frame) return;
targetPosition.set(frame.x, frame.z, frame.y);
ref.current.position.lerp(targetPosition, 0.2);
targetQuaternion.setFromEuler(new Euler(0, -frame.yaw, 0));
ref.current.quaternion.slerp(targetQuaternion, 0.2);
});

const hasSpawned = timeline.length > 0 && timeline[0].time <= time;
if (!mounted || !hasSpawned) return null;

return (
<primitive
ref={ref as React.RefObject<Object3D>}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { currentVehicle } from "@/config/vehicleConfig";
import { FrameData } from "@/types/FrameData";
import { OrbitControls } from "@react-three/drei";
import URDFLoader from "urdf-loader";
import { getInterpolatedFrame } from "@/utils/getInterpolatedFrame";

interface VehicleProps {
timeline: FrameData[];
Expand All @@ -15,7 +16,7 @@ interface VehicleProps {
export default function Vehicle({ timeline, time }: VehicleProps) {
const ref = useRef<THREE.Group>(null);
const vehicleGroup = useRef<THREE.Group>(new THREE.Group());
const mode = useCameraController(ref, timeline, time);
const mode = useCameraController(ref);

const targetPosition = useMemo(() => new THREE.Vector3(), []);
const targetQuaternion = useMemo(() => new THREE.Quaternion(), []);
Expand Down Expand Up @@ -55,14 +56,11 @@ export default function Vehicle({ timeline, time }: VehicleProps) {

useFrame(() => {
if (!ref.current || timeline.length === 0) return;

const frame = timeline.find((f) => f.time >= time) ?? timeline.at(-1);
if (!frame) return;

targetPosition.set(frame.x, 0, frame.y);
const interp = getInterpolatedFrame(timeline, time);
if (!interp) return;
targetPosition.set(interp.x, 0, interp.y);
ref.current.position.lerp(targetPosition, 0.2);

targetQuaternion.setFromEuler(new THREE.Euler(0, -frame.yaw, 0));
targetQuaternion.setFromEuler(new THREE.Euler(0, -interp.yaw, 0));
ref.current.quaternion.slerp(targetQuaternion, 0.2);
});

Expand All @@ -74,4 +72,4 @@ export default function Vehicle({ timeline, time }: VehicleProps) {
{mode === "free" && <OrbitControls />}
</>
);
}
}
Loading
Loading