Skip to content

Commit

Permalink
elliptic limbs #7
Browse files Browse the repository at this point in the history
  • Loading branch information
hnmr293 committed Mar 5, 2023
1 parent 995e26d commit 7cd352c
Showing 1 changed file with 56 additions and 28 deletions.
84 changes: 56 additions & 28 deletions js/posex.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const { THREE, TrackballControls, DragControls, MeshLine, MeshLineMaterial } = a

const JOINT_RADIUS = 4.0;
const LIMB_SIZE = 4.0;
const LIMB_N = 64;

const joint_names = [
'nose',
Expand Down Expand Up @@ -125,11 +126,10 @@ function create_body(unit, x0, y0, z0) {
}

for (let i = 0; i < limb_pairs.length; ++i) {
const [from_idx, to_idx] = limb_pairs[i];
const [r, g, b] = joint_colors[i];
const color = (r << 16) | (g << 8) | (b << 0);
const line = new MeshLine();
const mat = new MeshLineMaterial({ color: color });
const mat = new MeshLineMaterial({ color: color, opacity: 0.6, transparent: true });
limbs.push(new THREE.Mesh(line, mat));
}

Expand All @@ -147,11 +147,11 @@ function init_3d(ui) {
height = () => canvas.height,
unit = () => Math.min(width(), height()),
unit_max = () => Math.max(width(), height());

canvas.addEventListener('contextmenu', e => {
e.preventDefault();
}, false);

const scene = new THREE.Scene();
const default_bg = () => new THREE.Color(0x000000);
scene.background = default_bg();
Expand All @@ -161,7 +161,7 @@ function init_3d(ui) {

const renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: false,
antialias: true,
alpha: true,
preserveDrawingBuffer: true,
});
Expand Down Expand Up @@ -288,7 +288,7 @@ function init_3d(ui) {
e.object.dirty = true;
object_to_body.get(e.object).dirty = true;
});

dragger_body.addEventListener('dragstart', () => { controls.enabled = false; });
dragger_body.addEventListener('dragend', () => { controls.enabled = true; });
dragger_body.addEventListener('drag', e => {
Expand Down Expand Up @@ -390,7 +390,7 @@ function init_3d(ui) {
ui.fixed_roll.addEventListener('change', () => {
camera.fixed_roll = !!ui.fixed_roll.checked;
}, false);

let body_num = 1;
if (ui.add_body)
ui.add_body.addEventListener('click', () => {
Expand Down Expand Up @@ -479,10 +479,10 @@ function init_3d(ui) {
}
ui.bg.value = '';
}, false);

if (ui.reset_bg)
ui.reset_bg.addEventListener('click', () => set_bg(null), false);

function get_pose_dict(obj3d) {
return {
position: obj3d.position.toArray(),
Expand All @@ -508,10 +508,10 @@ function init_3d(ui) {
width: width(),
height: height(),
}

const camera_ = get_pose_dict(camera);
camera_.zoom = camera.zoom;

const joints = [];
for (let [name, body] of bodies) {
joints.push({
Expand All @@ -523,16 +523,45 @@ function init_3d(ui) {
z0: body.z0,
});
}

const image = await ui.getDataURL();

const data = { name, image, screen, camera: camera_, joints };
const result = await ui.save_pose_callback(data);
ui.notify(result.result, result.ok ? 'success' : 'error');
}, false);

const onAnimateEndOneshot = [];

// limb update
let elliptic_limbs = true;
const limb_vecs = Array.from(Array(LIMB_N)).map(x => new THREE.Vector3());
function elliptic_limb_width(p) {
// draw limb ellipse
// x^2 / a^2 + y^2 / b^2 = 1
// a := half of distance between two joints
// b := LIMB_SIZE / camera.zoom
// {a(2p-1)}^2 / a^2 + y^2 / b^2 = 1
// y^2 = b^2 { 1 - (2p-1)^2 }
const b = 2 * LIMB_SIZE / camera.zoom;
const pp = 2 * p - 1;
return b * Math.sqrt(1 - pp * pp);
}
function stick_limb_width(p) {
return 2 * LIMB_SIZE / camera.zoom;
}
function create_limb(mesh, from, to) {
const s0 = limb_vecs[0];
const s1 = limb_vecs[LIMB_N - 1];
from.getWorldPosition(s0);
to.getWorldPosition(s1);
const N = LIMB_N - 1;
for (let i = 1; i < limb_vecs.length - 1; ++i) {
limb_vecs[i].lerpVectors(s0, s1, i / N);
}
mesh.geometry.setPoints(limb_vecs, elliptic_limbs ? elliptic_limb_width : stick_limb_width);
}

let last_zoom = camera.zoom;
let running = true;
const animate = () => {
Expand All @@ -548,24 +577,23 @@ function init_3d(ui) {

for (let [name, body] of bodies) {
const { joints, limbs, group } = body;

// update joint size
for (let joint of joints) {
joint.scale.setScalar(1 / camera.zoom);
}

// show limbs
const zoom_changed = last_zoom !== camera.zoom;
if (body.dirty || zoom_changed) {
const v1 = new THREE.Vector3(), v2 = new THREE.Vector3();
for (let i = 0; i < limb_pairs.length; ++i) {
const [from_index, to_index] = limb_pairs[i];
const [from, to] = [joints[from_index], joints[to_index]];
if (from.dirty || to.dirty || zoom_changed) {
limbs[i].geometry.setPoints([from.getWorldPosition(v1), to.getWorldPosition(v2)], p => LIMB_SIZE / camera.zoom);
create_limb(limbs[i], from, to);
}
}

for (let i = 0; i < joints.length; ++i) {
joints[i].dirty = false;
}
Expand Down Expand Up @@ -609,7 +637,7 @@ function init_3d(ui) {
onAnimateEndOneshot.length = 0;
};

ui.loadPose = function(data) {
ui.loadPose = function (data) {
selected_body = null;
touched_body = null;
touchable_objects.length = 0;
Expand All @@ -623,14 +651,14 @@ function init_3d(ui) {
size_change(data.screen.width, data.screen.height);
if (width_input) width_input.value = data.screen.width;
if (height_input) height_input.value = data.screen.height;

// camera
set_pose_dict(camera, data.camera);
camera.zoom = data.camera.zoom;
camera.updateProjectionMatrix();

// bodies

// update `body_num`
const body_names = data.joints.map(x => {
const m = /^body_(\d+)$/.exec(x.name);
Expand All @@ -651,7 +679,7 @@ function init_3d(ui) {
}
};

ui.getDataURL = async function() {
ui.getDataURL = async function () {
const pr = new Promise(resolve => {
const current_bg = scene.background;
set_bg(null, true);
Expand All @@ -663,7 +691,7 @@ function init_3d(ui) {
return await pr;
};

ui.getBlob = async function() {
ui.getBlob = async function () {
const pr = new Promise(resolve => {
const current_bg = scene.background;
set_bg(null, true);
Expand All @@ -677,7 +705,7 @@ function init_3d(ui) {
return await pr;
};

ui.stop = function() {
ui.stop = function () {
running = false;
dragger_joint.deactivate();
dragger_joint.enabled = false;
Expand All @@ -686,7 +714,7 @@ function init_3d(ui) {
controls.enabled = false;
};

ui.play = function() {
ui.play = function () {
running = true;
dragger_joint.activate();
dragger_joint.enabled = true;
Expand All @@ -695,7 +723,7 @@ function init_3d(ui) {
controls.enabled = true;
controls.handleResize();
};

return animate;
}

Expand Down

0 comments on commit 7cd352c

Please sign in to comment.