xxxxxxxxxx
176
let video;
let faceMesh;
let faces = [];
let triangles;
let uvCoords;
let img;
let tex;
let flameEmitter;
function preload() {
faceMesh = ml5.faceMesh({ maxFaces: 1, flipped: false });
img = loadImage("Zombie_Dan_mesh_map.png");
}
function makeSemiTransparent(img) {
img.loadPixels();
for (let i = 0; i < img.pixels.length; i += 4) {
img.pixels[i + 3] = 128;
}
img.updatePixels();
}
function mousePressed() {
console.log(faces);
}
function gotFaces(results) {
faces = results;
}
function setup() {
createCanvas(640, 480, WEBGL);
video = createCapture(VIDEO, { flipped: false });
video.size(640, 480);
video.hide();
makeSemiTransparent(img);
tex = createImage(640, 480);
flameEmitter = new Emitter();
triangles = faceMesh.getTriangles();
uvCoords = faceMesh.getUVCoords();
faceMesh.detectStart(video, gotFaces);
}
function drawTriangle(tri, points) {
for (let index of tri) {
let p = points[index];
let uv = uvCoords[index];
vertex(p.x, p.y, -p.z, uv[0], uv[1]);
}
}
let midUpperLip = 13;
let midLowerLip = 14;
let mouthLeft = 78;
let mouthRight = 308;
let midNose = 19;
let midLeftNose = 241;
let midRightNose = 461;
function p2v(p) {
return createVector(p.x, p.y, p.z);
}
function pointDist(p1, p2) {
return dist(p1.x, p1.y, p1.z, p2.x, p2.y, p2.z);
}
function drawFire(face) {
let points = face.keypoints;
let mulP = points[midUpperLip];
let mllP = points[midLowerLip];
let vertD = pointDist(mulP, mllP);
let molP = points[mouthLeft];
let morP = points[mouthRight];
let horizD = pointDist(molP, morP);
let midP = p2v(mulP);
midP.add(p2v(mllP));
midP.mult(0.5);
let flameDir = p2v(points[midLeftNose]);
flameDir.add(p2v(points[midRightNose]));
flameDir.mult(-0.5);
flameDir.add(p2v(points[midNose]));
flameDir.normalize();
let flamePer = p2v(mulP);
flamePer.sub(p2v(mllP));
flamePer.normalize();
let flameCross = flameDir.cross(flamePer);
if (vertD / face.box.height < 0.03) {
flameEmitter.run(
midP,
[flameDir, flamePer, flameCross],
[vertD, horizD]);
return;
}
if (horizD / face.box.width < 0.3) {
for (let i = 0; i < 5; i++) {
flameEmitter.addParticle(new Water({
origin: midP,
orientation: [flameDir, flamePer, flameCross],
spreads: [vertD, horizD]}));
}
} else {
flameEmitter.addParticle(new Fire({
origin: midP,
orientation: [flameDir, flamePer, flameCross],
spreads: [vertD, horizD],
stroke: 8}));
flameEmitter.addParticle(new Fire({
velocitiesL: [1, 2],
lifespans: [5, 10],
streak: 0.1,
stroke: 4}));
}
flameEmitter.run(
midP,
[flameDir, flamePer, flameCross],
[vertD, horizD]);
//flameDir.mult(10);
//flamePer.mult(10);
//stroke(255, 255, 255);
//line(
// midP.x, midP.y, midP.z,
// midP.x + flameDir.x, midP.y + flameDir.y, midP.z + flameDir.z);
//line(
// midP.x, midP.y, midP.z,
// midP.x + flamePer.x, midP.y + flamePer.y, midP.z + flamePer.z);
}
function drawFace(face) {
texture(img);
textureMode(NORMAL);
noStroke();
beginShape(TRIANGLES);
points = face.keypoints;
for (let tri of triangles) {
drawTriangle(tri, points);
}
endShape();
clearDepth();
drawFire(face);
}
function drawVideo() {
translate(-width / 2, -height / 2);
background(0);
image(video, 0, 0);
}
function draw() {
drawVideo();
if (faces.length <= 0)
return;
clearDepth();
drawFace(faces[0]);
}