四棱锥映射贴图-VR播放显示

主要基于开源代码:https://github.com/ValveSoftware/openvr/tree/master/samples/hellovr_opengl 

进行修改,开发工具:VS2015。

首先你得有四棱锥全景图,如下:xxx.png  xxx.jpg  分辨率必须是4的倍数 宽高相同

bool CMainApplication::SetupTexturemaps()
{// 初始化 读取图片
	rgbImg = imread("C:/.../xxx.jpg");
	if (rgbImg.cols != rgbImg.rows | rgbImg.rows % 4 != 0 | rgbImg.cols % 4 != 0) {
		cout << "分辨率有问题!" << endl;
		getchar();
		return false;
	}	
	glGenTextures(1, &m_iTexture);
	glBindTexture(GL_TEXTURE_2D, m_iTexture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rgbImg.cols, rgbImg.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, rgbImg.data);//贴图
	glGenerateMipmap(GL_TEXTURE_2D);
	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_MIPMAP_LINEAR);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	GLfloat fLargest;
	glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);
	glBindTexture(GL_TEXTURE_2D, 0);
	return (m_iTexture != 0);
}

 

 

然后修改void CMainApplication::AddCubeToScene( Matrix4 mat, std::vector &vertdata )函数,这个函数是绘制立方体,我们要就改成绘制正四棱锥,添加AddPyramidToScene()函数。

记得在class CMainApplication中添加声明:
void AddPyramidToScene( std::vector &vertdata);

void CMainApplication::AddPyramidToScene(std::vector &vertdata)
{ //绘制的三维图形和二维图片坐标绑定
  //x右边 y上面 z后面      u右 v下     triangles instead of quads
  //这里直接用AddCubeVertex()来添加三维坐标和二维坐标绑定 不要被函数名误导
	AddCubeVertex(0.f, 0.f, 3.16987f, 0.0f, 1.0f, vertdata);//O
	AddCubeVertex(-5.f, 0.f, -1.830127f, 0.0f, 0.5f, vertdata);//A
	AddCubeVertex(0.f, -5.f, -1.830127f, 0.5f, 1.0f, vertdata);//D
	AddCubeVertex(0.f, 0.f, 3.16987f, 1.0f, 1.0f, vertdata);//O
	AddCubeVertex(0.f, -5.f, -1.830127f, 0.5f, 1.0f, vertdata);//D
	AddCubeVertex(5.f, 0.f, -1.830127f, 1.0f, 0.5f, vertdata);//C
	AddCubeVertex(0.f, 0.f, 3.16987f, 1.0f, 0.0f, vertdata);//O
	AddCubeVertex(5.f, 0.f, -1.830127f, 1.0f, 0.5f, vertdata);//C
	AddCubeVertex(0.f, 5.f, -1.830127f, 0.5f, 0.0f, vertdata);//B
	AddCubeVertex(0.f, 0.f, 3.16987f, 0.0f, 0.0f, vertdata);//O
	AddCubeVertex(0.f, 5.f, -1.830127f, 0.5f, 0.0f, vertdata);//B
	AddCubeVertex(-5.f, 0.f, -1.830127f, 0.0f, 0.5f, vertdata);//A
	AddCubeVertex(0.f, 5.f, -1.830127f, 0.5f, 0.0f, vertdata);//B
	AddCubeVertex(-5.f, 0.f, -1.830127f, 0.0f, 0.5f, vertdata);//A
	AddCubeVertex(0.f, -5.f, -1.830127f, 0.5f, 1.0f, vertdata);//D
	AddCubeVertex(0.f, 5.f, -1.830127f, 0.5f, 0.0f, vertdata);//B
	AddCubeVertex(0.f, -5.f, -1.830127f, 0.5f, 1.0f, vertdata);//D
	AddCubeVertex(5.f, 0.f, -1.830127f, 1.0f, 0.5f, vertdata);//C
}
//这个是源文件里绘制立方体的函数
void CMainApplication::AddCubeToScene(Matrix4 mat, std::vector &vertdata)
{
	//x右边 y上面 z后面      u右 v下     triangles instead of quads
	// Matrix4 mat( outermat.data() );
	Vector4 A = mat * Vector4(0, 0, 0, 1);
	Vector4 B = mat * Vector4(1, 0, 0, 1);
	Vector4 C = mat * Vector4(1, 1, 0, 1);
	Vector4 D = mat * Vector4(0, 1, 0, 1);
	Vector4 E = mat * Vector4(0, 0, 1, 1);
	Vector4 F = mat * Vector4(1, 0, 1, 1);
	Vector4 G = mat * Vector4(1, 1, 1, 1);
	Vector4 H = mat * Vector4(0, 1, 1, 1);
	// 
	AddCubeVertex(E.x, E.y, E.z, 0, 1, vertdata); //Front
	AddCubeVertex(F.x, F.y, F.z, 1, 1, vertdata);
	AddCubeVertex(G.x, G.y, G.z, 1, 0, vertdata);
	AddCubeVertex(G.x, G.y, G.z, 1, 0, vertdata);
	AddCubeVertex(H.x, H.y, H.z, 0, 0, vertdata);
	AddCubeVertex(E.x, E.y, E.z, 0, 1, vertdata);

	AddCubeVertex(B.x, B.y, B.z, 0, 1, vertdata); //Back
	AddCubeVertex(A.x, A.y, A.z, 1, 1, vertdata);
	AddCubeVertex(D.x, D.y, D.z, 1, 0, vertdata);
	AddCubeVertex(D.x, D.y, D.z, 1, 0, vertdata);
	AddCubeVertex(C.x, C.y, C.z, 0, 0, vertdata);
	AddCubeVertex(B.x, B.y, B.z, 0, 1, vertdata);
	AddCubeVertex(H.x, H.y, H.z, 0, 1, vertdata); //Top
	AddCubeVertex(G.x, G.y, G.z, 1, 1, vertdata);
	AddCubeVertex(C.x, C.y, C.z, 1, 0, vertdata);
	AddCubeVertex(C.x, C.y, C.z, 1, 0, vertdata);
	AddCubeVertex(D.x, D.y, D.z, 0, 0, vertdata);
	AddCubeVertex(H.x, H.y, H.z, 0, 1, vertdata);
	AddCubeVertex(A.x, A.y, A.z, 0, 1, vertdata); //Bottom
	AddCubeVertex(B.x, B.y, B.z, 1, 1, vertdata);
	AddCubeVertex(F.x, F.y, F.z, 1, 0, vertdata);
	AddCubeVertex(F.x, F.y, F.z, 1, 0, vertdata);
	AddCubeVertex(E.x, E.y, E.z, 0, 0, vertdata);
	AddCubeVertex(A.x, A.y, A.z, 0, 1, vertdata);
	AddCubeVertex(A.x, A.y, A.z, 0, 1, vertdata); //Left
	AddCubeVertex(E.x, E.y, E.z, 1, 1, vertdata);
	AddCubeVertex(H.x, H.y, H.z, 1, 0, vertdata);
	AddCubeVertex(H.x, H.y, H.z, 1, 0, vertdata);
	AddCubeVertex(D.x, D.y, D.z, 0, 0, vertdata);
	AddCubeVertex(A.x, A.y, A.z, 0, 1, vertdata);
	AddCubeVertex(F.x, F.y, F.z, 0, 1, vertdata); //Right
	AddCubeVertex(B.x, B.y, B.z, 1, 1, vertdata);
	AddCubeVertex(C.x, C.y, C.z, 1, 0, vertdata);
	AddCubeVertex(C.x, C.y, C.z, 1, 0, vertdata);
	AddCubeVertex(G.x, G.y, G.z, 0, 0, vertdata);
	AddCubeVertex(F.x, F.y, F.z, 0, 1, vertdata);
}

三维图形(四棱锥)顶点坐标和二位图片(纹理)坐标对应关系如下:

m_iSceneVolumeInit(1)// 绘制贴图显示数量^3

里面数值假设为x,则最终会绘制x^3个四棱锥,我们只需要一个,所以初始化置1。

for (int z = 0; z< m_iSceneVolumeDepth; z++)
	{
		for (int y = 0; y< m_iSceneVolumeHeight; y++)
		{
			for (int x = 0; x< m_iSceneVolumeWidth; x++)
			{
				AddPyramidToScene(vertdataarray);//调用绘制函数 绘制的三维图形和二维图片贴图绑定
				//AddCubeToScene(mat, vertdataarray);
				mat = mat * Matrix4().translate(m_fScaleSpacing, 0, 0);
			}
			mat = mat * Matrix4().translate(-((float)m_iSceneVolumeWidth) * m_fScaleSpacing, m_fScaleSpacing, 0);
		}
		mat = mat * Matrix4().translate(0, -((float)m_iSceneVolumeHeight) * m_fScaleSpacing, m_fScaleSpacing);
	}

到这里基本就可以观看四棱锥贴图的VR全景图。

float eyex=0., eyey=0., eyez=0.;//视点
Matrix4  LookAt(1., 0., 0., -eyex,
		0., 1., 0., -eyey,
		0., 0., 1., -eyez,
		0., 0., 0., 1);
void CMainApplication::UpdateHMDMatrixPose()
{// 每帧更新坐标矩阵
	if (!m_pHMD)
		return;
	vr::VRCompositor()->WaitGetPoses(m_rTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, NULL, 0);
	m_iValidPoseCount = 0;
	m_strPoseClasses = "";
	for (int nDevice = 0; nDevice < vr::k_unMaxTrackedDeviceCount; ++nDevice)
	{
		if (m_rTrackedDevicePose[nDevice].bPoseIsValid)
		{
			m_iValidPoseCount++;
			m_rmat4DevicePose[nDevice] = ConvertSteamVRMatrixToMatrix4(m_rTrackedDevicePose[nDevice].mDeviceToAbsoluteTracking);
			if (m_rDevClassChar[nDevice] == 0)
			{
				switch (m_pHMD->GetTrackedDeviceClass(nDevice))
				{
				case vr::TrackedDeviceClass_Controller:        m_rDevClassChar[nDevice] = 'C'; break;
				case vr::TrackedDeviceClass_HMD:               m_rDevClassChar[nDevice] = 'H'; break;
				case vr::TrackedDeviceClass_Invalid:           m_rDevClassChar[nDevice] = 'I'; break;
				case vr::TrackedDeviceClass_GenericTracker:    m_rDevClassChar[nDevice] = 'G'; break;
				case vr::TrackedDeviceClass_TrackingReference: m_rDevClassChar[nDevice] = 'T'; break;
				default:                                       m_rDevClassChar[nDevice] = '?'; break;
				}
			}
			m_strPoseClasses += m_rDevClassChar[nDevice];
		}
	}
	if (m_rTrackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].bPoseIsValid)
	{
		m_mat4HMDPose = m_rmat4DevicePose[vr::k_unTrackedDeviceIndex_Hmd];
		m_mat4HMDPose.setColumn(3, Vector4(0, 0, 0, 1));//只旋转 没有近大远小效果(会导致图片扭曲严重) 去掉该行则恢复该效果 视图矩阵=旋转矩阵*平移矩阵  平移矩阵置E
		m_mat4HMDPose *= LookAt;//设置视点 默认视点在原点
		m_mat4HMDPose.invert();
	}
}

后续我会继续介绍一下我对源代码的一些理解。

后续要播放全景视频,只要在每帧渲染函数里添加贴图函数glTexImage2D即可。

 

你可能感兴趣的:(HTC)