xxxxxxxxxx
270
// params
const r1 = 20;
const r2 = 60;
const fw = 15;
const cw = 4;
const tvw = 350; // camera pov width
const tvh = tvw/16*9;
const aperture = 8;
const bottom_padding = 30;
const object_margin = 5;
let is_film_selected = false;
let is_cam_selected = false;
let is_obj1_selected = false;
let is_obj2_selected = false;
let film_pos = 10;
let cam_pos = 200;
let obj1_pos = 400;
let obj2_pos = 600;
let mouseX_prev = 0;
// points projected on the film(only y axis because x axis is film_pos+fw)
let a1 = 0;
let b1 = 0;
let a2 = 0;
let b2 = 0;
function setup() {
createCanvas(1000, 600);
}
function mousePressed() {
// record mouseX
mouseX_prev = mouseX;
// find the nearest thing
const dist_obj1 = abs(mouseX - obj1_pos);
const dist_obj2 = abs(mouseX - obj2_pos);
const dist_film = abs(mouseX - film_pos);
const dist_cam = abs(mouseX - cam_pos);
if (dist_obj1 < dist_obj2 && dist_obj1 < dist_film && dist_obj1 < dist_cam) {
is_obj1_selected = true;
} else if (
dist_obj2 < dist_obj1 &&
dist_obj2 < dist_film &&
dist_obj2 < dist_cam
) {
is_obj2_selected = true;
} else if (
dist_film < dist_obj1 &&
dist_film < dist_obj2 &&
dist_film < dist_cam
) {
is_film_selected = true;
} else if (
dist_cam < dist_obj1 &&
dist_cam < dist_obj2 &&
dist_cam < dist_film
) {
is_cam_selected = true;
}
}
function mouseReleased() {
is_film_selected = false;
is_cam_selected = false;
is_obj1_selected = false;
is_obj2_selected = false;
}
function mouseDragged() {
if (is_film_selected && film_pos+(mouseX-mouseX_prev)>object_margin) {
film_pos += (mouseX-mouseX_prev);
} else if (is_cam_selected && cam_pos+(mouseX-mouseX_prev)<obj1_pos-r1-cw/2-object_margin && cam_pos+(mouseX-mouseX_prev)>film_pos+fw+object_margin) {
cam_pos += (mouseX-mouseX_prev);
} else if (is_obj1_selected && obj1_pos+(mouseX-mouseX_prev)>r1+cam_pos+cw+object_margin) {
obj1_pos += (mouseX-mouseX_prev);
} else if (is_obj2_selected && obj2_pos+(mouseX-mouseX_prev)>r2+cam_pos+cw+object_margin) {
obj2_pos += (mouseX-mouseX_prev);
}
mouseX_prev = mouseX;
}
function draw() {
background(25);
noStroke();
fill(255);
// Horizontal line
stroke(255, 30);
line(0, (height - bottom_padding) / 2, width, (height - bottom_padding) / 2);
noStroke();
// film
if(is_film_selected) fill(255, 150);
const film_height = height - bottom_padding - 20;
rect(film_pos, 10, fw, film_height);
// Cam
fill(255);
if(is_cam_selected) fill(255, 150);
rect(cam_pos, 10, cw, (height - bottom_padding - 20 - aperture) / 2);
rect(
cam_pos,
10 + (height - bottom_padding - 20 - aperture) / 2 + aperture,
cw,
(height - bottom_padding - 20 - aperture) / 2
);
// Obj 1
strokeWeight(3);
stroke("#E5483CAD");
fill("#E5483CAD");
if(is_obj1_selected) fill("#B12A20AD");
circle(obj1_pos, (height - bottom_padding) / 2, 2 * r1);
strokeWeight(1);
// Lines
stroke("#F44336");
const alpha3 = (r1 / (obj1_pos - cam_pos)) * (cam_pos - (film_pos + fw / 2));
a1 = (height - bottom_padding) / 2 - alpha3;
b1 = (height - bottom_padding) / 2 + alpha3;
line(
obj1_pos,
(height - bottom_padding) / 2 + r1,
film_pos + fw,
a1
);
line(
obj1_pos,
(height - bottom_padding) / 2 - r1,
film_pos + fw,
b1
);
noStroke();
// Obj 2
strokeWeight(3);
stroke("#38E686");
fill("#38E686AD");
if(is_obj2_selected) fill("#0E9249AD");
circle(obj2_pos, (height - bottom_padding) / 2, 2 * r2);
strokeWeight(1);
// Lines
stroke("#38E686");
const alpha3_2 = (r2 / (obj2_pos - cam_pos)) * (cam_pos - (film_pos + fw / 2));
a2 = (height - bottom_padding) / 2 - alpha3_2;
b2 = (height - bottom_padding) / 2 + alpha3_2;
line(
obj2_pos,
(height - bottom_padding) / 2 + r2,
film_pos + fw,
a2
);
line(
obj2_pos,
(height - bottom_padding) / 2 - r2,
film_pos + fw,
b2
);
noStroke();
// Texts
fill(255, 100);
textAlign(CENTER);
textSize(16);
text("Pin-hole Camera Simulator by Gholamreza Dar 2023", width/2, 20);
textSize(12);
fill(255, 50);
text("Try dragging something...", width/2, 40);
fill(255, 100);
text(
`${abs(film_pos - cam_pos)} px`,
(film_pos + cam_pos) / 2,
height - bottom_padding / 2
);
fill("#E5483CAD");
text(
`${abs(cam_pos - obj1_pos)} px`,
(cam_pos + obj1_pos) / 2,
height - bottom_padding / 2
);
fill("#38E68642");
text(
`${abs(obj1_pos - obj2_pos)} px`,
(obj1_pos + obj2_pos) / 2,
height - bottom_padding / 2
);
textAlign(LEFT);
fill(255, 25);
text(
`sensor`,
film_pos + fw + object_margin,
height-bottom_padding-10
);
text(
`pinhole camera`,
cam_pos + cw + object_margin,
height-bottom_padding-10
);
// TV frame
push();
translate(width-tvw, height-tvh);
fill(0, 20);
// stroke(20);
rect(0, 0, tvw, tvh);
noStroke();
fill(255, 100);
textAlign(CENTER);
text(
`Camera POV`,
tvw/2,
15
);
// TV content
push();
translate(tvw/2, tvh/2);
// Which obj is in front
let is_obj1_front = true;
if(obj2_pos-r2 < obj1_pos-r1){
is_obj1_front = false;
}
// calcualte the rendered radii
let rendered_d1 = abs(a1-b1)/film_height*tvh;
let rendered_d2 = abs(a2-b2)/film_height*tvh;
if(is_obj1_front){
fill("#38E686");
circle(0, 0, rendered_d2);
fill("#E5483C");
circle(0, 0, rendered_d1);
}
else{
fill("#E5483C");
circle(0, 0, rendered_d1);
fill("#38E686");
circle(0, 0, rendered_d2);
}
pop();
pop();
// bottom lines
noStroke();
const bottomrecth = 2;
fill(255, 100);
rect(film_pos, height-bottomrecth, cam_pos-(film_pos), bottomrecth);
fill("#E5483CAD");
rect(cam_pos, height-bottomrecth, obj1_pos-(cam_pos), bottomrecth);
fill("#38E68642");
rect(obj1_pos, height-bottomrecth, -(obj1_pos-obj2_pos), bottomrecth);
}