Skip to content

Commit

Permalink
Particles can interact (#27)
Browse files Browse the repository at this point in the history
* allow particles to interact with gravity

* revert setting changes
  • Loading branch information
yhattav authored Nov 27, 2024
1 parent b452085 commit 55c3609
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 40 deletions.
45 changes: 16 additions & 29 deletions src/components/GravitySimulator/GravitySimulator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,14 @@ import { Scenario } from "../../types/scenario";
import { SettingOutlined } from "@ant-design/icons";
import { SaveScenarioModal } from "../SaveScenarioModal/SaveScenarioModal";
import { createShareableLink } from "../../utils/compression";
import { Particle, ParticleMechanics, TrailPoint } from "../../types/particle";

interface ParticleMechanics {
position: Point2D;
velocity: Point2D;
force: Force;
mass: number;
elasticity: number;
}

interface Particle extends ParticleMechanics {
id: string;
color: string;
size: number;
showVectors: boolean;
trails: TrailPoint[];
}

interface TrailPoint extends Point2D {
timestamp: number;
}
const generatePastelColor = () => {
const r = Math.floor(Math.random() * 75 + 180);
const g = Math.floor(Math.random() * 75 + 180);
const b = Math.floor(Math.random() * 75 + 180);
return `rgb(${r}, ${g}, ${b})`;
};

interface GravitySimulatorProps {
gravityRef: React.RefObject<HTMLDivElement>;
Expand All @@ -63,13 +51,6 @@ interface SimulationScenario {
particles: Array<Omit<Particle, "trails" | "force">>;
}

const generatePastelColor = () => {
const r = Math.floor(Math.random() * 75 + 180);
const g = Math.floor(Math.random() * 75 + 180);
const b = Math.floor(Math.random() * 75 + 180);
return `rgb(${r}, ${g}, ${b})`;
};

export const GravitySimulator: React.FC<GravitySimulatorProps> = ({
gravityRef,
pointerPos,
Expand Down Expand Up @@ -157,14 +138,20 @@ export const GravitySimulator: React.FC<GravitySimulatorProps> = ({

const updateParticleMechanics = useCallback(
(
particle: ParticleMechanics & { trails: TrailPoint[] }
particle: ParticleMechanics & { trails: TrailPoint[] },
allParticles: Array<ParticleMechanics & { trails: TrailPoint[] }> = []
): ParticleMechanics => {
// Filter out the current particle from gravity calculations
const otherParticles = allParticles.filter((p) => p !== particle);

const calculatedForce = calculateTotalForce(
particle.position,
throttledPointerPos,
gravityPoints,
offset,
physicsConfig.POINTER_MASS
physicsConfig.POINTER_MASS,
otherParticles,
physicsConfig.PARTICLES_EXERT_GRAVITY
);

const force = {
Expand Down Expand Up @@ -232,7 +219,7 @@ export const GravitySimulator: React.FC<GravitySimulatorProps> = ({

setParticles((currentParticles) =>
currentParticles.map((particle) => {
const mechanics = updateParticleMechanics(particle);
const mechanics = updateParticleMechanics(particle, currentParticles);
return { ...particle, ...mechanics };
})
);
Expand Down
6 changes: 1 addition & 5 deletions src/components/ParticleRenderer/ParticleRenderer.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import React, { useState } from "react";
import { motion } from "framer-motion";
import { drawArrow } from "../../utils/physics/vectorUtils";
import { Point2D, Force } from "../../types/physics";

interface TrailPoint extends Point2D {
timestamp: number;
}
import { TrailPoint } from "../../types/particle";

interface ParticleRenderParams {
position: Point2D;
Expand Down
5 changes: 5 additions & 0 deletions src/constants/physics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const PHYSICS_CONFIG = {
CONSTANT_FORCE_X: 0,
CONSTANT_FORCE_Y: 0,
SOLID_BOUNDARIES: true,
PARTICLES_EXERT_GRAVITY: false,
} as const;

export const SETTINGS_METADATA: Record<
Expand Down Expand Up @@ -93,6 +94,10 @@ export const SETTINGS_METADATA: Record<
type: "boolean",
isDev: false,
},
PARTICLES_EXERT_GRAVITY: {
type: "boolean",
isDev: false,
},
} as const;

export const PARTICLE_MODES = {
Expand Down
21 changes: 21 additions & 0 deletions src/types/particle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Point2D, Force } from "../utils/types/physics";

export interface ParticleMechanics {
position: Point2D;
velocity: Point2D;
force: Force;
mass: number;
elasticity: number;
}

export interface TrailPoint extends Point2D {
timestamp: number;
}

export interface Particle extends ParticleMechanics {
id: string;
color: string;
size: number;
showVectors: boolean;
trails: TrailPoint[];
}
32 changes: 26 additions & 6 deletions src/utils/physics/physicsUtils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Point2D, Force, GravityPoint } from "../types/physics";
import { ParticleMechanics } from "../../types/particle";

// Basic physics calculations
export const calculateDistance = (p1: Point2D, p2: Point2D): number => {
Expand Down Expand Up @@ -51,6 +52,7 @@ export const calculateGravitationalForce = (
minDistance = 30,
maxForce = 2
): Force => {
console.log(x1, y1, x2, y2, mass);
if (!isFinite(x1) || !isFinite(y1) || !isFinite(x2) || !isFinite(y2)) {
return { fx: 0, fy: 0 };
} // TODO: see if we can check the isFinite on x1+y1+x2+y2, is it faster?
Expand Down Expand Up @@ -84,19 +86,21 @@ export const calculateGravitationalForce = (
};

export const calculateTotalForce = (
cursorPos: Point2D,
selfPosition: Point2D,
pointerPos: Point2D,
gravityPoints: GravityPoint[],
offset: Point2D,
pointerMass = 50000
pointerMass = 50000,
particles: Array<ParticleMechanics> = [],
particlesExertGravity = false
): Force => {
let totalFx = 0;
let totalFy = 0;

// Add pointer gravitational pull
const pointerForce = calculateGravitationalForce(
cursorPos.x,
cursorPos.y,
selfPosition.x,
selfPosition.y,
pointerPos.x,
pointerPos.y,
pointerMass
Expand All @@ -107,8 +111,8 @@ export const calculateTotalForce = (
// Add gravity points force
gravityPoints.forEach((point) => {
const force = calculateGravitationalForce(
cursorPos.x,
cursorPos.y,
selfPosition.x,
selfPosition.y,
point.x + offset.x,
point.y + offset.y,
point.mass
Expand All @@ -117,6 +121,22 @@ export const calculateTotalForce = (
totalFy += force.fy;
});

// Add particle gravity if enabled
if (particlesExertGravity) {
particles.forEach((particle) => {
const force = calculateGravitationalForce(
selfPosition.x,
selfPosition.y,
particle.position.x,
particle.position.y,
particle.mass
);
console.log(force);
totalFx += force.fx;
totalFy += force.fy;
});
}

return { fx: totalFx, fy: totalFy };
};

Expand Down

0 comments on commit 55c3609

Please sign in to comment.