GOOGLE VR SDK開發VR遊戲,VR播放器之一
最近一年來,VR虛擬現實和AR增強現實技術的宣傳甚囂塵上。其實VR,AR技術很早就有了,一直沒有流行開來,不可否認價格是影響技術推廣的最大壁壘。谷歌對VR最大的貢獻是提供了廉價的谷歌眼鏡,按照GOOGLE提供的圖紙,使用兩個放大鏡和一個披薩盒就能輕鬆DIY出自己的VR眼鏡,同一時期谷歌推出來開源的VR SDK,使得開發者可以輕鬆構建VR遊戲和VR播放器,使得幾乎所有對這一切感興趣的公司可以輕鬆的低成本的在技術上佈局VR產業鏈。很多VR眼鏡已經降到了幾十塊錢,毫無疑問,谷歌又藉著廉價和開源改變了我們的世界。
研究谷歌的SDK,需要具備一定的OPENGL知識,要不理解這一切十分困難。VR的原理十分簡單,人能夠感受的立體或者3D的世界全依賴人的雙眼,人的雙眼看到的東西是不一樣,存在一個視角差,看一個立體的物體,左右眼能同時看到物體中間的部分,不過左眼能看到比右眼更多一點的左邊部分,右眼能看到比左眼更多一點右邊部分,大腦對兩隻眼鏡看到的東西分析處理合成來感受這個世界的,一些3D畫可以恰當的利於光線和顏色組合達到視覺欺騙也是這個原理。如果對OPENGL熟悉的話,應該很容易知道3D建模中,Camera的位置不同,能顯示出來的物件角度是不一樣的,特別是使用透視效果時,人的兩眼就相當於3D世界裡攝像頭,兩個攝像頭看到的東西和一個是不同的。一般來說,獨眼的殘疾人如果不動的話,看到的世界是平面的,不過他們可以通過擺頭或者移動身體來從不同的角度觀察世界,從而在大腦裡合成立體的世界。所以VR的原理就是把一張圖片或者視訊分解兩個,分別提供給左右眼看,從而達到欺騙眼睛的效果,最終達到虛擬現實的效果。
谷歌VR SDK使用十分簡單,一般來說最好下載最新的google VR sdk,VR SDK包括unity版本和java版本,兩個版本功能差不多,一個用於unity平臺,一個用於android平臺,一個用於遊戲開發,一個用於應用開發,當然這不是絕對,有不少應用也是使用unity開發,也有不少遊戲使用java開發,選擇上感覺可以看自己使用習慣。java版本包括兩個包,一個cardboard.jar提借VR視覺支援,一個audio.jar提供VR聲音支援。
CardboardActivity是VRSDK的主類,要使開發的視窗支援VR,視窗需要派生於這個類。可以根據需要呼叫CardBoardView,支援各種呼叫,完整程式碼如下,不過完成後除了看到一個按鈕,其他都是黑鼕鼕的,因為Renderer我們沒有填充內容,是個空的glsurface,熟悉opgengl的,可以完善這個類,後面會新增一個立方體用於測試眼鏡
public class TestActivity extends CardboardActivity{ /* @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.activity_main); RajawaliCardboardView cv = (RajawaliCardboardView) findViewById(R.id.view2);//new CardboardView(this); //cv.setRestoreGLStateEnabled(false); //cv.setRenderer(rd); this.setCardboardView(cv); RajawaliCardboardRenderer renderer = new RajawaliCardboardRenderer(this){ @Override protected void initScene() { getCurrentScene().addChild(createSphereWithTexture(new Texture("photo", R.drawable.homepage))); getCurrentCamera().setPosition(Vector3.ZERO); getCurrentCamera().setFieldOfView(75); } @Override public void onNewFrame(HeadTransform headTransform) { super.onNewFrame(headTransform); } @Override protected void onRender(long ellapsedRealtime, double deltaTime) { super.onRender(ellapsedRealtime, deltaTime); } @Override public void onDrawEye(Eye eye) { super.onDrawEye(eye); } @Override public void onFinishFrame(Viewport viewport) { super.onFinishFrame(viewport); } @Override public void onSurfaceChanged(int width, int height) { super.onSurfaceChanged(width, height); } @Override public void onSurfaceCreated(EGLConfig config) { super.onSurfaceCreated(config); } @Override public void onRendererShutdown() { super.onRendererShutdown(); } @Override public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) { super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixelOffset, yPixelOffset); } @Override public void onTouchEvent(MotionEvent event) { super.onTouchEvent(event); } }; cv.setRenderer(renderer); cv.setSurfaceRenderer(renderer); } */ /* @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); super.onCreate(savedInstanceState); LinearLayout ln = new LinearLayout(this); ln.setBackgroundColor(Color.RED); CardboardView cbView = new CardboardView(this); cbView.setBackgroundColor(Color.BLUE); cbView.setVRModeEnabled(true); //cbView.setAlpha(0); cbView.setAlignmentMarkerEnabled(true); //cbView.setRenderer(new VrRenderer(this)); VrRenderer renderer = new VrRenderer(this); cbView.setRenderer(renderer); cbView.setPreserveEGLContextOnPause(true); setContentView(cbView); cbView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onCardboardTrigger(); } }); //mHideButtonsThread.start(); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); CardboardView cardboardView = (CardboardView) findViewById(R.id.view2); cardboardView.setRenderer(rd); setCardboardView(cardboardView); vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); imageLeft = (ImageView) findViewById(R.id.image_left); imageRight = (ImageView) findViewById(R.id.image_right); progressLeft = (ProgressBar) findViewById(R.id.progress_left); progressRight = (ProgressBar) findViewById(R.id.progress_right); statusLeft = (TextView) findViewById(R.id.status_text_left); statusRight = (TextView) findViewById(R.id.status_text_right); fadeInAnim = new AlphaAnimation(0.0f, 1.0f); fadeInAnim.setDuration(500); setProgress(true); setStatus(true, getString(R.string.status_finding_files)); // kick off our task to find all MPOs, which will in turn kick off showing the first one. new MpoFindTask().execute((Void) null); } */ private Renderer rd = new Renderer(){ @Override public void onDrawFrame(HeadTransform headTransform, Eye eye, Eye eye1) { } @Override public void onFinishFrame(Viewport viewport) { } @Override public void onSurfaceChanged(int i, int i1) { } @Override public void onSurfaceCreated(EGLConfig eglConfig) { } @Override public void onRendererShutdown() { } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); CardboardView mSurfaceView = new CardboardView(this); addContentView(mSurfaceView, new ActionBar.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT)); mSurfaceView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar | View.SYSTEM_UI_FLAG_IMMERSIVE); mSurfaceView.setRenderer(rd); mSurfaceView.setVRModeEnabled(true); //mSurfaceView.addChildrenForAccessibility(); setCardboardView(mSurfaceView); } }
參考:http://www.programcreek.com/java-api-examples/index.php?api=com.google.vrtoolkit.cardboard.CardboardView