上一次提到绘制了轮廓,接下来我们需要让其在特定触发之后相应。我们可以设置回调函数监测准心的位置。
本来想使用鼠标触发,但是在前几天的调试中,发现从窗口检测鼠标坐标并不能很好的与窗口内物体匹配。所以我先试试。
标志物交互
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
先释放一下鼠标
。。。
思来想去,还是用准心好了:)
当然这一步依旧,接着设置回调函数监视
glfwSetCrosshairCallback(window, Crosshair_callback);
去renderer.h中声明一下
void Crosshair_callback(GLFWwindow * window);
再renderer.cpp中定义(使用摄像机位置去判断准心是否在标志点之上 ,届时我们会禁用鼠标控制视角,限制在空间中自由移动的能力)
(不放在回填函数里也行哈,随着渲染循环,也可以实现相同的效果,而且更简便)
----------------------------------------------------------------------------------------------------------------------------
稍微有点乱,整理好了之后重来一遍
标志物交互2.0
声明一个数组,待会用它存放几个对应的摄像机位置
std::vector<glm::vec3> outlinePos;
添加一个绘制轮廓的条件
if (
(camera.m_Position.x <= (outlinePos[i].x + 0.2f) && camera.m_Position.x >= (outlinePos[i].x - 0.2f))
&&
(camera.m_Position.y <= (outlinePos[i].y + 0.2f) && camera.m_Position.y >= (outlinePos[i].y - 0.2f))
)
//格式调整了一下方便阅读,大概就是在一个正方形区域时满足条件
接下来print摄像机位置到控制台,记录下来
接下来使用该函数在渲染循环中,更改绘制轮廓的语句
//绘制outlining
GLCALL(glStencilMask(0x00)); //禁止模板写入
GLCALL(glStencilFunc(GL_NOTEQUAL, 1, 0xff)); //模板值不等于缓冲区中模板值时更新 通过测试
glDisable(GL_DEPTH_TEST); //选中的物体可以透过遮挡,不使用深度测试
outlineShader.Bind();
outlineShader.SetUniformMatrix4fv("u_Projection", projection.GetMatrixData());
outlineShader.SetUniformMatrix4fv("u_View", view.GetMatrixData());
for(size_t i = 0; i < outlinePos.size(); i++){
if ((camera.m_Position.x <= (outlinePos[i].x + 0.2f) && camera.m_Position.x >= (outlinePos[i].x - 0.2f)) && (camera.m_Position.y <= (outlinePos[i].y + 0.2f) && camera.m_Position.y >= (outlinePos[i].y - 0.2f)))
{
Matrix stencilModel("mat4");
stencilModel.Rotate(90.0f, glm::vec3(1.0f, 0.0f, 0.0f));
stencilModel.Translate(labels[i]);
stencilModel.Scale(glm::vec3(1.5f, 1.5f, 1.5f));
outlineShader.SetUniformMatrix4fv("u_Model", stencilModel.GetMatrixData());
renderer.DrawElements(cuboidVa, cuboidIb, outlineShader);
}
}
glEnable(GL_DEPTH_TEST); //恢复深度测试
GLCALL(glStencilMask(0xFF));
现在我看谁,谁就得给我高亮
标志物信息展示
首先考虑在此窗口中展示信息,如此一来,新建一个视口显然合适一点。
首先我们声明一个布尔变量mes(这个mes变量需要在渲染循环中,通过每一次渲染重复刷新),然后在上一次的轮廓渲染中添加一个储存状态的变量
bool mes = false;
//...
for(){
if ()
{
renderer.DrawElements(cuboidVa, cuboidIb, outlineShader);
mes = true; //添加
}
}
随后通过
if (mes) {
GLCALL(glDisable(GL_DEPTH_TEST));
GLCALL(glViewport(0, 0, SCR_WIDTH / 4, SCR_HEIGHT / 4));
quadShader.Bind();
texMes.Bind(0);
renderer.DrawArrays(quadVa, 6, quadShader);
}
来实现绘制轮廓的同时绘制这个小窗口
没看的时候
看的时候
方便起见呢,我将每一个标志点的信息通过截图的方式储存,届时绘制纹理即可。
更改
//绘制outlining
bool mes = false;
std::string message;
GLCALL(glStencilMask(0x00)); //禁止模板写入
GLCALL(glStencilFunc(GL_NOTEQUAL, 1, 0xff)); //模板值不等于缓冲区中模板值时更新 通过测试
glDisable(GL_DEPTH_TEST); //选中的物体可以透过遮挡,不使用深度测试
outlineShader.Bind();
outlineShader.SetUniformMatrix4fv("u_Projection", projection.GetMatrixData());
outlineShader.SetUniformMatrix4fv("u_View", view.GetMatrixData());
for(size_t i = 1; i < outlinePos.size() + 1; i++){
if ((camera.m_Position.x <= (outlinePos[i - 1].x + 0.2f) && camera.m_Position.x >= (outlinePos[i - 1].x - 0.2f)) && (camera.m_Position.y <= (outlinePos[i - 1].y + 0.2f) && camera.m_Position.y >= (outlinePos[i - 1].y - 0.2f)))
{
Matrix stencilModel("mat4");
stencilModel.Rotate(90.0f, glm::vec3(1.0f, 0.0f, 0.0f));
stencilModel.Translate(labels[i - 1]);
stencilModel.Scale(glm::vec3(1.5f, 1.5f, 1.5f));
outlineShader.SetUniformMatrix4fv("u_Model", stencilModel.GetMatrixData());
renderer.DrawElements(cuboidVa, cuboidIb, outlineShader);
mes = i;
message = "tex" + 'i';
}
}
glEnable(GL_DEPTH_TEST); //恢复深度测试
GLCALL(glStencilMask(0xFF));
//-----------------------------------------------------------------------------------------
if (mes) {
GLCALL(glDisable(GL_DEPTH_TEST));
GLCALL(glViewport(SCR_WIDTH / 3, SCR_WIDTH / 2.5, SCR_WIDTH / 2.5, SCR_HEIGHT / 2.5));
quadShader.Bind();
tex1.Bind(0);
renderer.DrawArrays(quadVa, 6, quadShader);
}
1.为了方便在if(mes){ }中控制不同的纹理,对应不同的情况。2.调整窗口方位。3.添加了一个变量message存储每一个绘制的物体的编号(从1到12,而不是0到11)
1.for(size_t i = 1; i < outlinePos.size() + 1; i++){
2.if ((camera.m_Position.x <= (outlinePos[i - 1].x + 0.2f) && camera.m_Position.x >= (outlinePos[i - 1].x - 0.2f)) && (camera.m_Position.y <= (outlinePos[i - 1].y + 0.2f) && camera.m_Position.y >= (outlinePos[i - 1].y - 0.2f)))
3.stencilModel.Translate(labels[i - 1]);
我在这三句代码中特定更改了i值,和条件中涉及i的地方。现在虽然只在if(mes){}中绑定了一个tex1,但是效果不错了
现在想的是通过message来实现tex1到tex12的控制,然后将字符转换为texture类型,通过“tex1.Bind(0);”实现对应纹理分配。
现在就是实现不同的纹理绘制了
最后一步
明天弄吧,睡了。明天弄一下不同的纹理控制,然后设置决赛信息交互。