Skip to content

Commit

Permalink
feat: Added double-pendulum example
Browse files Browse the repository at this point in the history
  • Loading branch information
bfanger committed Mar 9, 2022
1 parent 940ccf5 commit 461e21e
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 66 deletions.
31 changes: 0 additions & 31 deletions src/routes/ball.svelte

This file was deleted.

106 changes: 80 additions & 26 deletions src/routes/constraints/double-pendulum.svelte
Original file line number Diff line number Diff line change
@@ -1,47 +1,101 @@
<script lang="ts">
// https://www.kiwico.com/us/store/dp/glowing-pendulum-project-kit/2012
// Real wolrd Inspiration: https://www.kiwico.com/us/store/dp/glowing-pendulum-project-kit/2012
import * as CANNON from "cannon-es";
import * as PE from "$lib/index";
import Fab from "../../site/Fab.svelte";
import DebugCanvas from "../../site/ThreeRenderer.svelte";
import Debugger from "$lib/debugger";
import type { Scene } from "three";
import { onMount } from "svelte";
const linearDamping = 0.06;
let jointPosition = new CANNON.Vec3(1, -0.5, 0);
let penPosition = new CANNON.Vec3(1, -1.5, 0);
let trailsCanvas: HTMLCanvasElement;
let sticksCanvas: HTMLCanvasElement;
let onPostStep: () => void | undefined;
function scale(value: number) {
return value * 256 + 512;
}
onMount(() => {
const overlayCtx = sticksCanvas.getContext("2d");
const ctx = trailsCanvas.getContext("2d");
if (!ctx || !overlayCtx) {
throw new Error("No 2D context available");
}
let firstPosition = new CANNON.Vec3(1, 1, 0);
let secondPosition = new CANNON.Vec3(1, 2, 0);
let scene: Scene;
overlayCtx.lineCap = "round";
ctx.lineWidth = 16;
ctx.lineCap = "round";
const start = Date.now();
const previous = penPosition.clone();
onPostStep = () => {
if (!ctx) {
return;
}
// Pulsating eraser strength to prevent ghosting, but still getting long trails
const eraserStrength =
(Math.sin((Date.now() - start) / 10) + 1) / 15 + 0.05;
ctx.fillStyle = `rgba(255,255,255,${eraserStrength})`;
ctx.fillRect(0, 0, 1024, 1024);
ctx.beginPath();
ctx.moveTo(scale(previous.x), scale(previous.y));
const hue = (Date.now() - start) / 8;
ctx.strokeStyle = `hsl(${hue},100%,70%)`;
ctx.lineTo(scale(penPosition.x), scale(penPosition.y));
ctx.stroke();
previous.copy(penPosition);
overlayCtx.clearRect(0, 0, 1024, 1024);
overlayCtx.beginPath();
overlayCtx.lineWidth = 8;
overlayCtx.strokeStyle = "#ff9c26";
overlayCtx.moveTo(scale(0), scale(-0.5));
overlayCtx.lineTo(scale(jointPosition.x), scale(jointPosition.y));
overlayCtx.stroke();
overlayCtx.beginPath();
overlayCtx.lineWidth = 12;
overlayCtx.strokeStyle = "#ffc548";
overlayCtx.moveTo(scale(jointPosition.x), scale(jointPosition.y));
overlayCtx.lineTo(scale(penPosition.x), scale(penPosition.y));
overlayCtx.stroke();
};
});
</script>

<PE.World gravity={[0, -9.81, 0]}>
<PE.DistanceConstraint for={["anchor", "first", "second"]} distance={1} />
<PE.Body id="anchor" mass={0} position={[0, 1, 0]} />
<PE.Body
id="first"
mass={1}
linearDamping={0.08}
bind:position={firstPosition}
>
<canvas bind:this={trailsCanvas} width="1024" height="1024" />
<canvas bind:this={sticksCanvas} width="1024" height="1024" />
<PE.World gravity={[0, 9.81, 0]} on:postStep={onPostStep}>
<PE.DistanceConstraint for={["anchor", "joint", "pen"]} distance={1} />
<PE.Body id="anchor" mass={0} position={[0, -0.5, 0]} />
<PE.Body id="joint" mass={1} {linearDamping} bind:position={jointPosition}>
<PE.Sphere radius={0.2} />
</PE.Body>
<PE.Body
id="second"
mass={1}
linearDamping={0.08}
bind:position={secondPosition}
>
<PE.Body id="pen" mass={1} {linearDamping} bind:position={penPosition}>
<PE.Sphere radius={0.2} />
</PE.Body>
<Debugger {scene} />
<DebugCanvas bind:scene />
</PE.World>

<Fab
href="https://github.com/bfanger/svelte-cannon/blob/main/src/routes/debugger.svelte"
href="https://github.com/bfanger/svelte-cannon/blob/main/src/routes/constraints/double-pendulum.svelte"
/>
<svelte:head>
<title>Double pendulum - cannon-es DistanceContraint</title>
<title>Double pendulum - Simulated using cannon-es DistanceContraint</title>
<meta
name="description"
content="Double pendulum an example of the DistanceContraint, inspired by KiwiCo Glowing Pendulum"
/>
</svelte:head>

<style>
canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: contain;
}
</style>
22 changes: 14 additions & 8 deletions src/routes/index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@
</div>
</li>
<li>
<a href="spring">Spring</a>
<a href="constraints/bridge">Bridge</a>
<div class="description">Example of using the LockConstraint</div>
</li>
<li>
<a href="constraints/double-pendulum">Double pendulum</a>
<div class="description">
Box hanging on a spring
<a href="https://pmndrs.github.io/cannon-es/examples/spring">
original by cannon-es
</a>
Example of a chaotic rich dynamic behavior - Wikipedia
</div>
</li>
<li>
Expand All @@ -44,15 +45,20 @@
<a href="debugger">Debugger</a>
<div class="description">
Using the cannon-es-debugger, depends on additional packages:<br />
<a href="https://github.com/pmndrsnd /cannon-es-debugger">
<a href="https://github.com/pmndrs/cannon-es-debugger">
cannon-es-debugger
</a>
and <a href="https://threejs.org">threejs</a>
</div>
</li>
<li>
<a href="constraints/bridge">Bridge</a>
<div class="description">Example of using the LockConstraint</div>
<a href="spring">Spring</a>
<div class="description">
Box hanging on a spring
<a href="https://pmndrs.github.io/cannon-es/examples/spring">
original by cannon-es
</a>
</div>
</li>
</ul>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/routes/pill-eater.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,5 @@
/>
<svelte:head>
<title>Pill Eater</title>
<meta name="description" content="Small mini game, Go get the power pill" />
<meta name="description" content="Small mini game, Go get the power pill!" />
</svelte:head>

0 comments on commit 461e21e

Please sign in to comment.