zoukankan      html  css  js  c++  java
  • 简易的“虚拟头盔”实现

    头盔原理很简单,大致就是使用两个透镜,缩短眼睛的焦距,将两个眼睛看到的东西合二为一从而产生双屏3D效果。

    于是开始设想:既然有了3D效果,为了达到更加沉浸的体验,为何不将头部的运动也映射到虚拟世界中去呢?抱着这个想法,我们做了如下尝试:

    把头部数据(如旋转角、俯仰角等等)用陀螺仪接收传回电脑,为了简单起见快速出效果,直接手机,然后在手机端写了个app,负责使用wifi发送陀螺仪数据到pc,pc接收到数据之后,我写了个dll,共享内存的,不断更新那一块内存,宿主程序使用的时候,只需要call那块数据即可,方法非常简单。

    安卓客户端我不懂,所以是我同学写的。我只说c++ dll的代码,为了方便起见我是用了一个简单sender来模拟陀螺仪发回的数据。

    //sender
    #include <iostream>
    #include <Windows.h>
    #include <tchar.h>
    #include <ctime>
    using namespace std;
    
    struct DataStruct
    {
        float x;
        float y;
        float z;
    };
    
    #define BUF_SIZE 1024
    TCHAR szName[]=TEXT("Global\MyFileMappingObject"); 
    
    int main()
    {
        HANDLE hMapFile;
        float* pBuf;
    
        hMapFile = CreateFileMapping(
            INVALID_HANDLE_VALUE,  
            NULL,                 
            PAGE_READWRITE,         
            0,                     
            BUF_SIZE,            
            szName);                
    
        if (hMapFile == NULL)
        {
            _tprintf(TEXT("Could not create file mapping object (%d).
    "),
                GetLastError());
            return 1;
        }
        pBuf = (float*) MapViewOfFile(hMapFile, 
            FILE_MAP_ALL_ACCESS, 
            0,
            0,
            BUF_SIZE);
    
        if (pBuf == NULL)
        {
            _tprintf(TEXT("Could not map view of file (%d).
    "),
                GetLastError());
    
            CloseHandle(hMapFile);
    
            return 1;
        }
        while(1)
        {
            float s[3] = {1.0f,33.2f,12.3f};
            size_t a = sizeof(s);
            srand(clock());
            *s = rand() / (double)(3.2);
            *(s+1) = rand() / (double)(3.2);
            *(s+2) = rand() / (double)(3.2);
            cout<<s[0]<<" "<<s[1]<<" "<<s[2]<<endl;
            memcpy((PVOID)pBuf, (void*)s, sizeof(s));
        }
    }

    接收dll代码

    #include <windows.h>
    #include <string.h>
    #include <string>
    #include <iostream>
    #include <tchar.h>
    #include "recevedate.h"
    using namespace std;
    
    
    
    #define BUF_SIZE 1024
    TCHAR szName[]=TEXT("Global\MyFileMappingObject"); 
    HANDLE hMapFile;
    float* pBuf;
    
    int dll_data_init()
    {
            hMapFile = CreateFileMapping(
            INVALID_HANDLE_VALUE,    // use paging file
            NULL,                    // default security
            PAGE_READWRITE,          // read/write access
            0,                       // maximum object size (high-order DWORD)
            BUF_SIZE,                // maximum object size (low-order DWORD)
            szName);                 // name of mapping object
    
        if (hMapFile == NULL)
        {
            _tprintf(TEXT("Could not create file mapping object (%d).
    "),
                GetLastError());
            return -1;
        }
        pBuf = (float*) MapViewOfFile(hMapFile,   // handle to map object
            FILE_MAP_ALL_ACCESS, // read/write permission
            0,
            0,
            BUF_SIZE);
    
        if (pBuf == NULL)
        {
            _tprintf(TEXT("Could not map view of file (%d).
    "),
                GetLastError());
    
            CloseHandle(hMapFile);
    
            return -1;
        }
        return 0;
    }
    
    float get_x()
    {
        return pBuf[0];
    }
    
    float get_y()
    {
        return pBuf[1];
    }
    
    float get_z()
    {
        return pBuf[2];
    }
    
    float get_dx()
    {
        return pBuf[3];
    }
    
    float get_dy()
    {
        return pBuf[4];
    }
    
    float get_dz()
    {
        return pBuf[5];
    }
    
    void dll_data_ter()
    {
        UnmapViewOfFile(pBuf);
        CloseHandle(hMapFile);
    }

    初始化调用int dll_data_init()函数,退出时调用void dll_data_ter(),中间直接获取指定的数据即可。

    using UnityEngine;
    using System.Collections;
    using System;
    using System.Runtime.InteropServices; 
    
    public class dll : MonoBehaviour {
        [DllImport("daterecive.dll")]
        public static extern int dll_data_init();
        [DllImport("daterecive.dll")]
        public static extern void dll_data_ter ();
        [DllImport("daterecive.dll")]
        public static extern float get_x ();
        [DllImport("daterecive.dll")]
        public static extern float get_y ();
        [DllImport("daterecive.dll")]
        public static extern float get_z ();
        // Use this for initialization
        void Start () {
            dll_data_init ();
        }
        
        // Update is called once per frame
        void Update () {
    
            //getdata ();
        }
    
    
    
        void OnApplicationQuit()
        {
            dll_data_ter ();
        }
    }

    初始化后这些函数都是可以调用的,修改一下摄像机代码或者其他代码即可。

    在unity中处理了一个场景,做了一下实验:

    左上角就是传回的数据,由于是模拟数据,所以不是很真实。

    有了这个dll,这个系统可以轻松的拓展到很多游戏引擎中去,我在UE4中也做了相似的尝试。

    至于显示,只要场景是双屏即可:

    最后,整个装置就成型了:

    比较简陋不要在意那些细节,看上去效果还是很不错的,但是不知道怎么展示……

  • 相关阅读:
    初始化生成linux sysfs(8)
    内存延迟监控系统组件
    数组代码First Missing Positive
    类文件Spring中空值的写法java教程
    状态键盘完美适应iOS中的键盘高度变化
    框架绑定JavaScript MVC框架PK:Angular、Backbone、CanJS与Ember
    域编码jquery的AJAX跨域请求及跨域请求的原理
    数据格式利用GSON接卸JSON数据
    网元查看一个无厘头的core dump问题定位
    类型应用oracle如何显示毫秒?
  • 原文地址:https://www.cnblogs.com/wubugui/p/4322651.html
Copyright © 2011-2022 走看看