- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个控制相机的相机类,主要功能:
void PNDCAMERA::renderMatrix()
{
float dttime=getElapsedSeconds();
GetCursorPos(&cmc.p_cursorPos);
ScreenToClient(hWnd, &cmc.p_cursorPos);
double d_horangle=((double)cmc.p_cursorPos.x-(double)cmc.p_origin.x)/(double)screenWidth*PI;
double d_verangle=((double)cmc.p_cursorPos.y-(double)cmc.p_origin.y)/(double)screenHeight*PI;
cmc.horizontalAngle=d_horangle+cmc.d_horangle_prev;
cmc.verticalAngle=d_verangle+cmc.d_verangle_prev;
if(cmc.verticalAngle>PI/2) cmc.verticalAngle=PI/2;
if(cmc.verticalAngle<-PI/2) cmc.verticalAngle=-PI/2;
changevAngle(cmc.verticalAngle);
changehAngle(cmc.horizontalAngle);
rightVector=glm::vec3(sin(horizontalAngle - PI/2.0f),0,cos(horizontalAngle - PI/2.0f));
directionVector=glm::vec3(cos(verticalAngle) * sin(horizontalAngle), sin(verticalAngle), cos(verticalAngle) * cos(horizontalAngle));
upVector=glm::vec3(glm::cross(rightVector,directionVector));
glm::normalize(upVector);
glm::normalize(directionVector);
glm::normalize(rightVector);
if(moveForw==true)
{
cameraPosition=cameraPosition+directionVector*(float)C_SPEED*dttime;
}
if(moveBack==true)
{
cameraPosition=cameraPosition-directionVector*(float)C_SPEED*dttime;
}
if(moveRight==true)
{
cameraPosition=cameraPosition+rightVector*(float)C_SPEED*dttime;
}
if(moveLeft==true)
{
cameraPosition=cameraPosition-rightVector*(float)C_SPEED*dttime;
}
glViewport(0,0,screenWidth,screenHeight);
glScissor(0,0,screenWidth,screenHeight);
projection_matrix=glm::perspective(60.0f, float(screenWidth) / float(screenHeight), 1.0f, 40000.0f);
view_matrix = glm::lookAt(
cameraPosition,
cameraPosition+directionVector,
upVector);
gShader->bindShader();
gShader->sendUniform4x4("model_matrix",glm::value_ptr(model_matrix));
gShader->sendUniform4x4("view_matrix",glm::value_ptr(view_matrix));
gShader->sendUniform4x4("projection_matrix",glm::value_ptr(projection_matrix));
gShader->sendUniform("camera_position",cameraPosition.x,cameraPosition.y,cameraPosition.z);
gShader->sendUniform("screen_size",(GLfloat)screenWidth,(GLfloat)screenHeight);
};
它运行流畅,我可以用鼠标控制 X 和 Y 方向的角度,但不能围绕 Z 轴(Y 是世界空间中的“向上”)。
在我的渲染方法中,我使用一个 VAO 调用来渲染地形网格。网格本身是以四边形为中心(highes lod),其他都是按 2 的幂缩放的 L 形网格。它总是在相机前重新定位,缩放到世界空间,并由高度图置换。
rcampos.x = round((camera_position.x)/(pow(2,6)*gridscale))*(pow(2,6)*gridscale);
rcampos.y = 0;
rcampos.z = round((camera_position.z)/(pow(2,6)*gridscale))*(pow(2,6)*gridscale);
vPos = vec3(uv.x,0,uv.y)*pow(2,LOD)*gridscale + rcampos;
vPos.y = texture(hmap,vPos.xz/horizontal_scale).r*vertical_scale;
问题:
相机从原点开始,位于 (0,0,0)
。当我将它移离该点时,它会导致沿 X 轴的旋转不连续。感觉鼠标光标与屏幕空间中的网格对齐,并且仅将网格点处的位置记录为光标移动。
当它变得非常明显时,我还记录了相机位置,它在 X 或 Z 方向上距离原点大约 1,000,000。我注意到这种“滞后”随距离(从原点)线性增加。
此时还有一点Z-fighting(或类似效果),即使我使用没有位移的单个平面,也没有平面可以重叠。 (我使用曲面 segmentation 着色器和渲染补丁。)补丁上出现黑点。可能是雾造成的:
float fc = (view_matrix*vec4(Pos,1)).z/(view_matrix*vec4(Pos,1)).w;
float fResult = exp(-pow(0.00005f*fc, 2.0));
fResult = clamp(fResult, 0.0, 1.0);
gl_FragColor = vec4(mix(vec4(0.0,0.0,0.0,0),vec4(n,1),fResult));
另一个奇怪的行为是 Z 轴的小旋转,这也随着距离的增加而增加,但我不使用这种旋转。
可变格式:
顶点是unsigned short
格式,索引是unsigned int
格式。cmc
结构是带有 double
变量的相机/光标结构。
PI
和C_SPEED
是#define
常量。
附加信息:
网格是用上面提到的 ushort
数组创建的,间距为 1。在着色器中我用一个常数缩放它,然后使用曲面 segmentation 来实现最佳性能和最大视距.顶点的最终位置在 segmentation 评估着色器中计算。
mat4 MVP = projection_matrix*view_matrix*model_matrix;
如您所见,我使用 glm 库将我的矩阵发送到着色器。
+问:
float (或任何其他格式)的长度如何导致这种“精度损失”,或任何导致问题的原因。 view_matrix
可能是造成这种情况的原因,但我仍然无法在运行时将其输出到屏幕上。
PS:我不知道这是否有帮助,但是“滞后开始位置”附近的 View 矩阵是
-0.49662 -0.49662 0.863129 0
0.00514956 0.994097 0.108373 0
-0.867953 0.0582648 -0.493217 0
1.62681e+006 16383.3 -290126 1
编辑
比较相机位置和 View 矩阵:
view matrix = 0.967928 0.967928 0.248814 0
-0.00387854 0.988207 0.153079 0
-0.251198 -0.149134 0.956378 0
-2.88212e+006 89517.1 -694945 1
position = 2.9657e+006, 6741.52, -46002
最佳答案
这是一篇很长的帖子,所以我可能无法回答所有问题。我认为这很可能是精度问题。让我们从相机旋转问题开始。我认为主要问题在这里
view_matrix = glm::lookAt(
cameraPosition,
cameraPosition+directionVector,
upVector);
正如您所说,position 是一个很大的数字,例如 2.9657e+006 - 看看 glm 在 glm::lookAt 中做了什么:
GLM_FUNC_QUALIFIER detail::tmat4x4<T> lookAt
(
detail::tvec3<T> const & eye,
detail::tvec3<T> const & center,
detail::tvec3<T> const & up
)
{
detail::tvec3<T> f = normalize(center - eye);
detail::tvec3<T> u = normalize(up);
detail::tvec3<T> s = normalize(cross(f, u));
u = cross(s, f);
在您的例子中,eye 和 center 是这些大(非常相似)的数字,然后 glm 将它们相减以计算 f。这很糟糕,因为如果你减去两个几乎相等的 float ,最重要的数字将被设置为零,这会留下微不足道的(最错误的)数字。并且您将其用于进一步的计算,这只会强调错误。检查这个link了解一些细节。
z-fighting 是类似的问题。 Z 缓冲区不是线性的,由于透视划分,它在相机附近具有最佳分辨率。 z 缓冲区范围是根据您的近距和远距裁剪平面值设置的。您总是希望 far 和 near 值之间的比率尽可能小(通常 far/near 不应大于 30000)。 openGL wiki 上对此有很好的解释。 , 我建议你读一下:)
回到相机问题——首先,我会考虑你是否真的需要这么大的场景。我不这么认为,但如果是的话,你可以尝试以不同的方式计算你的 View 矩阵,分别计算旋转和平移,这可能对你的情况有所帮助。我通常处理相机的方式:
glm::vec3 cameraPos;
glm::vec3 cameraRot;
glm::vec3 cameraPosLag;
glm::vec3 cameraRotLag;
int ox, oy;
const float inertia = 0.08f; //mouse inertia
const float rotateSpeed = 0.2f; //mouse rotate speed (sensitivity)
const float walkSpeed = 0.25f; //walking speed (wasd)
void updateCameraViewMatrix() {
//camera inertia
cameraPosLag += (cameraPos - cameraPosLag) * inertia;
cameraRotLag += (cameraRot - cameraRotLag) * inertia;
// view transform
g_CameraViewMatrix = glm::rotate(glm::mat4(1.0f), cameraRotLag[0], glm::vec3(1.0, 0.0, 0.0));
g_CameraViewMatrix = glm::rotate(g_CameraViewMatrix, cameraRotLag[1], glm::vec3(0.0, 1.0, 0.0));
g_CameraViewMatrix = glm::translate(g_CameraViewMatrix, cameraPosLag);
}
void mousePositionChanged(int x, int y) {
float dx, dy;
dx = (float) (x - ox);
dy = (float) (y - oy);
ox = x;
oy = y;
if (mouseRotationEnabled) {
cameraRot[0] += dy * rotateSpeed;
cameraRot[1] += dx * rotateSpeed;
}
}
void keyboardAction(int key, int action) {
switch (key) {
case 'S':// backwards
cameraPos[0] -= g_CameraViewMatrix[0][2] * walkSpeed;
cameraPos[1] -= g_CameraViewMatrix[1][2] * walkSpeed;
cameraPos[2] -= g_CameraViewMatrix[2][2] * walkSpeed;
break;
...
}
}
这样,位置就不会影响你的旋转。我应该补充一点,我从 NVIDIA CUDA 示例 v5.0(烟雾粒子)改编了这段代码,我真的很喜欢它:)
希望至少有一些帮助。
关于c++ - 精度问题 - 远离原点的观点 - OpenGL C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19987726/
我试图弄清楚如何获取所有可见窗口的框架。我尝试了以下代码,但它仅适用于应用程序本身,其他窗口报告 {0,0,0,0} NSArray *windowArray = [NSWindow wind
左矩形=新矩形(0,0,WIDTH/9,HEIGHT);在此代码中,如果我增加宽度,为什么它看起来会进一步延伸到 JFrame 的左侧?如果我减少它为什么它会向右延伸?这不是像坐标平原一样工作吗?高度
假设我有一个 AffineTransform (transform) 并调用它的一堆方法。假设我旋转并平移它。然后我用它转换图形对象 (g2d): g2d.transform(transform);
我认为当你对物体施加力时,它会施加到 body 的原点(可能是质心)。现在我正在尝试创建类似俄罗斯方 block 的 block ,并通过应用 LinearPulse 使它们跳跃,如下所示: body
我正在阅读 Big Nerd Ranch 指南第 4 版,但在处理 View 和 View 层次结构的章节中,我遇到了一些与 View 来源有关的问题。 我已经在我的 View Controller
我想把原点放在中心,所以我做了: SetViewportOrgEx(hdc,width/2,height/2,NULL); (如下面的代码所示) 现在,在实现双缓冲后它似乎无法正常工作。任何想法为什么
当我的 Sprite 旋转原点固定在窗口的左上角时,我遇到了这个问题(与 sprite.Draw 和 sprite.Draw2D 相同)无论哪种方式,如果我改变旋转中心它仍然在左上角。我需要 Spri
有人告诉我,您可以通过以下方式向与当前 Git 分支名称相匹配的远程分支推送和 pull : git push origin HEAD 或 git pull origin HEAD 它以前一直对我有用
我正在使用自定义 View 和 Canvas 在屏幕上绘制对象。 View 位于距屏幕原点的 Y 偏移处。我想平移 Canvas ,然后绘制一个对象。但是,当我使用 setmatrix 平移 Canv
尝试拖动组。为什么 origin 在这里不起作用?注意到当你第一次点击它时它是如何跳跃的吗? JSFIDDLE基于此:http://bl.ocks.org/mbostock/1557377 var d
我正在尝试使用以下立方体的透视视角: http://jsfiddle.net/TrySpace/JvFSQ/5/ 但是我没有按照我的预期去做,我想要改变实际的视角。所以当transformOrigin
我的 OpenShift Origin 安装似乎有问题。 当我获得路由器的端点时,我得到以下信息: oc get endpoints --namespace=default --selector=ro
这是怎么做到的?我正在寻找 iOS7/8 解决方案。 KeyboardWillShow 并不令人满意,因为我需要在键盘实际显示之前根据键盘高度调整 View 大小。 最佳答案 keyboardWill
我正在 iframe 上监听其内容何时发生变化。当它发生时,我想知道内容的当前来源是什么。 我无法访问该内容,因为它违反了相同的域策略,但我只要根据网址或主机知道它显示的内容就可以了。 我可以通过 j
我一直致力于使用 CSS3 创建动画条形图。它在钢筋的两侧运行良好,但钢筋的顶部和底部一直存在问题。 我一直在通过 jQuery 改变它们的 css“高度”属性来缩放边,但我意识到这不是最好的方法。我
Edit3:我的问题与我预期的功能完全不同。我让代码保留下来,也许这对某人有帮助 :)(并且不要忘记调试!)。 我试图找到直线与三角形相交的 vector 。 当前状态:随机交叉,即使鼠标不在地板上和
我需要在原始 View 的坐标中计算 UIView subview 的可见 CGRect。如果比例为 1,我可以正常工作,但如果其中一个 super View 或 View 本身被缩放(收缩),可见的
这个问题类似于以前回答的问题 Fast interpolation over 3D array ,但无法解决我的问题。 我有一个维度为(时间、高度、纬度、经度)的 4D 数组,标记为 y.shape=
我正在制作自定义贴纸包。这是一个 iMessage 扩展应用程序。我继承了 UICollectionView 而不是使用基本的 MSMessagesViewController。因此,只有当我在展开
我使用 CGWindowListCopyWindowInfo 获取所有窗口的列表。它根据屏幕的 左上角 原点为我提供每个窗口的坐标。 如果我使用 NSWindow 的 setFrame 方法,坐标基于
我是一名优秀的程序员,十分优秀!