Created
March 9, 2023 13:10
-
-
Save akirayou/749e8e8904118c55089a55686882a867 to your computer and use it in GitHub Desktop.
魚眼カメラをthree.jsでパン・チルトして表示
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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