最近,我跳进了openGL。大多数事情都做得很好,但我一直用这个把头撞在墙上。
我正在尝试旋转/缩放2D图像。我正在努力解决这个问题,我应先旋转,然后进行缩放,或者相反。这两种方式都没有达到我想要的效果。
我制作了两个简短的视频,展示了它出了什么问题:
首先旋转,然后缩放 https://dl.dropboxusercontent.com/u/992980/rotate_then_scale.MOV
先缩放,然后旋转 https://dl.dropboxusercontent.com/u/992980/scale_then_rotate.MOV
左图像是方形,右图像是矩形。正如您所看到的,使用这两种方法,有些事情并不完全正确:)
黑色区域是openGL视口。当视口是方形时,一切都很好,当它是一个矩形时,事情开始出错:)对于我绘制的每个图像,我计算一个不同的X和Y标度,参考视口,我想我在做某事错了...... 请注意,我对openGL很新,我可能做了一些愚蠢的事情(我希望我是)。希望我能以这种方式清楚地解决我的问题。
提前感谢您提供任何帮助!
Corjan
绘制一张图片的代码:
void instrument_renderer_image_draw_raw(struct InstrumentRenderImage* image, struct InstrumentRendererCache* cache, GLuint program) {
// Load texture if not yet done
if (image->loaded == INSTRUMENT_RENDER_TEXTURE_UNLOADED) {
image->texture = instrument_renderer_texture_cache_get(image->imagePath);
if (image->texture == 0) {
image->loaded = INSTRUMENT_RENDER_TEXTURE_ERROR;
}
else {
image->loaded = INSTRUMENT_RENDER_TEXTURE_LOADED;
}
}
// Show image when texture has been correctly loaded into GPU memory
if (image->loaded == INSTRUMENT_RENDER_TEXTURE_LOADED) {
float instScaleX = (float)cache->instBounds.w / cache->instOrgBounds.w;
float instScaleY = (float)cache->instBounds.h / cache->instOrgBounds.h;
float scaleX = (float)image->w / (float)cache->instOrgBounds.w;
float scaleY = (float)image->h / (float)cache->instOrgBounds.h;
// Do internal calculations when dirty
if (image->base.dirty) {
mat4 matScale;
mat4 matRotate;
mat4 matModelView;
mat4 matProjection;
matrixRotateZ(image->angle, matRotate);
matrixScale(scaleX , scaleY * -1, 0, matScale);
matrixMultiply(matRotate, matScale, matModelView);
// Determine X and Y within this instrument's viewport
float offsetX = ((float)cache->instOrgBounds.w - (float)image->w) / 2 / (float)cache->instOrgBounds.w;
float offsetY = ((float)cache->instOrgBounds.h - (float)image->h) / 2 / (float)cache->instOrgBounds.h;
float translateX = ( ((float)image->x / (float)cache->instOrgBounds.w) - offsetX) * 2;
float translateY = ( ( ( (float)cache->instOrgBounds.h - (float)image->y - (float)image->h ) / (float)cache->instOrgBounds.h) - offsetY) * -2;
matrixTranslate(translateX, translateY*-1, -2.4,matModelView);
//matrixPerspective(45.0, 0.1, 100.0, (double)cache->instOrgBounds.w/(double)cache->instOrgBounds.h, matProjection);
matrixOrthographic(-1, 1, -1, 1, matProjection);
matrixMultiply(matProjection, matModelView, image->glMatrix);
image->base.dirty = 0;
}
glUseProgram(program);
glViewport(cache->instBounds.x * cache->masterScaleX,
cache->instBounds.y * cache->masterScaleY,
cache->instBounds.w * cache->masterScaleX,
cache->instBounds.w * cache->masterScaleX);
glUniformMatrix4fv(matrixUniform, 1, GL_FALSE, image->glMatrix);
// Load texture
glBindTexture(GL_TEXTURE_2D, image->texture);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
答案 0 :(得分:0)
您使用什么框架/库进行矩阵乘法?
首先需要的东西取决于你的矩阵表示(例如行与列主要和后期与预乘之比)。你使用的图书馆决定了这一点;固定功能OpenGL(glMultMatrix (...)
等。)是列主要和后乘法。大多数基于OpenGL的框架都遵循传统,尽管有一些例外,如OpenTK。传统的矩阵乘法按以下顺序进行:
1. Translation
2. Scaling
3. Rotation
但由于后乘乘列主要矩阵的性质(矩阵乘法是非交换的),操作有效地从底部到顶部发生。即使您在旋转之前进行平移乘法,旋转实际上也会应用于预平移坐标。
实际上,假设您的矩阵库遵循OpenGL约定,那么您正在反向执行矩阵乘法序列。