Public
Edited
Jun 10, 2023
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
walker = {
let walker = new BMWalker(0); // BMW_TYPE_HUMAN = 0
return walker;
}
Insert cell
Insert cell
walker.setSpeed(walkerSpeed) // updates the walking speed
Insert cell
walker.setTranslationParam(false) // true means they are moving Human and chickens only
Insert cell
{
walker.setCameraParam(azimuth, spin ? 1 : 0, elevation, roll);
return 'updating cam when sliders change' // could return something better that could be used to position head.
}
Insert cell
paramBounds = {
let tmpWalker = new BMWalker();
return {
bodyStructure: [tmpWalker.minBodyStructure, tmpWalker.maxBodyStructure],
weight: [tmpWalker.minWeight, tmpWalker.maxWeight],
nervousness: [tmpWalker.minNervousness, tmpWalker.maxNervousness],
happiness: [tmpWalker.minHappiness, tmpWalker.maxHappiness]
};
}
Insert cell
Insert cell
{
walker.setWalkerParam(
walkerBodyStructure,
walkerWeight,
walkerNervousness,
walkerHappiness
);
return {bodyStructure:walkerBodyStructure,
weight:walkerWeight,
nervousness:walkerNervousness,
happiness:walkerHappiness
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
base_head_infomation = ({
nose: {x:-14, y:-178, z:0, jc:"#ff0000" },
right_eye: {x:-23, y:-193, z:-6, jc:"#aa00ff" },
right_ear: {x:-38, y:-185, z:-6, jc:"#ff00aa" },
left_eye: {x: -2, y:-193, z:-9, jc:"#ff00ff" },
left_ear: {x: 12, y:-185, z:-9, jc:"#990066" }
})
Insert cell
8-14
Insert cell
-33-14
Insert cell
scaledHead = {
const SCALE_FACTOR = (walkerHeight / 512)
const rotated_head_information = {}

// calculate the scaling factor for each point
for (let key in base_head_infomation) {
if (key === 'nose') {
rotated_head_information[key] = base_head_infomation[key]
} else {
// Calculate the delta x, y, and z values for the current key
const deltaX = (base_head_infomation[key].x - base_head_infomation['nose'].x) * Math.cos(azimuth+Math.PI) - base_head_infomation[key].z * Math.sin(azimuth+Math.PI)
const deltaY = (base_head_infomation[key].y - base_head_infomation['nose'].y)
const deltaZ = (base_head_infomation[key].z - base_head_infomation['nose'].z)

rotated_head_information[key] = {
x: base_head_infomation['nose'].x + (deltaX * SCALE_FACTOR),
y: base_head_infomation['nose'].y + (deltaY * SCALE_FACTOR),
z: base_head_infomation['nose'].z + (deltaZ * SCALE_FACTOR),
jc: base_head_infomation[key].jc
};
}
}
return rotated_head_information
}
Insert cell
function te_pose(bmw) {
// change the neck length
let v1 = (_.find(bmw, { desc: 'Head'}))
let v2 = (_.find(bmw, { desc: 'Clavicles'}))
let v = parametricPointVector(v1, v2, 0.544)
Object.assign(v1, {...v})
// ------------------------------------------------------------------------------------------
let bones = draw_order.map( (joint) => {
const joint0 = bmw.find((item) => item.desc === equilivants[joint[0]] )
const joint1 = bmw.find((item) => item.desc === equilivants[joint[1]])
const boneColour = joint[2]
return {x0:joint0.x, y0:joint0.y, z0:joint0.z, desc0:joint0.desc, // xyz joint 0
x1:joint1.x, y1:joint1.y, z1:joint1.z, desc1:joint1.desc, // xyz joint 1
bone_colour: boneColour , type: 'bone'}
})

// add joints to them_bones
let joints = _.uniq(_.flattenDeep(draw_order))
.filter((el) => !el.startsWith('#'))
.map(joint_name => {
let joint = _.find(bmw, {desc:equilivants[joint_name]})
return {x0:joint.x, y0:joint.y, z0:joint.z,
jointColour:jointColour[_.findKey(equilivants, (value) => value === joint.desc)],
type:'joint',
desc:joint.desc }
})
//===========================================================================
// Add head elements

// this could be refactored to use a updateBones() and updateJoints() functions

// all head features have desc0 and desc1 == to 'Head', The code below changes them to a new descriptions based on head part.
let whereB = _.findIndex(bones, obj => obj.desc0 === obj.desc1);

let off_x = (bones[whereB].x0 - scaledHead.nose.x) // work out nose, eyes and ears offset.
let off_y = (bones[whereB].y0 - scaledHead.nose.y) // bmwalker x,y - pose default x,y

bones[whereB].x0 = scaledHead.nose.x + off_x
bones[whereB].y0 = scaledHead.nose.y + off_y
bones[whereB].z0 += scaledHead.nose.z
bones[whereB].jc0 = scaledHead.nose.jc
bones[whereB].desc0 = "nose"
bones[whereB].x1 = scaledHead.right_eye.x + off_x
bones[whereB].y1 = scaledHead.right_eye.y + off_y
bones[whereB].z1 = scaledHead.right_eye.z
bones[whereB].jc1 = scaledHead.right_eye.jc
bones[whereB].desc1 = "right_eye"
bones[whereB].bone_colour = "#330099"

// nose
let whereJ = _.findIndex(joints, obj => obj.desc === 'Head')
joints[whereJ].jointColour = jointColour.nose
joints[whereJ].x0 = bones[whereB].x0
joints[whereJ].y0 = bones[whereB].y0
joints[whereJ].z0 += scaledHead.nose.z
joints[whereJ].desc = "nose"

// right eye
whereJ = _.findIndex(joints, obj => obj.desc === 'Head')
joints[whereJ].jointColour = jointColour.right_eye
joints[whereJ].x0 = bones[whereB].x1
joints[whereJ].y0 = bones[whereB].y1
joints[whereJ].z0 = scaledHead.right_eye.z
joints[whereJ].desc = "right_eye"

//--- Right Ear * dup name
whereB = _.findIndex(bones, obj => obj.desc0 === obj.desc1)
bones[whereB].x0 = scaledHead.right_eye.x + off_x
bones[whereB].y0 = scaledHead.right_eye.y + off_y
bones[whereB].z0 = scaledHead.right_eye.z
bones[whereB].jc0 = scaledHead.right_eye.jc
bones[whereB].desc0 = "right_eye"
bones[whereB].x1 = scaledHead.right_ear.x + off_x
bones[whereB].y1 = scaledHead.right_ear.y + off_y
bones[whereB].z1 = scaledHead.right_ear.z
bones[whereB].jc1 = scaledHead.right_ear.jc
bones[whereB].desc1 = "right_ear"
bones[whereB].bone_colour = "#660099"

// right ear
whereJ = _.findIndex(joints, obj => obj.desc === 'Head')
joints[whereJ].jointColour = jointColour.right_ear
joints[whereJ].x0 = bones[whereB].x1
joints[whereJ].y0 = bones[whereB].y1
joints[whereJ].z0 = bones[whereB].z1
joints[whereJ].desc = "right_ear"

//--- Left Eyebrow
whereB = _.findIndex(bones, obj => obj.desc0 === obj.desc1)
bones[whereB].x0 = scaledHead.nose.x + off_x
bones[whereB].y0 = scaledHead.nose.y + off_y
bones[whereB].z0 = scaledHead.nose.z
bones[whereB].jc0 = scaledHead.nose.jc
bones[whereB].desc0 = "nose"
bones[whereB].x1 = scaledHead.left_eye.x + off_x
bones[whereB].y1 = scaledHead.left_eye.y + off_y
bones[whereB].z1 = scaledHead.left_eye.z
bones[whereB].jc1 = scaledHead.left_eye.jc
bones[whereB].desc1 = "left_eye"
bones[whereB].bone_colour = "#990099"

// left eye
whereJ = _.findIndex(joints, obj => obj.desc === 'Head');
joints[whereJ].jointColour = jointColour.left_eye
joints[whereJ].x0 = bones[whereB].x1
joints[whereJ].y0 = bones[whereB].y1
joints[whereJ].z0 = bones[whereB].z1
joints[whereJ].desc = "left_eye"

//--- Left Ear * dup name
whereB = _.findIndex(bones, obj => obj.desc0 === obj.desc1);
bones[whereB].x0 = scaledHead.left_eye.x + off_x
bones[whereB].y0 = scaledHead.left_eye.y + off_y
bones[whereB].z0 = scaledHead.left_eye.z
bones[whereB].jc0 = scaledHead.left_eye.jc
bones[whereB].desc0 = "left_eye"
bones[whereB].x1 = scaledHead.left_ear.x + off_x
bones[whereB].y1 = scaledHead.left_ear.y + off_y
bones[whereB].z1 = scaledHead.left_ear.z
bones[whereB].jc1 = scaledHead.left_ear.jc
bones[whereB].desc1 = "left_ear"
bones[whereB].bone_colour = "#990066"

// left ear
whereJ = _.findIndex(joints, obj => obj.desc === 'Head');
joints[whereJ].jointColour = jointColour.left_ear
joints[whereJ].x0 = bones[whereB].x1
joints[whereJ].y0 = bones[whereB].y1
joints[whereJ].z0 = bones[whereB].z1
joints[whereJ].desc = "left_ear"

let them_bones = [...bones,...joints]

return _.orderBy(them_bones, [ (obj) => _.min([obj.z0, obj.z1 !== undefined ? obj.z1 : obj.z0])]); // sort the bones by depth
}
Insert cell
function parametricPointVector(v1, v2, percentage) { // if percent = 0.5 the Vector returned is at 50% of the line length
const x = (1 - percentage) * v1.x + percentage * v2.x;
const y = (1 - percentage) * v1.y + percentage * v2.y;
const z = (1 - percentage) * v1.z + percentage * v2.z;

return {x: x, y: y, z: z};
}
Insert cell
// calculate distance between the two points and work out the lines angle as they share maths
// used in the p5 draw.
distance = (bx0,by0,bx1,by1) => {
let dx = bx1 - bx0
let dy = by1 - by0
let angle = Math.atan2(dy, dx)
return {dist:Math.sqrt(dx*dx + dy*dy),angle:angle}
}
Insert cell
Insert cell
BW_to_OP_index = [0, 1, 5, 6, 7, 2, 3, 4, 12, 13, 14, 9, 10, 11, 0, 0, 0, 0] // no belly point - could be wrong -- used to find colour
Insert cell
Insert cell
Insert cell
Insert cell
BoneColours =
connect_color.map((colorArray,i) => {
return {colour: d3.rgb(colorArray[0], colorArray[1], colorArray[2]).formatHex(),i:i}
})
Insert cell
Insert cell
Insert cell
default_keypoints = [[241,77],[241,120],[191,118],[177,183],[163,252],[298,118],[317,182],[332,245],[225,241],[213,359],[215,454],[270,240],[282,360],[286,456],[232,59],[253,60],[225,70],[260,72]]
Insert cell
Insert cell
mutable saveFile = 0;
Insert cell
Insert cell
frameGap = walker.getPeriod()/numberOfFrames
Insert cell
Insert cell
sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)) // adds a delay so we don't flood the browsers save functions
Insert cell
Insert cell
Insert cell
Insert cell
BMWalker = fetch("https://tetunori.github.io/BMWalker.js/dist/v0.6.1/bmwalker.js")
.then((r) => r.text())
.then((src) => new Function(` let abs = Math.abs;
${src};
return BMWalker`)())
Insert cell
import {p5 as p5js} from "@hellonearthis/p5_s2" // temp as there where issues with unpkg and this version of p5 is newer
// import {p5 as p5js} from "@tmcw/p5";
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more