學習如 Oculus Rift 等VR設備開發需要掌握哪些知識/技術?


要想完整說明的話,先要明確以下Oculus Rift是個什麼概念。

Oculus Rift是一種虛擬現實儀器(以下簡稱rift),用一個遮罩在雙眼前的不透明顯示器,搭配兩個可更換透鏡,高質量陀螺儀、加速度感測器和地磁感測器,以及後來的位置跟蹤器(DK2專有)而成的一整套設備。目前rift尚未發布面向正式消費者的版本,而只公開了兩個版本開發包(development kit),通常稱之為DK1和DK2。

Rift的工作原理分為兩部分。一部分跟目前3D電影或者3D眼鏡概念類似(順帶說一句,我個人比較討厭3D這個說法,太寬泛也極具商業欺騙性,更準確的說法是stereoscope,這裡感謝 @Milo Yip 指正),即模仿現實世界,通過為左右兩眼顯示不同的畫面,讓大腦合成一副帶有更多深度信息的「立體」圖像。另一部分是跟互動相關。由於rift不只是要做另一個Sony HMZ-T3W,所以它為了互動體驗還專門提供和優化了捕捉頭部運動的組件。Rift設備可以很精準且迅速地捕捉到頭部的任意旋轉,DK2更能在一個空間角範圍內捕捉頭部的線性運動。

結合這兩部分,rift能營造一個和現實世界完全隔絕的視覺環境,且能提供一定程度上的體感結合,即頭部旋轉和小範圍線性移動。在硬體上也做到了較好的廣視域和低延遲。

=============================
Rift的義務廣告到此結束。了解了rift是什麼後,我們進入正題:要具備怎樣的知識才能進行rift開發?

首當其衝的一點是3D相關知識。這裡我說的不是stereoscopic的「3D」,而是一些計算機圖形學基本知識。這裡面包括現代實時圖形應用的主要邏輯組成部分,包括:

  • 攝像機
  • 光照及其原理
  • 坐標系及其轉換
  • 材質和紋理系統
  • 基於網格的物件表示

其他方面如屏幕空間後處理效果、shader、動畫系統等鋪開的部分不是必須項。說得更明白一些,是一個運用3ds max/Maya這類數字內容創作軟體的創作人員應該熟知的部分。這方面稍有門檻,但不算太高。

在早期stereoscope概念出來的時候,很多開發者還必須關心如何在節省性能的前提下渲染左右兩張不同的畫面。而現在rift硬體和SDK已經做掉大部分工作,不要說什麼頭部高速同步,連透鏡色散和調瞳距都被我們卡馬克大神和Abrash大神做掉了。而且Oculus公司也跟很多引擎大廠合作,提供了這些引擎的插件。所以如果你用Unity或者Unreal的話,連SDK集成的事都可以省去了(out-of-box)。留給開發者的任務是更好地理解rift硬體所能帶給我們的特性,並將這些特性應用到實際應用中去。

舉個很實際的例子:由於rift是沉浸式的體驗,帶上了rift視覺上就跟外界說拜拜了。這時候輸入便成了一個棘手問題。如果要用戶在看到logo之後,再脫下rift去摸鍵盤就太弱了,而且不是所有鍵盤用戶都能應付盲打,保不齊某些用戶還要在使用過程中再脫下來去找鍵位。配備一個手柄會好一些,但不能從根本上解決問題。當然還有一些諸如掛載LeapMotion、MYO之類的解決方案,但這都超出了rift本身的範疇。就這個問題來說,我傾向於從rift能提供的輸入來著手解決。比如把頭部旋轉和移動不僅看做是攝像機的同步,還能當做一種輸入方式。這方面比較好的例子有《Titans of Space》和《Vanguard V》,但我最欣賞的還是Google Cardboard官方應用的做法(好像有奇怪的東西混了進來)。

所以我認為除了必要的3D知識之外,rift開發要學習的東西對於大部分人都是全新的,而且他們基本都屬於應用層問題。

官方煞費苦心地在官網放了很多關於如何開發rift應用的忠告(Oculus Best Practices Guide),主要是一些Do and Don"t的條例,有較多關於避免眩暈(sickness)和增強沉浸感方面的內容。不過我瀏覽了官方Oculus VR Share (Beta)中的demo(吐了)之後,卻發現好像甚少有人注意這些點。這裡先列出一些我初步看下來有必要關心的吧:

  • 從頭部動作到畫面展現之間的延遲控制在20ms以內,以減少眩暈感。可使用內置的延遲測試工具測試應用的延遲。
  • 使用位置跟蹤的場合下,當用戶接近跟蹤區域邊緣時,以某種方式提示用戶回到跟蹤區域內。
  • 不要嘗試修改圖像變形演算法、不要嘗試修改頭部跟蹤數據、不要嘗試修改位置跟蹤數據。
  • 人眼通過立體圖像獲得場景深度信息,對近處物體很敏感,一旦物體拉遠則感知度立即變差。
  • 儘可能地將UI融合在場景內,且最佳顯示的位置是距離觀察者2-3米的位置。準星一類的UI應該以聚焦對象的深度進行渲染。
  • 加速/停止會引起視覺和平衡器官之間的感知衝突,如果加速/停止不是由用戶發起的,則儘可能地避免上述情況。
  • 避免線性垂直震動,接近0.2Hz頻率的垂直震動讓人最感不適。非垂直震動在接近0.3Hz的頻率讓人最感不適。
  • Zoom,或鏡頭縮放效果,儘可能避免。
  • 避免要求用戶平移、後退、旋轉的場景。
  • 使用用戶熟知的環境作為背景(如響應頭部轉動的天空盒)有助於減輕視覺衝突和增強舒適感。
  • 避免使用高頻紋理(如條狀、精細的紋理),高頻紋理會增強環境中對於運動的感知,會讓人不適。改用低頻紋理可以改善這一狀況。
  • 解決用戶接觸輸入設備困難的問題,或者將頭部運動本身作為一種輸入方式。
  • 使用3D音效加強沉浸感。

最後還是夾一下私貨,這是我在知乎專欄寫的:[原]Oculus Rift DK2試用手記 - 燈塔實驗室,有興趣可以看看。

以上

====
UPDATE: 上面說到的「官方解決」的輸入問題,Oculus Touch控制器和Steam VR(HTC Vive)所提供的幾個原型控制器,可以算是初步解決問題了。相比之下Gear VR頭盔上的觸摸板、Cardboard上的磁塊撥片對於重度遊戲來說就顯得過於簡單了。

UPDATE2: 之前據體驗過Steam VR(HTC Vive)的同學講,它的控制器做到的一些類似力反饋效果拔群,例如在它的「修理場」demo里,俯身下去撿起一把扳手,並使用扳手擰螺帽的感覺很棒。道聽途說,權當參考。


請注意:此回答基於 DK1,並且不會再更新了。
----- ----- -----
如果想要開始 Oculus Rift 的開發,首要的一點是:你可以將 Oculus Rift 理解為一個擴展顯示器。這個顯示器有一點像我們平時看到的 3D 電視的屏幕,左右各有一個畫面,兩個畫面有視差。在使用的時候,左右眼各看到一個畫面。

所以,你只要應用各種方法實現這兩個畫面就可以了

如果你是 3D 遊戲的開發者,那麼可以通過各種開發工具來實現這兩個畫面同時顯示。當然,最快的方式是使用 Unity,因為 Oculus VR 已經提供了 Unity 的支持,其最主要的作用就是提供了一個支持 Oculus Rift 的攝像頭,只要將這個 camera 放入場景,那麼通過這個 camera 看到的畫面就已經是符合 Oculus Rift 要求的了。簡單來說,如果你已經做好了一個第一/第三人稱視角的 3D 遊戲,那麼用 Oculus VR 提供的 camera 替換掉正常的 camera,然後再做一些輔助工作就可以實現你想要的效果了。其它框架或者引擎也是大同小異(比如 Unreal 或者 Source Engine 等)。

其實我們使用 Oculus Rift 不一定局限在 3D 應用/遊戲中,我們也可以將其應用在網頁中。這個相對會複雜一些,目前常用的方法是在後台跑一個 Socket Server(甚至可以採用 node.js 來跑 http://socket.io),這個 Server 不斷的獲取 Oculus Rift 頭盔的數據變化,然後通過 Web Socket 傳遞給瀏覽器。瀏覽器裡面採用 WebGL(常用 three.js)來渲染兩個有視差的畫面,這時戴上 Oculus Rift 就可以看到效果。

有了這兩個例子,既然 Oculus Rift 是個顯示器,那麼我們是否需要專門去學習某些特定的知識就變得不那麼重要了,在了解了原理和特性之後,我們就可以使用我們用著比較順手的 Adobe Flash、Adobe AIR、Processing、SDL……等等具有圖形開發功能的工具來開發 Oculus Rift App 了。如果有 3D 攝影設備(3D 攝像機、3D Panorama 全景攝像機等),也完全可以做出支持 Oculus Rift 的帶有沉浸感的 3D 視頻。配合其它的附件,比如 Leap Motion(同樣也支持 Web 使用)等,就能做出更佳豐富的體驗了。

那麼,基於自己的現有的知識積累,說不定就能找到突破口。不斷的嘗試並且了解 Oculus Rift 的工作原理,吃透它的機能才是首要的。所以,關鍵還是在於要做出什麼樣的東西,拿出什麼樣的驚人想法(別忘了 2D 的遊戲/應用也是可能出現在 Oculus Rift 上的哦~還有直接用頭盔當遊戲控制器的也有哦~)。


碰巧在坡島的時候參加了一個VR Workshop,當時用了Unity 3D來做一個VR的Demo遊戲,類似Pacman迷宮這樣,所以對VR的開發也有一個初步的認識了,有一些乾貨,所以來答一下。

————————————
根據我的感覺,其實一個VR Game Developer和傳統的Game Developer並沒有巨大的區別。

= 基本能力 =

編程知識,寫代碼的能力。對框架的熟悉程度,學習新技術的能力。具體的路線的話選擇應該就比較多,跟一般的遊戲開發差別不大,還有3D建模的能力(美工,原型設計)。

有兩個我比較了解的路線。

1. Unity + VR SDK

直接使用Unity,導入專門的Oculus SDK,使用VR視角就好了,然後就是慢慢去磨咯。

我自己做的Demo:VR Workshop - pacman prototype(Youtube鏈接,需翻牆)

2. WebGL + Three.js + WebVR

VR meetup 上的 Demo: desertVR(用手機打開可以直接看在VR設備的效果)

因為WebGL實際上是按照OpenGL規範去設計的,所以學習WebGL可以從OpenGL開始。

具體學習可以參考某個關於WebGL學習路線的問題與下面的答案:WebGL 是否需要以 OpenGL 為學習基礎? - OpenGL。

如果要學習 OpenGL,那麼脫不了三本書
紅寶書 OpenGL Programming Guide,出到第八版
藍寶書 OpenGL SuperBible,出到第六版
橙寶書 OpenGL Shading Language,出到第三版

如果要學習OpenGL ES,那麼只有一本,入門的話我最推薦的是這本,它與 WebGL 的關係也最近
OpenGL ES 2.0 Programming Guide
(2014-04-26更新,已經出到 OpenGL ES 3.0 版本了)

其實還有一本最靠譜的
WebGL Programming Guide,但是還沒發售(2014-04-26更新,已發售)

2013-11-03 更新
WebGL高級編程:開發Web 3D圖形 是一本非常全面的書籍,推薦作為第一本入門書。

然後再加上一定的Javascript的知識,就可以開發了,利用Three.js這樣的框架 + WebVR就可以開發VR應用了。

WebGL現在雖然大部分都是Prototype的階段,但是由於Web非常利於傳播,一次開發全應用適配等等原因,加上現在基本上VR設備都會支持WebGL,所以有一定理由相信WebGL在未來會是遍地開花的情況

= 綜合能力 =

美術常識、遊戲系統設計算是綜合能力裡面最基本的。除了這些以外,任何的知識與人生體驗都有幫助。因為一款遊戲會融入了很多個人的東西。

因為是VR,所以還有一些別的要求,比方說設計交互方式,交互設備的能力,HCI的經驗等等,甚至一些醫學常識(比方說如何設計遊戲以避免暈眩,這一點在官方指南上也有提及)。

—————————————

補充:

我大概看了一下前面的答案,或多或少都說到了一些東西,但是都沒有全部說到點上,把他們結合在一起就是一個很好的答案了。

總結一下,

——@Shen Li 列舉了Valve招聘的要求。

或多或少說明了如何點技能點。比一般的Game Developer多出的要求就是HCI的經驗,畢竟如果使用VR的話,還有甚至能有一些硬體的知識最好,因為有可能需要自己去設計交互設備,畢竟光有視覺沒有體感不能算完整的VR。

——@didayin 提到了用SDK從零開發和用遊戲引擎的區別。
——@康托耶夫 講了一個自己開發的故事,其實還是蠻貼近現在的情況的。

利用遊戲引擎入門的話,其實花上很多很多的時間,細心設計,慢慢打磨都能做出一款很好的遊戲,對技術上的要求並不高,重要的在如何去實現你的東西,花多少時間,有多少能力和創意。

——@Ye Feng 提到了一個很重要的一點,就是設備暈眩的問題。

想必工程師們在開發Oculus Rift的時候就已經感受到了,並且提出了一些在遊戲設計上的解決辦法。(這一點我自己也是深有體會,我大概5分鐘左右就開始覺得噁心了,這種感覺和暈車的感覺是一樣的。)

個人見解,請多指教。

希望本答案能有幫助。


完整文章鏈接:Oculus + Node.js + Three.js 打造VR世界 |VR第一資訊 VR013

周五Hackday Showcase的時候,突然有了點小靈感,便將閑置在公司的Oculus DK2借回家了——已經都是灰塵了~~。

在嘗試一個晚上的開發環境搭建後,我放棄了開發原生應用的想法。一是沒有屬於自己的電腦(如果Raspberry Pi II不算的話)——沒有Windows、沒有GNU/Linux,二是公司配的電腦是Mac OS。對於嵌入式開發和遊戲開發來說,Mac OS簡直是手機中的Windows Phone——坑爹的LLVM、GCC(Mac OS )、OpenGL、OGLPlus、C++11。並且官方對Mac OS和Linux的SDK的支持已經落後了好幾個世紀。

說到底,還是Web的開發環境到底還是比較容易搭建的。這個repo的最後效果圖如下所示:

效果:

  1. WASD控制前進、後退等等。
  2. 旋轉頭部 = 真實的世界。
  3. 附加效果: 看久了頭暈。

現在,讓我們開始構建吧。

Node Oculus Services

這裡,我們所要做的事情便是將感測器返回來的四元數(Quaternions)與歐拉角(Euler angles)以API的形式返回到前端。

安裝Node NMD

Node.js上有一個Oculus的插件名為node-hmd,hmd即面向頭戴式顯示器。它就是Oculus SDK的Node介面,雖說年代已經有些久遠了,但是似乎是可以用的——官方針對 Mac OS和Linux的SDK也已經很久沒有更新了。

在GNU/Linux系統下,你需要安裝下面的這些東西的

freeglut3-dev
mesa-common-dev
libudev-dev
libxext-dev
libxinerama-dev
libxrandr-dev
libxxf86vm-dev

Mac OS如果安裝失敗,請使用Clang來,以及GCC的C標準庫(PS: 就是 Clang + GCC的混合體,它們之間就是各種複雜的關係。。):

export CXXFLAGS=-stdlib=libstdc++

export CC=/usr/bin/clang
export CXX=/usr/bin/clang++

(PS: 我使用的是Mac OS El Captian + Xcode 7.0. 2)clang版本如下:

Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.0.0
Thread model: posix

反正都是會報錯的:

ld: warning: object file (Release/obj.target/hmd/src/platform/mac/LibOVR/Src/Service/Service_NetClient.o) was built for newer OSX version (10.7) than being linked (10.5)
ld: warning: object file (Release/obj.target/hmd/src/platform/mac/LibOVR/Src/Tracking/Tracking_SensorStateReader.o) was built for newer OSX version (10.7) than being linked (10.5)
ld: warning: object file (Release/obj.target/hmd/src/platform/mac/LibOVR/Src/Util/Util_ImageWindow.o) was built for newer OSX version (10.7) than being linked (10.5)
ld: warning: object file (Release/obj.target/hmd/src/platform/mac/LibOVR/Src/Util/Util_Interface.o) was built for newer OSX version (10.7) than being linked (10.5)
ld: warning: object file (Release/obj.target/hmd/src/platform/mac/LibOVR/Src/Util/Util_LatencyTest2Reader.o) was built for newer OSX version (10.7) than being linked (10.5)
ld: warning: object file (Release/obj.target/hmd/src/platform/mac/LibOVR/Src/Util/Util_Render_Stereo.o) was built for newer OSX version (10.7) than being linked (10.5)
node-hmd@0.2.1 node_modules/node-hmd

不過,有最後一行就夠了。

Node.js Oculus Hello,World

現在,我們就可以寫一個Hello,World了,直接來官方的示例~~。

var hmd = require("node-hmd");

var manager = hmd.createManager("oculusrift");

manager.getDeviceInfo(function(err, deviceInfo) {
if(!err) {
console.log(deviceInfo);
}
else {
console.error("Unable to retrieve device information.");
}
});

manager.getDeviceOrientation(function(err, deviceOrientation) {
if(!err) {
console.log(deviceOrientation);
}
else {
console.error("Unable to retrieve device orientation.");
}
});

運行之前,記得先連上你的Oculus。會有類似於下面的結果:

{ CameraFrustumFarZInMeters: 2.5,
CameraFrustumHFovInRadians: 1.29154372215271,
CameraFrustumNearZInMeters: 0.4000000059604645,
CameraFrustumVFovInRadians: 0.942477822303772,
DefaultEyeFov:
[ { RightTan: 1.0923680067062378,
LeftTan: 1.0586576461791992,
DownTan: 1.3292863368988037,
UpTan: 1.3292863368988037 },
{ RightTan: 1.0586576461791992,
LeftTan: 1.0923680067062378,
DownTan: 1.3292863368988037,
UpTan: 1.3292863368988037 } ],
DisplayDeviceName: "",
DisplayId: 880804035,
DistortionCaps: 66027,
EyeRenderOrder: [ 1, 0 ],
...

接著,我們就可以實時返回這些數據了。

Node Oculus WebSocket

在網上看到three.js - Oculus Rift這個虛擬現實的電影,並且發現了它有一個WebSocket,然而是Java寫的,只能拿來當參考代碼。

現在我們就可以寫一個這樣的Web Services,用的仍然是Express + Node.js + WS。

var hmd = require("node-hmd"),
express = require("express"),
http = require("http").createServer(),
WebSocketServer = require("ws").Server,
path = require("path");

// Create HMD manager object
console.info("Attempting to load node-hmd driver: oculusrift");
var manager = hmd.createManager("oculusrift");
if (typeof(manager) === "undefined") {
console.error("Unable to load driver: oculusrift");
process.exit(1);
}
// Instantiate express server
var app = express();
app.set("port", process.env.PORT || 3000);

app.use(express.static(path.join(__dirname + "/", "public")));
app.set("views", path.join(__dirname + "/public/", "views"));
app.set("view engine", "jade");

app.get("/demo", function (req, res) {
"use strict";
res.render("demo", {
title: "Home"
});
});

// Attach socket.io listener to the server
var wss = new WebSocketServer({server: http});
var id = 1;

wss.on("open", function open() {
console.log("connected");
});

// On socket connection set up event emitters to automatically push the HMD orientation data
wss.on("connection", function (ws) {
function emitOrientation() {
id = id + 1;
var deviceQuat = manager.getDeviceQuatSync();
var devicePosition = manager.getDevicePositionSync();

var data = JSON.stringify({
id: id,
quat: deviceQuat,
position: devicePosition
});

ws.send(data, function (error) {
//it"s a bug of websocket, see in https://github.com/websockets/ws/issues/337
});
}

var orientation = setInterval(emitOrientation, 1000);

ws.on("message", function (data) {
clearInterval(orientation);
orientation = setInterval(emitOrientation, data);
});

ws.on("close", function () {
setTimeout(null, 500);
clearInterval(orientation);
console.log("disconnect");
});
});

// Launch express server
http.on("request", app);
http.listen(3000, function () {
console.log("Express server listening on port 3000");
});

總之,就是連上的時候不斷地發現設備的數據:

var data = JSON.stringify({
id: id,
quat: deviceQuat,
position: devicePosition
});

ws.send(data, function (error) {
//it"s a bug of websocket, see in https://github.com/websockets/ws/issues/337
});

上面有一行注釋是我之前一直遇到的一個坑,總之需要callback就是了。

Three.js + Oculus Effect + DK2 Control

在最後我們需要如下的畫面:

當然,如果你已經安裝了Web VR這一類的東西,你就不需要這樣的效果了。如標題所說,你已經知道要用Oculus Effect,它是一個Three.js的插件。

在之前的版本中,Three.js都提供了Oculus的Demo,當然只能用來看。並且交互的介面是HTTP,感覺很難玩~~。

Three.js DK2Controls

這時,我們就需要根據上面傳過來的四元數(Quaternions)與歐拉角(Euler angles)來作相應的處理。

{
"position": {
"x": 0.020077044144272804,
"y": -0.0040545957162976265,
"z": 0.16216422617435455
},
"quat": {
"w": 0.10187230259180069,
"x": -0.02359195239841938,
"y": -0.99427556991577148,
"z": -0.021934293210506439
}
}

歐拉角與四元數

(ps: 如果沒copy好,麻煩提出正確的說法,原諒我這個掛過高數的人。我只在高中的時候,看到這些資料。)

歐拉角是一組用於描述剛體姿態的角度,歐拉提出,剛體在三維歐氏空間中的任意朝向可以由繞三個軸的轉動複合生成。通常情況下,三個軸是相互正交的。

對應的三個角度又分別成為roll(橫滾角),pitch(俯仰角)和yaw(偏航角),就是上面的postion裡面的三個值。。

roll = (rotation about Z);

pitch = (rotation about (Roll ? Y));

yaw = (rotation about (Pitch ? Raw ? Z));」

— 引自《Oculus Rift In Action》

轉換成代碼。。

this.headPos.set(sensorData.position.x * 10 - 0.4, sensorData.position.y * 10 + 1.75, sensorData.position.z * 10 +10);

四元數是由愛爾蘭數學家威廉·盧雲·哈密頓在1843年發現的數學概念。

從明確地角度而言,四元數是複數的不可交換延伸。如把四元數的集合考慮成多維實數空間的話,四元數就代表著一個四維空間,相對於複數為二維空間。

反正就是用於描述三維空間的旋轉變換。

結合下代碼:

this.headPos.set(sensorData.position.x * 10 - 0.4, sensorData.position.y * 10 + 1.75, sensorData.position.z * 10 + 10);
this.headQuat.set(sensorData.quat.x, sensorData.quat.y, sensorData.quat.z, sensorData.quat.w);

this.camera.setRotationFromQuaternion(this.headQuat);
this.controller.setRotationFromMatrix(this.camera.matrix);

就是,我們需要設置camera和controller的旋轉。

這使我有足夠的理由相信Oculus就是一個手機 + 一個6軸運動處理組件的升級板——因為,我玩過MPU6050這樣的感測器,如圖。。。

Three.js DK2Controls

雖然下面的代碼不是我寫的,但是還是簡單地說一下。

/*
Copyright 2014 Lars Ivar Hatledal
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

THREE.DK2Controls = function (camera) {

this.camera = camera;
this.ws;
this.sensorData;
this.lastId = -1;

this.controller = new THREE.Object3D();

this.headPos = new THREE.Vector3();
this.headQuat = new THREE.Quaternion();

var that = this;
var ws = new WebSocket("ws://localhost:3000/");
ws.onopen = function () {
console.log("### Connected ####");
};

ws.onmessage = function (evt) {
var message = evt.data;
try {
that.sensorData = JSON.parse(message);
} catch (err) {
console.log(message);
}
};

ws.onclose = function () {
console.log("### Closed ####");
};

this.update = function () {

var sensorData = this.sensorData;
if (sensorData) {
var id = sensorData.id;
if (id &> this.lastId) {
this.headPos.set(sensorData.position.x * 10 - 0.4, sensorData.position.y * 10 + 1.75, sensorData.position.z * 10 + 10);
this.headQuat.set(sensorData.quat.x, sensorData.quat.y, sensorData.quat.z, sensorData.quat.w);

this.camera.setRotationFromQuaternion(this.headQuat);
this.controller.setRotationFromMatrix(this.camera.matrix);
}
this.lastId = id;
}

this.camera.position.addVectors(this.controller.position, this.headPos);
if (this.camera.position.y &< -10) { this.camera.position.y = -10; } if (ws) { if (ws.readyState === 1) { ws.send("get "); } } }; };

打開WebSocket的時候,不斷地獲取最新的感測器狀態,然後update。誰在調用update方法?Three.js

我們需要在我們的初始化代碼里初始化我們的control:

var oculusControl;

function init() {
...
oculusControl = new THREE.DK2Controls( camera );
...
}

並且不斷地調用update方法。

function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
oculusControl.update( clock.getDelta() );
THREE.AnimationHandler.update( clock.getDelta() * 100 );

camera.useQuaternion = true;
camera.matrixWorldNeedsUpdate = true;

effect.render(scene, camera);
}

最後,添加相應的KeyHandler就好了~~。

Three.js KeyHandler

KeyHandler對於習慣了Web開發的人來說就比較簡單了:

this.onKeyDown = function (event) {
switch (event.keyCode) {
case 87: //W
this.wasd.up = true;
break;
case 83: //S
this.wasd.down = true;
break;
case 68: //D
this.wasd.right = true;
break;
case 65: //A
this.wasd.left = true;
break;
}
};

this.onKeyUp = function (event) {
switch (event.keyCode) {
case 87: //W
this.wasd.up = false;
break;
case 83: //S
this.wasd.down = false;
break;
case 68: //D
this.wasd.right = false;
break;
case 65: //A
this.wasd.left = false;
break;
}
};

然後就是萬惡的if語句了:

if (this.wasd.up) {
this.controller.translateZ(-this.translationSpeed * delta);
}

if (this.wasd.down) {
this.controller.translateZ(this.translationSpeed * delta);
}

if (this.wasd.right) {
this.controller.translateX(this.translationSpeed * delta);
}

if (this.wasd.left) {
this.controller.translateX(-this.translationSpeed * delta);
}

this.camera.position.addVectors(this.controller.position, this.headPos);

if (this.camera.position.y &< -10) { this.camera.position.y = -10; }

快接上你的HMD試試吧~~

------------------------------------分割符-----------------------------------------------------------

qq群:544405366


謝邀。外出中,用手機大概說下。索尼那個不熟悉,說說OR吧,因為是用unity來開發的,所以unity你得會吧,那unity的腳本語言你也得會吧(個人建議c#),這樣,你就有了基本的開發能力。然後,你需要一個可操作的場景,這個一般由美工和建模師來完成,偷懶可以網上下,作死可以自己學3dmax,maya等比如我。。。學完這些就能完成個比較簡單的虛擬現實場景了。然後就是再深入了,上到。玩家體驗,下到物理模擬。。。各種天坑等你填(我受夠了T_T)


來扯會淡吧

雖然說現在OculusRift當紅,是個誰都知道,又和可穿戴設備聯繫在一塊(我老婆買個奮達電子的股票還說丫會漲因為是可穿戴設備。。。)所以大家自然的想成了一個高大上的東西。 其實開發起來令人驚訝的簡單。
這麼說,它根子就是把個顯示器套頭上而已,(要不然國內廠商怎麼一窩蜂過去山寨,技術不複雜的),硬體層面似乎沒太多困難,要說有主要是OculusRift用的是弧面屏幕,國內廠商往往就是給你個放大鏡,效果還是有區別。

真正有哏的可能倒是更多集中在硬體層面。

來說說我的開發故事。
我朋友某甲是個神奇的人,精熟各種哲學理論,雄辯驚人,初次見他,他用鮑德里亞的消費社會理論配上虛擬現實的概念解釋魔獸世界。。。 毀我三觀於一旦。
後來覺得盛大的零世界項目簡直太需要這個一個能在哲學層面扯淡的高人,推薦他前去面試,據說面試中藐視考官,考官問策劃理論他直接繞過軟肋大談禪機,把面試的策劃徹底逼瘋,於是未果。
(這種案例似乎在他的生涯裡面發生無數)

過了很多年之後,又再次相望與江湖,這哥們據說已經愛上了遊戲引擎,在家好好學習了一陣UDK決定重返上海灘,要做一番事業,聽聞我在各種奇葩項目上面頗有建樹,於是再邀我一聚,聊聊他此行的宏圖。

其時某甲從未聽聞過oculusrift,MYO ,Leaopmotion之類我們新媒體行業的騙錢利器,只是紅口白牙談了個願景,說能否像刀劍神域一樣,大家戴上個頭盔,拿起茶杯在個茶室喝茶,這樣身在曹營眼在漢,虛擬場景裡面或茫茫草原,或皚皚白雪,或酒池肉林,與手中茶有種種呼應,甚至可以和隔壁茶屋上的人的Avatar來個交談,人不相見,精神出軌,似乎頗為好玩。

我對他的想法頗有興趣,倒不覺得項目能夠盈利(或者就算某甲用扭曲現實立場弄來筆投資,要到兜里其實前路漫漫,犯不上我資深業內混子全情投入)不過對這個技術的可實現性還是興趣盎然,覺得可以完全free,給他弄個小demo出來,讓他去忽悠投資,我全身而退,盡了人事,賺了經驗,也不耗費我太多精力。

於是找朋友借了個Oculus,開始瞎折騰,主要是實現兩個場景,一個在一個虛擬空間裡面,一杯熱茶飄蕩,人跳入熱茶,隨後在一道如同時間隧道的荒誕場景裡面,各種生活雜物在空中如走馬燈在身邊呼嘯過(此處強調三維出畫感),隨後人物飛入一個車廂坐定,面前出一虛擬人物與之談人生談感情云云

腦洞大開啊,設計有飛機稿,這項目也足可打上一飛機

於是打開unity,下載oculusrift sdk導入,找了一堆美術素材,三四天業餘搞定

需要什麼技術呢,會個引擎導入插件就成,於是輕鬆的搞定
這個項目後來似乎朋友也沒忽悠到投資,但是因此愛上了unity,奮發了一年學習了一下,居然開了加公司做起增強現實的生意來,這是後話。

這是不是也側面反映了OculusRift的開發難度?

找不著工程了 哪天找到了放幾張截圖上來

ps: 騰訊開始採購奮達的頭戴設備。。 媽的提前漲了 說好行情呢 嗚嗚


OR 有三種實現方式,實拍,3D動畫,3D引擎。
可以根據自己比較擅長和熟悉的領域的去選擇。
比較簡單的適合個人的就是3D引擎這個方式了,用unity就好了。
進階過程中要仔細研究什麼情況會產生眩暈感,然後在製作和設計層面要規避開,同時也可以看些3D電影拍攝的知識,這些也是很好的借鑒。


用UE4吧,裝好驅動後,插上DK2,任何遊戲瞬間升級成VR遊戲。
不需要程序員也能完成遊戲邏輯,


這是Valve Software軟體和硬體工程師的招聘要求。

Virtual Reality - Engineers

At Valve we are pushing the boundaries
of virtual reality and related technologies. We are looking for versatile,
self-directed hardware and software engineers in many disciplines that can help
us achieve the next steps in VR. Join the Valve team pursuing hardware design,
software development, prototyping, testing, and production as we invent,
design, and deliver new experiences to over 100 million customers.

Experience in one or more of the
following areas:

·
User Interfaces

·
Human Computer Interaction

·
Controllers

·
Computer Vision (Tracking, Photogrammetry, Bundle
Adjustment)

·
Image-Based Rendering Light Field Rendering

·
Optics Computational Displays

·
Tracking (EKF, State Estimation, Inertial Navigation,
Control Theory)

·
3D Graphics: Shading, Rendering, Drivers

·
Engine Integration (Unity, Unreal)

·
Spatialized Audio

·
Human Perception Vision Science

·
FPGA / ASIC Development

·
Analog / Mixed Signal Circuit Design

·
Embedded Firmware

·
Video Compression

·
Wireless Technologies

Apply for this
position &>

Valve


以 Oculus Rift 為例,應用開發主要兩種途徑,一種是直接使用 SDK,一種是使用 UE4,Unity 這樣的遊戲引擎。

前者的話要求你掌握一種編程語言,然後使用對應該語言的 SDK,具體可以參照 Manning: Oculus Rift in Action。使用 SDK 可以擁有最大的靈活度,不過工作量也大,更要命的是,不同的設備應該會有不同的 SDK。而且 OR 只是虛擬現實的輸出設備,當你進一步考慮各種不同的輸入設備時,就會發現直接使用 SDK 是件工作量巨大的事情。

使用遊戲引擎的話則可以避免這個問題,因為引擎的一個責任就是對不同的 SDK 進行封裝,包括輸入與輸出。在 Unity 推出免費的 OR 支持前,UE4 是最好的選擇。除了遊戲引擎外,最好還能擅長一種建模軟體,可以試試 Blender。在建模軟體之外如果還有餘力的話,可以研究下圖像處理和音頻處理。


虛擬現實(VR)是當今全球最前沿的科學技術之一,谷歌,微軟、Facebook、蘋果、三星、索尼等知名科技企業將其視為座上賓。VR通過計算機虛擬出現實世界,在VR技術影響下,彷彿置身於另一個立體的真實世界。2016年,是VR技術突破性發展的元年,VR將與各行各業相互結合,產生龐大的崗位需求——VR開發工程師,而Unity已經成為VR內容開發的首選技術平台。


Unity是由Unity Technologies開發的一個全面整合的專業遊戲引擎。據悉,截至2015年底,Unity全球註冊用戶已經超過400萬,Unity編輯器月活躍數量達到40萬,Unity的PC插件安裝量達到2億。Unity在中國手游市場佔有率高達75%,在遊戲引擎市場高居全球第一。

Unity通用性較強,可以開發出基於各種平台的遊戲,包括手機遊戲(iPhone、Android、Windows Phone、黑莓)、PC(Windows、Mac、Linux)、網頁遊戲(基於各種主流瀏覽器)、遊戲機專用遊戲(Wii、Xbox360、XboxOne、PS3、PS4)。


智能硬體物聯網可穿戴/植入,感測器等高新科技專欄微納機電系統(MEMS/NEMS) - 知乎專欄
MEMS(微機械系統)如何實現眼動追蹤? - 微納機電系統(MEMS/NEMS) - 知乎專欄

揭開MEMS(微機械系統)的面紗 (0618更) - 微納機電系統(MEMS/NEMS) - 知乎專欄


推薦閱讀:

Oculus Rift 為什麼選擇先支持 Android,而不是 iOS 平台?

TAG:虛擬現實VR | OculusRift | PlayStationVR | HTCVive |