mirror of
https://github.com/TomHodson/tomhodson.github.com.git
synced 2025-06-26 10:01:18 +02:00
fix page
This commit is contained in:
parent
2e05be2a70
commit
3157992b04
@ -80,6 +80,23 @@
|
|||||||
<script src="/assets/mathjax/tex-mml-svg.js" id="MathJax-script" defer></script>
|
<script src="/assets/mathjax/tex-mml-svg.js" id="MathJax-script" defer></script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if page.model_viewer %}
|
||||||
|
|
||||||
|
<script async src="/node_modules/es-module-shims/dist/es-module-shims.js"></script>
|
||||||
|
|
||||||
|
<script type="importmap">
|
||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"three": "/node_modules/three/build/three.module.min.js",
|
||||||
|
"three/addons/": "/node_modules/three/examples/jsm/",
|
||||||
|
"lil-gui": "/node_modules/lil-gui/dist/lil-gui.esm.min.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script src="/assets/js/outline-model-viewer/index.js" type="module"></script>
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if page.load_klipse %}
|
{% if page.load_klipse %}
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/klipse/codemirror.css">
|
<link rel="stylesheet" type="text/css" href="/assets/klipse/codemirror.css">
|
||||||
<script src="/assets/klipse/setup_klipse.js" defer></script>
|
<script src="/assets/klipse/setup_klipse.js" defer></script>
|
||||||
|
@ -20,25 +20,11 @@ alt: An image of the text "{...}" to suggest the idea of a template.
|
|||||||
image_class: invertable # For images that look good when inverted in dark modes by default they're dimmed
|
image_class: invertable # For images that look good when inverted in dark modes by default they're dimmed
|
||||||
|
|
||||||
mathjax: true
|
mathjax: true
|
||||||
|
model_viewer: true
|
||||||
|
load_klipse: true
|
||||||
|
|
||||||
head: |
|
head: |
|
||||||
<script async src="/node_modules/es-module-shims/dist/es-module-shims.js"></script>
|
<meta name="robots" content="noindex">
|
||||||
|
|
||||||
<script type="importmap">
|
|
||||||
{
|
|
||||||
"imports": {
|
|
||||||
"three": "/node_modules/three/build/three.module.min.js",
|
|
||||||
"three/addons/": "/node_modules/three/examples/jsm/",
|
|
||||||
"lil-gui": "/node_modules/lil-gui/dist/lil-gui.esm.min.js"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script src="/assets/js/projects.js" type="module"></script>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -209,176 +195,7 @@ footnote[^2].
|
|||||||
|
|
||||||
* * *
|
* * *
|
||||||
|
|
||||||
<canvas style ="width: 100%;" id="myCanvas"></canvas>
|
|
||||||
|
|
||||||
<script type="module">
|
|
||||||
import * as THREE from "three";
|
|
||||||
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
|
|
||||||
import { DragControls } from "three/addons/controls/DragControls.js";
|
|
||||||
|
|
||||||
let scene, camera, renderer;
|
|
||||||
let orbitControls, dragControls;
|
|
||||||
let sphereA, sphereB;
|
|
||||||
let arrowA, arrowB, arrowCross;
|
|
||||||
let objectsToDrag = [];
|
|
||||||
const d = 1;
|
|
||||||
|
|
||||||
init();
|
|
||||||
animate();
|
|
||||||
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
const canvas = document.getElementById('myCanvas');
|
|
||||||
|
|
||||||
// --- Scene ---
|
|
||||||
scene = new THREE.Scene();
|
|
||||||
const aspect = canvas.clientWidth / canvas.clientHeight;
|
|
||||||
camera = new THREE.OrthographicCamera(
|
|
||||||
-d * aspect, // left
|
|
||||||
d * aspect, // right
|
|
||||||
d, // top
|
|
||||||
-d, // bottom
|
|
||||||
-100, // near
|
|
||||||
100 // far
|
|
||||||
);
|
|
||||||
camera.position.set(5, 5, 5);
|
|
||||||
camera.lookAt(0, 0, 0);
|
|
||||||
|
|
||||||
// --- Renderer (use the existing canvas) ---
|
|
||||||
renderer = new THREE.WebGLRenderer({ alpha: true, canvas: canvas, antialias: true });
|
|
||||||
renderer.setSize(canvas.clientWidth, canvas.clientHeight,);
|
|
||||||
|
|
||||||
// --- OrbitControls ---
|
|
||||||
orbitControls = new OrbitControls(camera, renderer.domElement);
|
|
||||||
// orbitControls.enableRotate = false; // Keep isometric
|
|
||||||
orbitControls.enablePan = false;
|
|
||||||
orbitControls.enableDamping = true;
|
|
||||||
orbitControls.dampingFactor = 0.05;
|
|
||||||
|
|
||||||
// const gridHelper = new THREE.GridHelper(5, 25, 0x444444, 0x888888);
|
|
||||||
// scene.add(gridHelper);
|
|
||||||
|
|
||||||
// --- Spheres for vector endpoints (draggable) ---
|
|
||||||
const sphereGeom = new THREE.SphereGeometry(0.08, 16, 16);
|
|
||||||
const sphereMat = new THREE.MeshStandardMaterial({ color: 0x000000 });
|
|
||||||
|
|
||||||
sphereA = new THREE.Mesh(sphereGeom, sphereMat);
|
|
||||||
sphereB = new THREE.Mesh(sphereGeom, sphereMat);
|
|
||||||
|
|
||||||
// Initial positions
|
|
||||||
sphereA.position.set(0, 0, 1);
|
|
||||||
sphereB.position.set(1, 0, 0);
|
|
||||||
|
|
||||||
scene.add(sphereA);
|
|
||||||
scene.add(sphereB);
|
|
||||||
objectsToDrag.push(sphereA, sphereB);
|
|
||||||
|
|
||||||
// --- Lights ---
|
|
||||||
const ambientLight = new THREE.AmbientLight(0xffffff, 0.7);
|
|
||||||
scene.add(ambientLight);
|
|
||||||
|
|
||||||
const dirLight = new THREE.DirectionalLight(0xffffff, 0.7);
|
|
||||||
dirLight.position.set(5, 5, 10);
|
|
||||||
scene.add(dirLight);
|
|
||||||
|
|
||||||
// --- Arrows for A, B, and A x B ---
|
|
||||||
const headLength = 0.1;
|
|
||||||
const headWidth = 0.1;
|
|
||||||
|
|
||||||
arrowA = new THREE.ArrowHelper(
|
|
||||||
new THREE.Vector3(1, 0, 0).normalize(),
|
|
||||||
new THREE.Vector3(0, 0, 0),
|
|
||||||
1,
|
|
||||||
0x000000, headLength, headWidth
|
|
||||||
);
|
|
||||||
arrowB = new THREE.ArrowHelper(
|
|
||||||
new THREE.Vector3(0, 1, 0).normalize(),
|
|
||||||
new THREE.Vector3(0, 0, 0),
|
|
||||||
1,
|
|
||||||
0x000000, headLength, headWidth
|
|
||||||
);
|
|
||||||
// Cross product arrow in red
|
|
||||||
arrowCross = new THREE.ArrowHelper(
|
|
||||||
new THREE.Vector3(0, 0, 1).normalize(),
|
|
||||||
new THREE.Vector3(0, 0, 0),
|
|
||||||
1,
|
|
||||||
0xff0000, headLength, headWidth
|
|
||||||
);
|
|
||||||
|
|
||||||
scene.add(arrowA);
|
|
||||||
scene.add(arrowB);
|
|
||||||
scene.add(arrowCross);
|
|
||||||
|
|
||||||
// --- DragControls ---
|
|
||||||
dragControls = new DragControls(objectsToDrag, camera, renderer.domElement);
|
|
||||||
|
|
||||||
// Disable orbiting during drag
|
|
||||||
dragControls.addEventListener('dragstart', function () {
|
|
||||||
orbitControls.enabled = false;
|
|
||||||
});
|
|
||||||
dragControls.addEventListener('dragend', function () {
|
|
||||||
orbitControls.enabled = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Keep spheres in XZ plane, update arrows
|
|
||||||
dragControls.addEventListener('drag', (event) => {
|
|
||||||
event.object.position.y = 0;
|
|
||||||
updateArrows();
|
|
||||||
});
|
|
||||||
|
|
||||||
updateArrows();
|
|
||||||
|
|
||||||
window.addEventListener('resize', onWindowResize, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update arrow directions and lengths based on sphere positions
|
|
||||||
function updateArrows() {
|
|
||||||
const A = new THREE.Vector3().copy(sphereA.position);
|
|
||||||
const B = new THREE.Vector3().copy(sphereB.position);
|
|
||||||
|
|
||||||
// Update arrow A
|
|
||||||
const lengthA = A.length();
|
|
||||||
arrowA.setLength(lengthA, 0.2 * lengthA, 0.2 * lengthA);
|
|
||||||
arrowA.setDirection(A.clone().normalize());
|
|
||||||
arrowA.position.set(0, 0, 0);
|
|
||||||
|
|
||||||
// Update arrow B
|
|
||||||
const lengthB = B.length();
|
|
||||||
arrowB.setLength(lengthB, 0.2 * lengthB, 0.2 * lengthB);
|
|
||||||
arrowB.setDirection(B.clone().normalize());
|
|
||||||
arrowB.position.set(0, 0, 0);
|
|
||||||
|
|
||||||
// A x B
|
|
||||||
const cross = new THREE.Vector3().crossVectors(A, B);
|
|
||||||
const lengthCross = cross.length();
|
|
||||||
|
|
||||||
let directionCross = cross.clone().normalize();
|
|
||||||
// If cross is zero (or close to zero), set a default
|
|
||||||
if (isNaN(directionCross.x)) {
|
|
||||||
directionCross.set(0, 0, 1);
|
|
||||||
}
|
|
||||||
arrowCross.setDirection(directionCross);
|
|
||||||
arrowCross.setLength(lengthCross, 0.2 * lengthCross, 0.2 * lengthCross);
|
|
||||||
arrowCross.position.set(0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onWindowResize() {
|
|
||||||
const aspect = canvas.clientWidth / canvas.clientHeight;
|
|
||||||
camera.left = -d * aspect;
|
|
||||||
camera.right = d * aspect;
|
|
||||||
camera.top = d;
|
|
||||||
camera.bottom = -d;
|
|
||||||
camera.updateProjectionMatrix();
|
|
||||||
|
|
||||||
renderer.setSize(canvas.clientWidth, canvas.clientHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
function animate() {
|
|
||||||
requestAnimationFrame(animate);
|
|
||||||
orbitControls.update();
|
|
||||||
renderer.render(scene, camera);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<figure class="multiple">
|
<figure class="multiple">
|
||||||
<img src="/assets/blog/alpha_test/original.jpg" class = "no-dim">
|
<img src="/assets/blog/alpha_test/original.jpg" class = "no-dim">
|
||||||
@ -388,3 +205,20 @@ function animate() {
|
|||||||
<figcaption> Here are some images, (top left) original, (top right) white subtracted and replaced with alpha, (bottom left) same but brightened, (bottom right) ai background removal tool (loses shadow) </figcaption>
|
<figcaption> Here are some images, (top left) original, (top right) white subtracted and replaced with alpha, (bottom left) same but brightened, (bottom right) ai background removal tool (loses shadow) </figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
## 3D models
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<img class="outline-model-poster no-wc" src = "/assets/projects/bike_lights/thumbnail.svg">
|
||||||
|
<outline-model-viewer model = "/assets/blog/vector_magnet/vector_magnet.glb" zoom=500 camera='{"position":[3.118,3.203,10.1],"rotation":[-0.3104,0.2858,0.0902],"zoom":428.68750000000136,"target":[0,0,0]}'>
|
||||||
|
</outline-model-viewer>
|
||||||
|
<figcaption class="no-wc">If you have JS enabled this is interactive.</figcaption>
|
||||||
|
<figcaption class="has-wc">An interactive point cloud view. Should show a billboard if JS is disabled.</figcaption>
|
||||||
|
</figure>
|
||||||
|
|
||||||
|
<figure>
|
||||||
|
<img class="no-wc" src="{{page.assets}}/rear_stereo/point_cloud_preview.png">
|
||||||
|
<point-cloud-viewer model="/assets/blog/heic_depth_map/rear_stereo/pointcloud.pcd" camera = '{"type":"perspective","position":[-3.598,-0.4154,1.971],"rotation":[0.2078,-1.06,0.1819],"zoom":1,"target":[0,0,0]}'>
|
||||||
|
</point-cloud-viewer>
|
||||||
|
<figcaption class="no-wc">If you have JS enabled this is interactive.</figcaption>
|
||||||
|
<figcaption class="has-wc">An interactive point cloud view. Should show a billboard if JS is disabled.</figcaption>
|
||||||
|
</figure>
|
@ -22,7 +22,6 @@ head: |
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script src="/assets/js/projects.js" type="module"></script>
|
|
||||||
|
|
||||||
draft: true
|
draft: true
|
||||||
---
|
---
|
||||||
|
@ -9,21 +9,7 @@ social_image: /assets/blog/heic_depth_map/thumbnail.png
|
|||||||
|
|
||||||
alt: An image of the text "{...}" to suggest the idea of a template.
|
alt: An image of the text "{...}" to suggest the idea of a template.
|
||||||
|
|
||||||
head: |
|
model_viewer: true
|
||||||
<script async src="/node_modules/es-module-shims/dist/es-module-shims.js"></script>
|
|
||||||
|
|
||||||
<script type="importmap">
|
|
||||||
{
|
|
||||||
"imports": {
|
|
||||||
"three": "/node_modules/three/build/three.module.min.js",
|
|
||||||
"three/addons/": "/node_modules/three/examples/jsm/",
|
|
||||||
"lil-gui": "/node_modules/lil-gui/dist/lil-gui.esm.min.js"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script src="/assets/js/projects.js" type="module"></script>
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
You know how iPhones do this fake depth of field effect where they blur the background? Did you know that the depth information used to do that effect is stored in the file?
|
You know how iPhones do this fake depth of field effect where they blur the background? Did you know that the depth information used to do that effect is stored in the file?
|
||||||
@ -104,74 +90,9 @@ Click and drag to spin me around. It didn't really capture my nose very well, I
|
|||||||
<point-cloud-viewer model="/assets/blog/heic_depth_map/rear_stereo/pointcloud.pcd" camera = '{"type":"perspective","position":[-3.598,-0.4154,1.971],"rotation":[0.2078,-1.06,0.1819],"zoom":1,"target":[0,0,0]}'>
|
<point-cloud-viewer model="/assets/blog/heic_depth_map/rear_stereo/pointcloud.pcd" camera = '{"type":"perspective","position":[-3.598,-0.4154,1.971],"rotation":[0.2078,-1.06,0.1819],"zoom":1,"target":[0,0,0]}'>
|
||||||
</point-cloud-viewer>
|
</point-cloud-viewer>
|
||||||
<figcaption class="no-wc">If you have JS enabled this is interactive.</figcaption>
|
<figcaption class="no-wc">If you have JS enabled this is interactive.</figcaption>
|
||||||
<figcaption class="has-wc">An interactive point cloud view.</figcaption>
|
<figcaption class="has-wc">An interactive point cloud view of the depth data from the rear facing camera of my phone.</figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
|
||||||
<script type="module">
|
|
||||||
// import * as THREE from "three";
|
|
||||||
// import { OrbitControls } from "three/addons/controls/OrbitControls.js";
|
|
||||||
// import { DragControls } from "three/addons/controls/DragControls.js";
|
|
||||||
// import { PCDLoader } from 'three/addons/loaders/PCDLoader.js';
|
|
||||||
// import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// init('canvas-id-1', '{{page.assets}}/rear_stereo/pointcloud.pcd');
|
|
||||||
// init('canvas-id-2', '{{page.assets}}/front_facing/pointcloud.pcd');
|
|
||||||
|
|
||||||
// function init(canvas_id, url) {
|
|
||||||
// let render, gui, orbitControls;
|
|
||||||
// let canvas = document.getElementById(canvas_id);
|
|
||||||
// const loader = new PCDLoader();
|
|
||||||
// let scene = new THREE.Scene();
|
|
||||||
// scene.add( new THREE.AxesHelper( 1 ) );
|
|
||||||
|
|
||||||
// loader.load(url, function ( points ) {
|
|
||||||
// points.geometry.center();
|
|
||||||
// points.geometry.rotateZ( -Math.PI/2 );
|
|
||||||
// points.name = 'depth_map';
|
|
||||||
// scene.add( points );
|
|
||||||
// points.material.color = new THREE.Color(0x999999);
|
|
||||||
// points.material.size = 0.001
|
|
||||||
// render();
|
|
||||||
|
|
||||||
// } );
|
|
||||||
|
|
||||||
// // --- Scene ---
|
|
||||||
// const aspect = canvas.clientWidth / canvas.clientHeight;
|
|
||||||
// let camera = new THREE.PerspectiveCamera( 30, aspect, 0.01, 40 );
|
|
||||||
// camera.position.set( -2, 2, 3);
|
|
||||||
// camera.lookAt(0, 0, 0);
|
|
||||||
|
|
||||||
// // --- Renderer (use the existing canvas) ---
|
|
||||||
// let renderer = new THREE.WebGLRenderer({ alpha: true, canvas: canvas, antialias: true });
|
|
||||||
// renderer.setSize(canvas.clientWidth, canvas.clientHeight,);
|
|
||||||
|
|
||||||
// render = () => renderer.render(scene, camera);
|
|
||||||
|
|
||||||
// // --- OrbitControls ---
|
|
||||||
// orbitControls = new OrbitControls(camera, renderer.domElement);
|
|
||||||
// orbitControls.addEventListener( 'change', render);
|
|
||||||
|
|
||||||
// const ambientLight = new THREE.AmbientLight(0xffffff, 0.7);
|
|
||||||
// scene.add(ambientLight);
|
|
||||||
|
|
||||||
// const dirLight = new THREE.DirectionalLight(0xffffff, 0.7);
|
|
||||||
// dirLight.position.set(5, 5, 10);
|
|
||||||
// scene.add(dirLight);
|
|
||||||
|
|
||||||
// window.addEventListener('resize', onWindowResize, false);
|
|
||||||
|
|
||||||
// function onWindowResize() {
|
|
||||||
// camera.aspect = canvas.clientWidth / canvas.clientHeight;
|
|
||||||
// camera.updateProjectionMatrix();
|
|
||||||
// renderer.setSize(canvas.clientWidth, canvas.clientHeight);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
</script>
|
|
||||||
|
|
||||||
## Update
|
## Update
|
||||||
|
|
||||||
After looking a bit more into this, I found the [Apple docs on capturing depth information](https://developer.apple.com/documentation/avfoundation/capturing-photos-with-depth) which explains that for phones with two or more front cameras, they use the difference in the two images to estimate depth, while the front facing camera on modern phones has [an IR camera](https://developer.apple.com/documentation/avfoundation/avcapturedevice/devicetype-swift.struct/builtintruedepthcamera) that uses a grid of dots to estimate true depth like the good old kinect sensor.
|
After looking a bit more into this, I found the [Apple docs on capturing depth information](https://developer.apple.com/documentation/avfoundation/capturing-photos-with-depth) which explains that for phones with two or more front cameras, they use the difference in the two images to estimate depth, while the front facing camera on modern phones has [an IR camera](https://developer.apple.com/documentation/avfoundation/avcapturedevice/devicetype-swift.struct/builtintruedepthcamera) that uses a grid of dots to estimate true depth like the good old kinect sensor.
|
||||||
@ -191,5 +112,5 @@ The depth information, while lower resolution, is much better. My nose really po
|
|||||||
<point-cloud-viewer model="/assets/blog/heic_depth_map/front_facing/pointcloud.pcd" camera = '{"type":"perspective","position":[-3.682,0.3606,1.82],"rotation":[-0.1955,-1.104,-0.1751],"zoom":1,"target":[0,0,0]}'>
|
<point-cloud-viewer model="/assets/blog/heic_depth_map/front_facing/pointcloud.pcd" camera = '{"type":"perspective","position":[-3.682,0.3606,1.82],"rotation":[-0.1955,-1.104,-0.1751],"zoom":1,"target":[0,0,0]}'>
|
||||||
</point-cloud-viewer>
|
</point-cloud-viewer>
|
||||||
<figcaption class="no-wc">If you have JS enabled this is interactive.</figcaption>
|
<figcaption class="no-wc">If you have JS enabled this is interactive.</figcaption>
|
||||||
<figcaption class="has-wc">An interactive point cloud view.</figcaption>
|
<figcaption class="has-wc">An interactive point cloud view of the depth from the front facing camera of an iPhone.</figcaption>
|
||||||
</figure>
|
</figure>
|
Loading…
x
Reference in New Issue
Block a user