fix(game): implemented the InstancedMesh principle on the particle system for drifting

instancedMeshParticles
Alex 2024-01-25 11:02:20 +01:00
parent b1b93043f8
commit 2d9230b8ea
6 changed files with 71 additions and 98 deletions

View File

@ -43,7 +43,7 @@ function App() {
<KeyboardControls map={map}> <KeyboardControls map={map}>
<Experience /> <Experience />
</KeyboardControls> </KeyboardControls>
{/* <Stats /> */} <Stats />
</Physics> </Physics>
</Suspense> </Suspense>
</Canvas> </Canvas>

View File

@ -10,16 +10,16 @@ export const DriftParticlesLeft = ({turboColor,scale, ...props}) => {
return ( return (
<group {...props}> <group {...props}>
<Particles1 turboColor={turboColor} scale={scale} /> <Particles1 turboColor={turboColor} scale={scale} />
{/* <Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} /> <Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} /> <Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} /> <Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} /> <Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} /> <Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} /> <Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} /> <Particles1 turboColor={turboColor} scale={scale} /> */}
<Particles1 turboColor={turboColor} scale={scale} />
<Particles3 turboColor={turboColor} scale={scale} /> {/* <Particles3 turboColor={turboColor} scale={scale} /> */}
</group> </group>
) )

View File

@ -9,18 +9,7 @@ export const DriftParticlesRight = ({turboColor,scale, ...props}) => {
return ( return (
<group {...props}> <group {...props}>
<Particles2 turboColor={turboColor} scale={scale} /> <Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles4 turboColor={turboColor} scale={scale} />
</group> </group>
) )

View File

@ -1,55 +1,47 @@
import { useRef } from "react"; import { useRef, useMemo } from "react";
import { useFrame } from "@react-three/fiber"; import { useFrame } from "@react-three/fiber";
import * as THREE from 'three'; import * as THREE from 'three';
export const Particles1 = ({ turboColor, scale, ...props }) => { export const Particles1 = ({ turboColor, scale, numParticles = 50, ...props }) => {
const ref = useRef(); const instancedMeshRef = useRef();
const velocity = useRef({ const particlesData = useMemo(() => {
x: -Math.random() * 0.05, return new Array(numParticles).fill().map(() => ({
y: Math.random() * 0.05, position: new THREE.Vector3(-0.6, 0.05, 0.5),
z: Math.random() * 0.02, velocity: new THREE.Vector3(-Math.random() * 0.05, Math.random() * 0.05, Math.random() * 0.02),
}); gravity: -0.003
const gravity = -0.003; }));
}, [numParticles]);
useFrame((state, delta) => { useFrame((state, delta) => {
let position = ref.current.position; const deltaScaled = delta * 144; // Scale for 144 FPS
let velocityVector = new THREE.Vector3(velocity.current.x, velocity.current.y, velocity.current.z); particlesData.forEach((particle, i) => {
particle.velocity.y += particle.gravity * deltaScaled;
// Adjust gravity and velocity based on delta
velocity.current.y += gravity * delta * 144; // Multiply by 144 to scale for 144 FPS particle.position.x += particle.velocity.x * deltaScaled;
particle.position.y += particle.velocity.y * deltaScaled;
// Scale velocity changes by delta particle.position.z += particle.velocity.z * deltaScaled;
position.x += velocity.current.x * delta * 144;
position.y += velocity.current.y * delta * 144; if (particle.position.y < 0.05) {
position.z += velocity.current.z * delta * 144; particle.position.set(-0.6, 0.05, 0.5);
particle.velocity.set(-Math.random() * 0.05, Math.random() * 0.05, Math.random() * 0.02);
if (!velocityVector.equals(new THREE.Vector3(0, 0, 0))) { }
const alignmentQuaternion = new THREE.Quaternion();
alignmentQuaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), velocityVector.normalize()); const matrix = new THREE.Matrix4();
ref.current.quaternion.slerp(alignmentQuaternion, 0.1); matrix.setPosition(particle.position);
} instancedMeshRef.current.setMatrixAt(i, matrix);
});
if (position.y < 0.05) {
position.set(-0.6, 0.05, 0.5); instancedMeshRef.current.instanceMatrix.needsUpdate = true;
velocity.current = {
x: -Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.02,
};
}
ref.current.position.set(position.x, position.y, position.z);
}); });
return ( return (
<mesh ref={ref} position={[-0.6, 0.05, 0.5]} scale={[scale, scale * 5, scale]}> <instancedMesh ref={instancedMeshRef} args={[null, null, numParticles]}>
<sphereGeometry args={[0.01, 16, 16]} /> <sphereGeometry args={[0.01, 16, 16]} />
<meshStandardMaterial <meshStandardMaterial
emissive={turboColor} emissive={turboColor}
toneMapped={false} toneMapped={false}
emissiveIntensity={5} emissiveIntensity={5}
/> />
</mesh> </instancedMesh>
); );
}; };

View File

@ -1,55 +1,47 @@
import { useRef } from "react"; import { useRef, useMemo } from "react";
import { useFrame } from "@react-three/fiber"; import { useFrame } from "@react-three/fiber";
import * as THREE from 'three'; import * as THREE from 'three';
export const Particles2 = ({ turboColor, scale, ...props }) => { export const Particles2 = ({ turboColor, scale, numParticles = 50, ...props }) => {
const ref = useRef(); const instancedMeshRef = useRef();
const velocity = useRef({ const particlesData = useMemo(() => {
x: Math.random() * 0.05, return new Array(numParticles).fill().map(() => ({
y: Math.random() * 0.05, position: new THREE.Vector3(0.6, 0.05, 0.5),
z: Math.random() * 0.02, velocity: new THREE.Vector3(Math.random() * 0.05, Math.random() * 0.05, Math.random() * 0.02),
}); gravity: -0.003
const gravity = -0.003; }));
}, [numParticles]);
useFrame((state, delta) => { useFrame((state, delta) => {
let position = ref.current.position; const deltaScaled = delta * 144; // Scale for 144 FPS
let velocityVector = new THREE.Vector3(velocity.current.x, velocity.current.y, velocity.current.z); particlesData.forEach((particle, i) => {
particle.velocity.y += particle.gravity * deltaScaled;
// Adjust gravity and velocity based on delta
velocity.current.y += gravity * delta * 144; // Multiply by 144 to scale for 144 FPS particle.position.x += particle.velocity.x * deltaScaled;
particle.position.y += particle.velocity.y * deltaScaled;
// Scale velocity changes by delta particle.position.z += particle.velocity.z * deltaScaled;
position.x += velocity.current.x * delta * 144;
position.y += velocity.current.y * delta * 144; if (particle.position.y < 0.05) {
position.z += velocity.current.z * delta * 144; particle.position.set(0.6, 0.05, 0.5);
particle.velocity.set(Math.random() * 0.05, Math.random() * 0.05, Math.random() * 0.02);
if (!velocityVector.equals(new THREE.Vector3(0, 0, 0))) { }
const alignmentQuaternion = new THREE.Quaternion();
alignmentQuaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), velocityVector.normalize()); const matrix = new THREE.Matrix4();
ref.current.quaternion.slerp(alignmentQuaternion, 0.1); matrix.setPosition(particle.position);
} instancedMeshRef.current.setMatrixAt(i, matrix);
});
if (position.y < 0.05) {
position.set(0.6, 0.05, 0.5); instancedMeshRef.current.instanceMatrix.needsUpdate = true;
velocity.current = {
x: Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.02,
};
}
ref.current.position.set(position.x, position.y, position.z);
}); });
return ( return (
<mesh ref={ref} position={[0.6, 0.05, 0.5]} scale={[scale, scale * 5, scale]}> <instancedMesh ref={instancedMeshRef} args={[null, null, numParticles]}>
<sphereGeometry args={[0.01, 16, 16]} /> <sphereGeometry args={[0.01, 16, 16]} />
<meshStandardMaterial <meshStandardMaterial
emissive={turboColor} emissive={turboColor}
toneMapped={false} toneMapped={false}
emissiveIntensity={5} emissiveIntensity={5}
/> />
</mesh> </instancedMesh>
); );
}; };

View File

@ -387,13 +387,13 @@ export const PlayerController = () => {
/> />
</mesh> </mesh>
<Cylinder {/* <Cylinder
args={[0.1, 0, 1, 128, 64, true]} args={[0.1, 0, 1, 128, 64, true]}
position={[-0.6, 0.05, 0.5]} position={[-0.6, 0.05, 0.5]}
rotation={[Math.PI / 3, 0 , 0]} rotation={[Math.PI / 3, 0 , 0]}
> >
<meshStandardMaterial side={THREE.DoubleSide} /> <meshStandardMaterial side={THREE.DoubleSide} />
</Cylinder> </Cylinder> */}
{/* <Flame/> */} {/* <Flame/> */}
<FlameParticles isBoosting={isBoosting} /> <FlameParticles isBoosting={isBoosting} />
<DriftParticlesLeft turboColor={turboColor} scale={scale} /> <DriftParticlesLeft turboColor={turboColor} scale={scale} />