xxxxxxxxxx
194
let video;
let poseNet;
let poses = [];
let circles = [];
let engine;
let world;
let skeletonBodies = []; // Array to store skeleton rigid bodies
let frameCounter = 0;
// Define connections between keypoints in a human body
const skeleton = [
["leftShoulder", "rightShoulder"],
["leftShoulder", "leftElbow"],
["rightShoulder", "rightElbow"],
["leftElbow", "leftWrist"],
["rightElbow", "rightWrist"],
["leftShoulder", "leftHip"],
["rightShoulder", "rightHip"],
["leftHip", "rightHip"],
["leftHip", "leftKnee"],
["rightHip", "rightKnee"],
["leftKnee", "leftAnkle"],
["rightKnee", "rightAnkle"],
];
function setup() {
createCanvas(640, 480);
video = createCapture(VIDEO);
video.hide();
poseNet = ml5.poseNet(video, modelReady);
poseNet.on("pose", gotPoses);
// Initialize Matter.js engine
engine = Matter.Engine.create();
world = engine.world;
world.gravity.y = 1; // Gravity acting in the downward direction. Adjust the value to make it stronger or weaker.
}
function modelReady() {
console.log("PoseNet model loaded!");
}
function gotPoses(results) {
poses = results;
// Update or recreate skeleton bodies based on new poses
updateSkeletonBodies();
}
function draw() {
image(video, 0, 0, width, height);
// Add a new circle every 120 frames
// Update Matter.js engine
Matter.Engine.update(engine);
// draw circles
for (let circle of circles) {
fill(255, 0, 0); // Set fill color for circles
noStroke(); // No border
ellipse(circle.position.x, circle.position.y, 20, 20); // Adjust size if necessary
}
// Update or recreate skeleton bodies based on new poses
//updateSkeletonBodies();
//drawSkeleton();
// Check for collision with pose keypoints
for (let pose of poses) {
for (let keypoint of pose.pose.keypoints) {
for (let circle of circles) {
let d = dist(
keypoint.position.x,
keypoint.position.y,
circle.position.x,
circle.position.y
);
if (d < 10) {
// Collision detected!
// Apply an impulse away from the pose
let dx = circle.position.x - keypoint.position.x;
let dy = circle.position.y - keypoint.position.y;
let mag = sqrt(dx * dx + dy * dy);
let bounceFactor = 0.02; // Adjust this value for desired bounce strength
Matter.Body.applyForce(circle, circle.position, {
x: (bounceFactor * dx) / mag,
y: (bounceFactor * dy) / mag,
});
}
}
}
}
}
function updateSkeletonBodies() {
// Remove existing skeleton bodies from the world to prevent them from stacking up
// This is a simple approach; a more sophisticated method would update existing bodies instead of recreating them
skeletonBodies.forEach((body) => {
Matter.World.remove(world, body);
});
skeletonBodies = []; // Clear the array for new bodies
poses.forEach((pose) => {
skeleton.forEach(([partA, partB]) => {
const keypointA = pose.pose.keypoints.find(
(point) => point.part === partA
);
const keypointB = pose.pose.keypoints.find(
(point) => point.part === partB
);
if (keypointA && keypointB) {
// Calculate midpoint, angle, and distance
const midpoint = calculateMidpoint(
keypointA.position,
keypointB.position
);
const angle = calculateAngle(keypointA.position, keypointB.position);
const distance = calculateDistance(
keypointA.position,
keypointB.position
);
// Create a rectangle body at the midpoint, with length equal to distance and a small height, rotated to the calculated angle
const rect = Matter.Bodies.rectangle(
midpoint.x,
midpoint.y,
distance,
10,
{
angle: angle,
isStatic: false, // Set to true if you don't want them to fall under gravity
}
);
Matter.World.add(world, rect);
skeletonBodies.push(rect); // Keep track of the body
}
});
});
}
// Utility functions
function calculateMidpoint(pointA, pointB) {
return {
x: (pointA.x + pointB.x) / 2,
y: (pointA.y + pointB.y) / 2,
};
}
function calculateAngle(pointA, pointB) {
return Math.atan2(pointB.y - pointA.y, pointB.x - pointA.x);
}
function calculateDistance(pointA, pointB) {
return Math.sqrt((pointA.x - pointB.x) ** 2 + (pointA.y - pointB.y) ** 2);
}
function drawSkeleton() {
for (let pose of poses) {
for (let [partA, partB] of skeleton) {
let keypointA = pose.pose.keypoints.find((point) => point.part === partA);
let keypointB = pose.pose.keypoints.find((point) => point.part === partB);
if (keypointA && keypointB) {
stroke(255, 0, 0);
line(
keypointA.position.x,
keypointA.position.y,
keypointB.position.x,
keypointB.position.y
);
}
}
}
}
// Add a new circle when mouse is clicked
function mousePressed() {
let newCircle = Matter.Bodies.circle(mouseX, mouseY, 10);
circles.push(newCircle);
Matter.World.add(world, newCircle);
}
function addFallingCircle() {
// Random X position above the canvas, Y position slightly above the top edge
let x = Math.random() * width;
let y = -10; // Start above the canvas to make it look like it's falling into view
let circle = Matter.Bodies.circle(x, y, 10); // Adjust size as needed
Matter.World.add(world, circle);
circles.push(circle); // Keep track of it if you need to reference or draw it later
}