EN

# 四、功能及接口说明

# 4.1 数据结构

struct qiyu_SdkVersion
{
	int versionProduct;
	int versionMajor;
	int versionMinor;
};
enum class qiyu_GraphicsApi
{
	GA_OpenGLES,
};
struct qiyu_ViewFrustum
{
	float left;					//left plane
	float right;				//right plane
	float top;					//top plane
	float bottom;				//bottom plane
	float near;				//near plane
	float far;					//far plane
	qiyu_Vector3    position;	//frustum position
	qiyu_Quaternion rotation;	//frustum rotation
};
enum qiyu_FoveationLevel
{
	FL_None = 0,						//Default value. Not use foveation.
	FL_Low,								//use foveationLow from qiyu_DeviceInfo.
	FL_Medium,							//use foveationMedium from qiyu_DeviceInfo.
	FL_High,							//use foveationHigh from qiyu_DeviceInfo.
	FL_COUNT_DeviceLevel,

	FL_Custom = FL_COUNT_DeviceLevel,	//use customFoveation.

	FL_COUNT
};
struct qiyu_FoveationParam
{
	qiyu_Vector2	gainRate;		//Foveation Gain Rate [1, ...]
	float			areaSize;		//Foveation Area Size [0, ...]
	float			minResolution;	//Foveation Minimum Resolution [1, 1/2, 1/4, ..., 1/16, 0]
};
struct qiyu_DeviceInfo
{
	qiyu_ViewFrustum 	frustumLeftEye;		//frustum information for left eye
	qiyu_ViewFrustum 	frustumRightEye;	//frustum information for right eye
	int32_t 			iEyeTargetWidth;		//eye buffer width
	int32_t 			iEyeTargetHeight;		//eye buffer height
    qiyu_FoveationParam	foveationLow;		//foveation low level values
	qiyu_FoveationParam	foveationMedium;	//foveation medium level values
	qiyu_FoveationParam	foveationHigh;		//foveation high level values

};
enum qiyu_EyeType
{
	EYE_Left = 0,		//left eye
	EYE_Right,		//right eye
	EYE_COUNT		//eye count
};
struct qiyu_ControllerData

{
    int 			isConnect;			//connection state
    int 			button;		//button state. refer to qiyu_ButtonType
    int 			buttonTouch;//touch state. refer to qiyu_ButtonType
    int 			batteryLevel;		//[0, 1] battery level
    float 			triggerForce;		//[0.0f, 1.0f] trigger force
    float 			gripForce;			//[0.0f, 1.0f] grip force
    int 			isShow;				//whether show controller
    qiyu_Vector2 	joyStickPos;		//[-1.0f, 1.0f] joystick position
    qiyu_Vector3 	position;			//controller position (meter)
    qiyu_Quaternion rotation;			//controller quaternion
    qiyu_Vector3 	velocity;			//linear velocity
    qiyu_Vector3 	acceleration;		//linear acceleration
    qiyu_Vector3 	angVelocity;		//angular velocity
    qiyu_Vector3 	angAcceleration;	//angular acceleration

};
enum qiyu_ButtonType
{
	BT_None			= 0,
	BT_Trigger		= 0x01,
	BT_Grip			= 0x02,
	BT_A_X			= 0x10,
	BT_B_Y			= 0x20,
	BT_Home_Menu	= 0x40,
	BT_JoyStick 	= 0x80
};
enum class qiyu_ControllerMask
{
	CM_Left = 0x01,		//left controller
	CM_Right  = 0x02,	//right controller
	CM_Both = 0x03		//left and right controllers
};
enum class qiyu_ControllerIndex

{
	CI_Left = 0,
	CI_Right,
	CI_COUNT
};
enum qiyu_PerfLevel
{
	PL_System 	= 0,		//default system level
	PL_Minimum 	= 1,		//min level
	PL_Medium 	= 2,		//medium level
	PL_Maximum 	= 3,		//max level
	PL_COUNT
};
struct qiyu_HeadPose
{
	qiyu_Quaternion	rotation;		//rotation quaternion
	qiyu_Vector3      	position;		//position
};
struct qiyu_HeadPoseState
{
    qiyu_HeadPose 	pose;				//head pose
    int32_t 	poseStatus;	            //Bit field (sxrTrackingMode) //indicating pose status
    uint64_t 	poseTimeStampNs;       //Time stamp in which the head pose //was generated (nanoseconds)
    uint64_t 	poseFetchTimeNs;       //Time stamp when this pose was //retrieved
    uint64_t 	expectedDisplayTimeNs;	//Expected time when this pose //should be on screen (nanoseconds)
};
enum class qiyu_TrackingOriginMode

{
    TM_Device,	//device mode. default mode.
    TM_Ground	//ground mode. 
};
enum qiyu_TextureType
{
	TT_Texture = 0,			//Standard texture
	TT_TextureArray,		//Standard texture array (Left eye is first layer, right eye is second layer)
	TT_Image,				//EGL Image texture
	TT_EquiRectTexture,		//Equirectangular texture
	TT_EquiRectImage,		//Equirectangular Image texture
	TT_CubemapTexture,		//Cubemap texture (Not supporting cubemap image)
};
struct qiyu_RenderLayer_ScreenPosUV
{
	float LowerLeftPos[4];		//0 = X-Position; 1 = Y-Position; 2 = Z-Position; 3 = W-Component
	float LowerRightPos[4];		//0 = X-Position; 1 = Y-Position; 2 = Z-Position; 3 = W-Component
	float UpperLeftPos[4];		//0 = X-Position; 1 = Y-Position; 2 = Z-Position; 3 = W-Component
	float UpperRightPos[4];		//0 = X-Position; 1 = Y-Position; 2 = Z-Position; 3 = W-Component
	float LowerUVs[4];			//[0,1] = Lower Left UV values; [2,3] = Lower Right UV values
	float UpperUVs[4];			//[0,1] = Upper Left UV values; [2,3] = Upper Right UV values
};
enum qiyu_RenderLayer_EyeMask
{
	RL_EyeMask_Left		= 0x00000001,
	RL_EyeMask_Right		= 0x00000002,
	RL_EyeMask_Both		= 0x00000003
};
struct qiyu_RenderLayer
{
	int32_t						imageHandle;	//Handle to the texture/image to be rendered
	qiyu_TextureType				imageType;	//Type of texture: Standard Texture or EGL Image
	qiyu_RenderLayer_ScreenPosUV	imageCoords;	//Layout of this layer on the screen
	qiyu_RenderLayer_EyeMask		eyeMask;		//Determines which eye[s] receive this render layer
};
static const int qiyu_RenderLayerMaxCount = 16;

struct qiyu_FrameParam
{
	int32_t minVsyncs; //Minimum number of vysnc events before displaying the frame (1=display refresh, 2=half refresh, etc...)
	qiyu_RenderLayer renderLayers[qiyu_RenderLayerMaxCount]; //Description of each render layer
	qiyu_HeadPoseState headPoseState; //Head pose state used to generate the frame
};

# 4.2 基础功能接口

@brief 函数说明
@param[in] 输入参数
@param[inout] 输出参数
@return 返回值
qiyu_SdkVersion qiyu_GetSdkVersion();
@brief 获取SDK版本。
@return qiyu_SdkVersion.
bool qiyu_Init(jobject clazz,  
               JavaVM* vm, 
               qiyu_GraphicsApi graphicsApi = qiyu_GraphicsApi::GA_OpenGLES,
               qiyu_TrackingOriginMode trackMode = qiyu_TrackingOriginMode::TM_Device,
               bool bLogVerbose = false);

- @brief //初始化QiyuNativeSDK。'void android_main(struct android_app* app)'是使用android_native_app_glue的native应用程序入口的主函数。它运行在其自身的线程,包含事件循环以接收输入事件和处理其他事件。
- @param[in] clazz //activity的对象句柄,即'android_app'运行于其内的'ANativeActivity'对象实例。例如'android_app->activity->clazz;'
- @param[in] vm // 'android_app'中'ANativeActivity'的进程的Java虚拟机的全局句柄。例如'android_app->activity->vm;'
- @param[in] graphicsApi // 指定图形API。请参阅'enum class qiyu_GraphicsApi'.
- @param[in] trackMode // 指定追踪模式为设备或地面。请参阅'enum class qiyu_TrackingOriginMode'.
- @param[in] bLogVerbose // 输出冗长的日志。注意如果打开会输出很多无用的信息,仅在需要时打开,例如需要调试程序错误时。
- @return //成功返回True; 失败返回False。
bool qiyu_Release();

- @brief //释放QiyuNativeSDK,通常在APP_CMD_DESTROY/APP_CMD_TERM_WINDOW等消息响应函数中调用。请参考Samples目录中的例子。
- @return //成功返回True; 失败返回False。
bool qiyu_StartVR(ANativeWindow* nativeWindow, qiyu_PerfLevel cpuPerfLevel, qiyu_PerfLevel gpuPerfLevel);

- @brief //启动VR服务,通常在主循环响应APP_CMD_START/APP_CMD_RESUME/APP_CMD_INIT_WINDOW等消息时调用。请参考Samples目录中的例子。
- @param[in] nativeWindow // 'android_app'可绘制的窗口表面。例如'android_app->window;'
- @param[in] cpuPerfLevel // CPU性能级别。
- @param[in] gpuPerfLevel //GPU性能级别。
- @return //成功返回True; 失败返回False。
bool qiyu_EndVR();

- @brief //结束VR服务,通常在APP_CMD_PAUSE等消息响应函数中调用。请参考Samples目录中的例子。
- @return //成功返回True; 失败返回False。
bool qiyu_StartEye(bool isMultiView, qiyu_Eye eyeType, qiyu_TextureType imageType);


- @brief //准备开始渲染,在帧缓冲区绑定之后以及实际渲染之前调用,通常在渲染状态设置之后调用。
- @param[in] isMultiView // True使用MultiView; False使用MultiPass
- @param[in] imageType // 指定纹理类型,请参考'enum qiyu_TextureType'。
- @param[in] eyeType // 指定要渲染到左眼/右眼的缓冲区。
- @return //成功返回True; 失败返回False。
bool bool qiyu_EndEye(bool isMultiView, qiyu_Eye eyeType, qiyu_TextureType imageType);

- @brief //结束渲染,在实际渲染之后以及帧缓冲区解绑和提交帧之前调用。
- @param[in] isMultiView // True使用MultiView; False使用MultiPass。
- @param[in] eyeType //指定要渲染到左眼/右眼的缓冲区。
- @param[in] imageType // 指定纹理类型,请参考'enum qiyu_TextureType'。
- @return //成功返回True; 失败返回False。
bool bool qiyu_SubmitFrame(const qiyu_FrameParam& frameParam);

- @brief //提交帧,默认提交到ATW(异步时间扭曲),在渲染之后调用。
- @param[in] frameParam // 参考qiyu_FrameParam。
- @return //成功返回True; 失败返回False。
qiyu_Update(float deltaTime);

- @brief //更新函数,通常在渲染函数之前或者其他非渲染线程调用。
- @param[in] deltaTime //(单位:秒)  两帧之间的时间增量。
qiyu_DeviceInfo qiyu_GetDeviceInfo();

- @brief //获取设备信息。
- @return qiyu_DeviceInfo // 请查阅'struct qiyu_DeviceInfo'.
bool qiyu_SetFoveation(qiyu_FoveationLevel foveatLevel, const qiyu_FoveationParam* customFoveatParam = nullptr);

- @brief 设置foveation数据。
- @param[in] foveatLevel // 请查阅'enum qiyu_FoveationLevel'。
- @param[in] customFoveatParam // 仅需要当(foveatLevel==FL_Custom)时传入。请查阅'struct qiyu_FoveationParam'。
- @return 成功返回true; 失败返回false。
bool qiyu_GetFoveation(qiyu_FoveationLevel& foveatLevel, qiyu_FoveationParam& foveatParam);

- @brief 获取foveation数据。
- @param[out] foveatLevel // 请查阅'enum qiyu_FoveationLevel'。
- @param[out] foveatParam // 请查阅'struct qiyu_FoveationParam'。
- @return 成功返回true; 失败返回false。
bool qiyu_GetViewMatrix(qiyu_Matrix4& outLeftEyeViewMatrix, qiyu_Matrix4& outRightEyeViewMatrix, float& outDistanceToGround, const qiyu_HeadPoseState& poseState, const qiyu_Quaternion& eyeRotationLeft, const qiyu_Quaternion& eyeRotationRight);

- @brief //获取最新的观察矩阵,在渲染和提交帧之前,即在qiyu_StartEye之前调用。内部使用最新更新的IPD。
- @param[inout] outLeftEyeViewMatrix // 返回左眼的观察矩阵。
- @param[inout] outRightEyeViewMatrix // 返回右眼的观察矩阵。
- @param[inout] outTrackingOffset//(单位:米) - 返回追踪偏移,它是考虑从设备到地面的高度和校准高度之后的值。从设备到地面的高度值为负数。注意应该使用该值去校正手柄等的位置。
- @param[in] poseState // 头部位姿数据,通常使用由qiyu_PredictHeadPose函数获得的值。
- @param[in] eyeRotationLeft // 左眼的旋转偏移。
- @param[in] eyeRotationRight // 右眼的旋转偏移。
- @return //成功返回True; 失败返回False。
float qiyu_PredictDisplayTime();

- @brief //获取显示当前帧的预测时间。
- @return //预测时间(单位:毫秒)。
qiyu_HeadPoseState qiyu_PredictHeadPose(float predicteDisplayTime);

- @brief //基于传入的预测显示时间预测头部位姿,通常在qiyu_GetViewMatrix函数之前调用。
- @param[in] predicteDisplayTime//(单位:毫秒) - 当前时刻到显示时刻的时间,用来预测显示时的头部位姿。
- @return qiyu_HeadPoseState // 预测的头部位姿。请参阅'struct qiyu_HeadPoseState'.
void qiyu_PostSetEyeBufferSize(int width, int height)
    
- @brief //请在每次设置EyeBuffer大小之后调用该接口,否则“奇遇性能分析工具”的数据会出错。注意!EyeBuffer完全由开发者管理,该接口只是为“奇遇性能分析工具”统计数据。
- @param[in] width // EyeBuffer宽度。
- @param[in] height // EyeBuffer高度。
qiyu_GraphicsApi qiyu_GetGraphicsApi();

- @brief //获取图形API,在qiyu_Init初始化时需要传入图形API,初始化之后可以通过qiyu_GetGraphicsApi函数获取。
- @return qiyu_GraphicsApi // 返回图形API。请参阅'enum class qiyu_GraphicsApi'.

# 4.3 附加功能

# 4.3.1 追踪模式

void qiyu_SetTrackingOriginMode(qiyu_TrackingOriginMode trackMode);

- @brief //设置追踪模式,在qiyu_Init初始化时需要传入追踪模式,初始化之后可以通过本函数改变。
- @param[in] trackMode // 指定追踪模式为设备或地面。请参阅'enum class qiyu_TrackingOriginMode'.
qiyu_TrackingOriginMode qiyu_GetTrackingOriginMode();

- @brief //获取追踪模式,在qiyu_Init初始化时需要传入追踪模式,初始化之后可以通过qiyu_SetTrackingOriginMode函数改变。
- @return qiyu_TrackingOriginMode // 返回追踪模式。请参阅'enum class qiyu_TrackingOriginMode'.

# 4.3.2 Eye Resolution Scale Factor

开发者在创建EyeBuffer时可以根据需要创建合适尺寸的RenderTexture,系数越小,画面清晰度越低,但帧率会提升,功耗降低;系数越大,画面清晰度提升,但是帧率会降低,功耗和内存会增加。

qiyu_DeviceInfo.iEyeTargetWidth * Scale

qiyu_DeviceInfo.iEyeTargetHeight * Scale

Scale推荐设为0.7,最大值不超过1。

可参考QiyuVR_NativeActivity样例中QYApp_Init函数里的qiyu_GetDeviceInfoQYApp_InitEyeBuffers部分。样例展示了两种不同大小的EyeBuffer的创建及通过摁下手柄X/Y键在这两种不同大小的EyeBuffer间动态切换。

# 4.4 奇遇手柄

bool qiyu_IsControllerInit();

- @brief //判断手柄模块是否初始化,在手柄相关接口函数调用之前可使用该函数检查确认。
- @return //已经初始化返回True; 尚未初始化返回False。
void qiyu_GetControllerData(qiyu_ControllerData* left, qiyu_ControllerData* right);

- @brief //获取最新的手柄数据。请参阅'struct qiyu_ControllerData'.
- @param[inout] left // 返回左手柄的数据。
- @param[inout] right // 返回右手柄的数据。
void qiyu_StartControllerVibration(qiyu_ControllerMask whichController, float amplitude, float duration);

- @brief //震动指定的手柄。
- @param[in] whichController // 要震动哪个手柄。请参阅'enum class qiyu_ControllerMask'.
- @param[in] amplitude // [0.0f, 1.0f] 振幅。
- @param[in] duration//(单位:秒) - [0.0f, 9999.0f] 震动时长。
void qiyu_StopControllerVibration(qiyu_ControllerMask whichController);

- @brief //停止震动指定的手柄。
- @param[in] whichController // 要震动哪个手柄。请参阅'enum class qiyu_ControllerMask'。

# 4.5 安全围栏

qiyu_GetBoundaryGeometry(void* points, int& pointsCount);

- @brief //获取虚拟围栏的几何体。
- @param[inout] points // 返回几何体的顶点数据。
- @param[inout] pointsCount // 返回几何体的顶点的数量。
- @return //成功返回True; 失败返回False。
qiyu_Vector3 qiyu_GetBoundaryDimensions();

- @brief //获取虚拟围栏的三个维度的大小。
- @return qiyu_Vector3 // x/y/z三个维度上的大小。
bool qiyu_IsBoundaryVisible();

- @brief //获取围栏是否可见。
- @return //可见返回True; 不可见返回False。
bool qiyu_IsBoundaryBelowHeadVisible();

- @brief //获取底部围栏是否可见。
- @return //可见返回True; 不可见返回False。

# 4.6 高级渲染

# 4.6.1 注视点渲染

使用方法,参见QiyuVR_NativeActivity例子中QYApp_testFoveation, InitFunction_Foveation, IsSupport_Foveation, FoveationLevel等相关代码。

如何使用:

  1. 检测是否支持注视点渲染扩展,如果支持,则需要加载注视点渲染相关函数。
  2. 在创建framebuffer时,设置 GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM。
  3. 使用 glTextureFoveationParametersQCOM 并设置其参数如 focalPoint, focalX, focalY, gainX, gainY, foveaArea.

参考链接:

【1】 https://www.khronos.org/registry/OpenGL/extensions/QCOM/QCOM_framebuffer_foveated.txt (opens new window)

【2】https://www.khronos.org/registry/OpenGL/extensions/QCOM/QCOM_texture_foveated.txt (opens new window)

【3】 https://www.khronos.org/registry/OpenGL/extensions/QCOM/QCOM_texture_foveated2.txt (opens new window)

【4】https://www.khronos.org/registry/OpenGL/extensions/QCOM/QCOM_texture_foveated_subsampled_layout.txt (opens new window)

# 4.6.2 MultiView

使用方法,参见QiyuVR_NativeActivity例子中QYApp_testMultiView函数,以‘_MultiView’为后缀的shader等相关代码。

请按以下步骤:

  1. 检测是否支持 multiview 扩展,如果支持,则需要加载 multiview相关函数。

  2. 创建纹理数组并绑定 framebuffer。

  3. 将观察矩阵(view matrix)传递给顶点着色器(vertex shader), 使用 gl_ViewID_OVR 索引访问观察矩阵, 这会计算两次并在一次draw call中渲染。

  4. 将参数 'isMultiView' 传入函数: qiyu_StartEye;qiyu_EndEye;qiyu_SubmitFrame.

# 4.7 平台接口

# 4.7.1 初始化

void qiyu_Platform_Init(const char* app_id, const char* app_secret, PCallback_Init callback);

- @brief 初始化平台相关接口。须在使用其他平台API前调用。
- @param[in] app_id // 应用程序ID.
- @param[in] app_secret // 开发者秘钥.
- @param[in] callback // 回调函数
  • app_id、app_secret:请您在登录奇遇开发者网站后,点击“管理 - 我的应用 - 新增”创建您的应用,系统将会给每个应用生成唯一app_id和app_secret。创建应用后,点击“API”查看App ID,App Secret信息

返回码:

监听码 原因
S0000 成功
S9000 系统异常
B1009 获取Token失败
B3021 应用ID或秘钥错误

# 4.7.2 奇遇账号

  • 是否登录
bool qiyu_Platform_IsAccountLogin();

- @brief //账户是否登录。
- @return //登录返回true;没有登录返回false。
  • 账号信息
void qiyu_Platform_GetQiyuAccountInfo(PCallback_GetAccountInfo callback);

- @brief //获取账户信息。
- @param[in] callback // 回调函数.

# 4.7.3 深度链接

void qiyu_Platform_LaunchOtherApp(const char* app_id, const char* key, const char* value);	

- @brief //打开其他应用。
- @param[in] app_id // 应用id。
- @param[in] key // 深度连接key。
- @param[in] value // 深度连接value。
void qiyu_Platform_GetDeepLink(PCallback_GetDeepLink callback);

- @brief //获取DeepLink。
- @param[in] callback // 回调函数.

# 4.7.4 数据存档

void qiyu_Prefs_Init();

- @brief //初始化用户自定义存档接口。会弹存储权限弹窗。需要申请external storage权限。须在使用其他存档API前调用。
void float qiyu_Prefs_GetFloat(const char* key, float defaultValue);

- @brief //返回存档文件中的key对应的float值,不存在返回defaultValue。
- @param[in] key // 键值。
- @param[in] defaultValue // 默认值。 
- @return //返回float值。
int qiyu_Prefs_GetInt(const char* key, int defaultValue);

- @brief //返回存档文件中的key对应的int值,不存在返回defaultValue。
- @param[in] key // 键值。
- @param[in] defaultValue // 默认值。 
- @return //返回int值。
const char* qiyu_Prefs_GetString(const char* key, const char* defaultValue);

- @brief //返回存档文件中的key对应的string值,不存在返回defaultValue。
- @param[in] key // 键值。
- @param[in] defaultValue // 默认值。 
- @return //返回string值。
bool qiyu_Prefs_HasKey(const char* key);

- @brief //存档文件中的key存在返回true,否则返回false。
- @param[in] key // 键值。
- @return //存在返回true,否则返回false。
void qiyu_Prefs_Save();

- @brief //将存档写入磁盘。所有修改后,需要调用Save。
void qiyu_Prefs_DeleteAll();

- @brief //删除所有存档,清空存档文件。
void qiyu_Prefs_DeleteKey(const char* key);

- @brief //删除存档文件中的key。
- @param[in] key // 键值。
void qiyu_Prefs_SetFloat(const char* key, float value);

- @brief //设置给定key的float值。
- @param[in] key // 键值。
- @param[in] value // 值。
void qiyu_Prefs_SetInt(const char* key, int value);

- @brief //设置给定key的int值。
- @param[in] key // 键值。
- @param[in] value // 值。
void qiyu_Prefs_SetString(const char* key, const char* value);

- @brief //设置给定key的string值。
- @param[in] key // 键值。
- @param[in] value // 值。