Palash 3D Projector
Sun Lee簡介
此投影機的原理為透過螢幕將畫面照設置透明壓克力板,透過壓克力的折射,產生出立體的影像,以下我將從3個部份來介紹我們的3D投影機
- 硬體架構
- 畫面呈現
- 遠端控制
1.硬體架構
螢幕:我們使用22吋螢幕*1
透明壓克力板*3:設計圖參考如下:
根據螢幕大小,我們的所需木頭如下:
薄木板:58公分*38公分
木框長邊:58公分角木頭*4
木框短邊:33公分角木頭*4
木框支撐:30公分角木頭*2
木框支撐:角落固定架*4
黑色噴漆:1灌
組裝過程:使用釘子將框釘好
裝訂完成後,建議再加上角落固定架,確保整體的支撐穩定度
組裝完成之後,為了之後整體效果,建議漆上全黑色,以確保展示之品質
2.畫面呈現
我們採用播放影片的方式,將預錄好的畫面,折射至壓克力板上,使其產生立體效果。
而立體米果畫面來源為:http://palashntub.000webhostapp.com/projector.html
由我們自行開發的米果展示網頁,改變背景而成,使用Three.js技術將立體圖案呈現於HTML網頁上。
網頁原始碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Palash Rice Cracker 3d viewer</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="Description" content="Check the 3D Palash Rice Cracker by THREE.js">
<link rel="icon" href="favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="assets/css/3d.css" />
</head>
<body style="margin:0;" onload="myFunction()">
<div id="logos">
<div class="logos_img">
<img src="images/logos.png" alt="Palash3D">
</div>
<div id="loader"></div>
</div>
<div id="canvas" style="display:none">
<div class="link">
<p>Palash Rice Cracker 3D simulation</p>
<a target="_blank" href="index.html">Click to Palash Home page</a>
</div>
</div>
<script>
var myVar;
function myFunction() {
myVar = setTimeout(showPage, 5000);
}
function showPage() {
document.getElementById("logos").style.display = "none";
document.getElementById("canvas").style.display = "block";
//document.getElementsByTagName("canvas").style.display = "none";
}
</script>
<script type="module">
import * as THREE from 'https://threejs.org/build/three.module.js';
import { OBJLoader } from 'https://threejs.org/examples/jsm/loaders/OBJLoader.js';
import { MTLLoader } from 'https://threejs.org/examples/jsm/loaders/MTLLoader.js';
import { DDSLoader } from 'https://threejs.org/examples/jsm/loaders/DDSLoader.js';
import Stats from 'https://threejs.org/examples/jsm/libs/stats.module.js';
import { GUI } from 'https://threejs.org/examples/jsm/libs/dat.gui.module.js';
import { OrbitControls } from 'https://threejs.org/examples/jsm/controls/OrbitControls.js';
import { RGBELoader } from 'https://threejs.org/examples/jsm/loaders/RGBELoader.js';
draw();
var renderer;
function initRender() {
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(window.innerWidth, window.innerHeight);
//陰影效果
renderer.setClearColor(0xffffff);
document.getElementById("canvas").appendChild(renderer.domElement);
}
var camera;
function initCamera() {
camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.set(-35, 55, 95);
camera.lookAt(new THREE.Vector3(0,0,0));
}
var scene;
function initScene() {
scene = new THREE.Scene();
}
function initLight() {
var ambientLight = new THREE.AmbientLight(0xcccccc, 1.5);
scene.add(ambientLight);
var pointLight = new THREE.PointLight(0xffffff, 1);
camera.add(pointLight);
//告訴平行光需要開啟陰影投射
pointLight.castShadow = false;
scene.add(pointLight);
}
function initModel() {
new RGBELoader()
.setDataType(THREE.UnsignedByteType)
.load('https://cdn.jsdelivr.net/gh/nyy28477590/palash/background.hdr', function(texture) {
var envMap = pmremGenerator.fromEquirectangular(texture).texture;
scene.background = envMap;
scene.environment = envMap;
texture.dispose();
pmremGenerator.dispose();
render();
//model
var onProgress = function ( xhr ) {
if ( xhr.lengthComputable ) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log( Math.round( percentComplete, 2 ) + '% downloaded' );
}
};
var onError = function () { };
var manager = new THREE.LoadingManager();
manager.addHandler( /\.dds$/i, new DDSLoader() );
new MTLLoader( manager )
.load( 'https://cdn.jsdelivr.net/gh/nyy28477590/palash/palash5.mtl', function ( materials ) {
materials.preload();
new OBJLoader( manager )
.setMaterials( materials )
.load( 'https://cdn.jsdelivr.net/gh/nyy28477590/palash/palash5.obj', function ( object ) {
object.scale.set(1.3, 1.3, 1.3); //縮放
object.position.y = 0;
object.position.x = 0;
scene.add( object );
}, onProgress, onError );
} );
})
var pmremGenerator = new THREE.PMREMGenerator( renderer );
pmremGenerator.compileEquirectangularShader();
}
//初始化性能顯示
var stats;
function initStats() {
stats = new Stats();
document.getElementById("canvas").appendChild(stats.dom);
}
//滑鼠左鍵可以旋轉,右鍵重新平移,滾輪縮放
var controls;
function initControls() {
controls = new OrbitControls( camera, renderer.domElement );
//是否有慣性
controls.enableDamping = true;
//滑鼠靈敏度
controls.dampingFactor = 0.25;
//是否可以縮放
controls.enableZoom = true;
//是否自動旋轉
controls.autoRotate = true;
controls.autoRotateSpeed = 0.5;
//相機距離原點的最進距離
controls.minDistance = 1;
//相機距離原點的最遠距離
controls.maxDistance = 200;
//開啟右鍵拖移
controls.enablePan = true;
}
function render() {
renderer.render( scene, camera );
}
//變動觸發的函數
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
render();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
//更新控制器
render();
controls.update();
requestAnimationFrame(animate);
}
function draw() {
initRender();
initScene();
initCamera();
initLight();
initModel();
initControls();
animate();
window.onresize = onWindowResize;
}
</script>
</body>
</html>
米果呈現影片:
LOGO漂浮影片:
3.遠端控制
我們使用了樹莓派3做為控制中心,將呈現畫面放到樹莓派裡
再將分別根據播放的影片寫成獨立的Python檔案
程式碼如下:
from omxplayer
import OMXPlayer.player from pathlib import Path
from time import sleep
VIDEO_PATH = Path("/home/pi/Videos/palash.mp4")#自行更換要播放的影片位址
player = OMXPlayer(VIDEO_PATH)
sleep(15)
player.quit()
接者使用Node-red(事先安裝好),建立按鈕(左邊藍色部分),將樹莓派Lunix指令與按鈕連接起來
範例程式碼:
執行Python檔:python3 /home/pi/Desktop/palash.py
停止播放:pkill omxplayer
完成之後,部署應用程式完成後,即可透過區域連線控制此樹莓派,適用裝置包括手機、筆電、平板電腦等可以連上網的裝置都行!
控制網址:區域網路ip:1880/ui
參考資料
Holographic Audio Visualizer with Motion Control: https://www.hackster.io/hackershack/holographic-audio-visualizer-with-motion-control-e72fee
Three.js: https://threejs.org/
特別感謝
國際商務系 林純如 副教授
山雲創新科技執行長 Kent Su
國際商務系 系辦公室
同學爸爸
協助製作
如果有任何問題歡迎聯絡我,聯絡方式:
Email: nyy28477590@gmail.com
Line: sunlee0329
Instagram: sunlee0329
GitHub: https://github.com/nyy28477590