添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  • WVR_ReleaseControllerModel
  • WVR_GetCtrlerModelAnimNodeData
  • WVR_ReleaseCtrlerModelAnimNodeData
  • 如何使用 Controller Model
  • How to Use Controller Animation
  • 手 (Hand)
  • WVR Hand Model
  • 追踪器(Tracker)
  • 眼 (Eye)
  • 唇 (Lip)
  • 通知装置资料(NotifyDeviceInfo)
  • 应用程序版本确认
  • 设备支持功能
  • WaveVR Time Warp Stabilization
  • Java APIs
  • Wave VR 应用程序声明
  • SDK 教学
  • Compatibility Guide
  • Wave Unity SDK
  • Wave Unreal SDK
  • Tutorial for MR Contents
  • 绘图效能优化指南
  • 如何使用 Controller Model

    在 VIVE Wave™ 中,我们可以取得当前连线的手柄模型。 WVR_CtrlerModel_t 结构用于将手柄模型回传给开发者。在这种结构中我们可以获得每个组件的顶点属性(位置,法线,贴图坐标),主体的贴图,触控板平面(模拟您在触控板上的触摸位置)和电量表示(告诉手把剩余电量)。

    WVR_VertexBuffer_t 结构用于记录网格的顶点属性。 buffer 是一个用于储存顶点属性,且有 size 长的阵列。 dimension 告诉我们一组顶点属性有多少个阵列元素。如果要初始化顶点属性,请编写以下源代码(以OpenGL为例):

    //Bind buffer.
    glGenBuffers(1, &vaBufID);
    glBindBuffer(GL_ARRAY_BUFFER, vaBufID);
    glBufferData(GL_ARRAY_BUFFER, (*mCachedData).compInfos.table[wvrCompID].vertices.buffer * sizeof(float), (*mCachedData).compInfos.table[wvrCompID].vertices.buffer, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    //...
    //Enable vertex attribute.
    glBindBuffer(GL_ARRAY_BUFFER, vaBufID);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, (*mCachedData).compInfos.table[wvrCompID].vertices.dimension, GL_FLOAT, GL_FALSE, sizeof(float) * (*mCachedData).compInfos.table[wvrCompID].vertices.dimension, 0);
    

    WVR_IndexBuffer_t 结构用于记录网格中每个面的顶点索引。 buffer 是一个用于储存这些索引,且有 size 长的阵列。 type 表示一个面有多少个索引。 在我们的手柄模型中,每个组件中的 type 通常等于3。如果要初始化这个阵列,请编写以下程式码(以OpenGL为例):

    //Bind buffer
    glGenBuffers(1, &idxBufID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, idxBufID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, (*mCachedData).compInfos.table[wvrCompID].indices.size * sizeof(uint32_t), (*mCachedData).compInfos.table[wvrCompID].indices.buffer, GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
    

    WVR_CtrlerTexBitmap_t 结构用于记录手把模型中的所有纹理。 此结构与NDK中的AndroidBitmap相同。 在我们的手柄模型中,纹理格式为RGBA8888。 如果要初始化贴图,请编写以下程式码(以OpenGL为例):

    //wvrBitmap is WVR_CtrlerTexBitmap_t.
    glGenTextures(1, &texID);
    if (wvrBitmap.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
        glBindTexture(GL_TEXTURE_2D, texID);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); //only one leve1.
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, wvrBitmap.width, wvrBitmap.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, wvrBitmap.bitmap);
    

    结构 WVR_CtrlerCompInfo_t 用于记录手把模型中组件的网格。 顶点属性 verticesnormalstexCoords 和索引阵列 indices 储存此组件的形状。 texIndex 告诉我们需要在贴图表中使用哪种贴图(通常等于0)。 localMat 是来自控制器原点的转换矩阵。 其格式遵循opengl(column-major)。 最终 name 是该组件的名称。且它的长度小于 63 byte。

    在手柄模型中,我们为每个组件定义名称。组件的所有名称如下:

    每个组件不是必需的。因此,我们可能无法在该手把中获得所有组件。

    请注意,我们将关于手把外观的组件中的网格(Battery,Emitter 和 touchpad_touch 除外)合并在組件__CM__Body上。因此,除非按下对应按钮,否则我们需要隐藏所有这些组件。

    结构 WVR_TouchPadPlane_t 用于告诉我们有关触控板平面的几何资讯。 uvwcenter 是触控板平面的原点和座标轴。 floatingDistance 用于调整触控板特效和触控板平面之间的距离。 radius 告诉我们触控板范围。 valid 是告诉我们触控板平面资讯是通过设定还是由模型计算得出的结果。如果valid为**false**,我们需要转换触碰的Y轴。范例源代码如下:

    WVR_Axis_t axis = WVR_GetInputAnalogAxis(mCtrlerType, WVR_InputId_Alias1_Touchpad);//get the touched pt on touchpad.
    //1. calculate touchpad touch pos.
    float invAxisY = 1.0f;
    if (touchpadPlane.valid == true) {
        invAxisY = -1.0f;
    Vector3 Tp;
    //Pout = Pc + Ax * R + Ay * R;
    Tp.x = axis.x * mRadius;
    Tp.y = mFloatingDistance;
    Tp.z = invAxisY * axis.y * mRadius;
    Matrix4 offsetMat;
    offsetMat[12] = Tp.x;
    offsetMat[13] = Tp.y;
    offsetMat[14] = Tp.z;
    offsetMat[15] = 1.0f;
    Matrix4 dotFinalMat = mTouchPadPlaneMat * offsetMat;//Use this as transformation matrix in ctrler space.
    

    WVR_BatteryLevelTable_t 结构用于记录有关控制器剩余电量显示。texTablemixLvTablemaxLvTable 用来告诉我们 当电量的百分比在相应间隔内时应使用哪张贴图 。我们可以每秒更新一次电池,并在绘制元件__CM__Battery 时使用对应的贴图。示例源代码如下:

    //Check battery is exist or not.
    if (mCompExistFlags[CtrlerComp_Battery] == false) {
        return;
    std::chrono::system_clock::time_point current = std::chrono::system_clock::now();
    float diffs = std::chrono::duration_cast<std::chrono::seconds>(
        current - mLastUpdateTime).count();
    if (diffs >= 1.0f) {
        mLastUpdateTime = current;
        float power = WVR_GetDeviceBatteryPercentage(mCtrlerType);
        for (uint32_t lv = 0; lv < mBatMinLevels.size(); ++lv) {
            uint32_t percentage = static_cast<uint32_t>(power * 100.0f);
            if (percentage >= mBatMinLevels[lv] && percentage <= mBatMaxLevels[lv]) {
                mBatteryLevel = lv;//Indicate target interval.
                break;
    

    介绍完手柄模型的所有结构后,绘制控制器的步骤可分为三个部分。第一步是 异步加载控制器模型 。此API的局限性在于我们无法在 缴交画面的线程(或会卡住缴交画面的线程) 使用 WVR_GetCurrentControllerModelWVR_GetCurrentControllerEmitter

    第二步是 初始化载入模型至显示卡 。我们需要初始化手柄模型每个组件的顶点属性和贴图。

    最后,我们需要在开始时 绘制手把模型的__CM__Body 和 __CM__Battery(如果存在)隐藏按钮组件 。如果按下了某些按钮,我们可以绘制该按钮并在组件上添加一些效果。

    如果要查看更多详细资讯,请参考 VIVE Wave™ 中的示例 wvr_hellovr 的类别 Controller。