Skip to content

Instantly share code, notes, and snippets.

@akirayou
Created March 9, 2023 13:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akirayou/749e8e8904118c55089a55686882a867 to your computer and use it in GitHub Desktop.
Save akirayou/749e8e8904118c55089a55686882a867 to your computer and use it in GitHub Desktop.
魚眼カメラをthree.jsでパン・チルトして表示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://unpkg.com/three@0.147.0/build/three.min.js"></script>
<script>
//videoタグにUSBカメラ画像を流し込む
window.addEventListener('DOMContentLoaded', init);
function init_video() {
navigator.mediaDevices.enumerateDevices()
.then(function (devices) {
let devs = []
devices.forEach(function (device) {
console.log(device);
if (device.kind == "video.input") device.deviceId;
devs.push(device.deviceId);
});
const video = document.getElementById("video")
navigator.mediaDevices.getUserMedia({
video: { deviceId: devs[0], width: 3264, height: 2448 },
audio: false,
}).then(stream => {
video.srcObject = stream;
video.play()
}).catch(e => {
console.log(e)
});
})
}
//Sphere の場合
//w_segs+1の点数だけuvが並び
//それがh_segs+1段スタックしている。
//魚眼の射影を考えると回転角方向にw_seg+1を割り当て
// h_segsの分だけ
function fishUV(W, H) {
var uv = new Float32Array(W * H * 2);
const cx = 0.5;
const cy = 0.5;
const R = 0.5*180/170;
var c = 0;
for (h = 0; h < H; h++)
for (w = 0; w < W; w++) {
const theta = w / (W - 1) * 2 * Math.PI;
const radius = h / (H - 1) * R * 2;
uv[c] = cx - radius * Math.cos(theta);
c++;
uv[c] = cy + radius * Math.sin(theta);
c++;
}
return uv;
}
function init() {
init_video();
// サイズを指定
const width = 960;
const height = 960*3/4;
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#myCanvas')
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, width / height);
//skybox代わりの球をさくせい
const w_segs = 32;
const h_segs = 16;
const geometry = new THREE.SphereGeometry(100, w_segs, h_segs);
//uv座標系を設定(シェーダのほうが綺麗だけど、uvならjsだけかける)
const uv = fishUV(w_segs + 1, h_segs + 1);
geometry.setAttribute('uv', new THREE.BufferAttribute(uv, 2));
const texture = new THREE.VideoTexture(video);
const material = new THREE.MeshBasicMaterial({ map: texture, color: 0xffffff, side: THREE.DoubleSide });
const sky = new THREE.Mesh(geometry, material);
scene.add(sky);
sky.rotation.x = -Math.PI / 2; //デフォルトのカメラのむきを正面に変えておく
tick();
function tick() {
//カメラを時間にあわせて振る(めっちゃ酔う)
look=new THREE.Vector3(
Math.sin(performance.now() / 1000 * 1.0),
Math.sin(performance.now() / 1000 * 0.3),
-1);
camera.lookAt(look);
renderer.render(scene, camera);
requestAnimationFrame(tick);
}
}
</script>
</head>
<body>
<video id="video" style="width:960px"></video>
<canvas id="myCanvas"></canvas>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment