简体   繁体   English

OpenGL尝试使用纹理拉伸四边形但拉伸三角形?

[英]OpenGL trying to stretch quad with texture but stretches triangles?

I wrote code to reshape a quad that has been textured. 我编写了代码以重塑已纹理化的四边形。 When I stretch the quad the image does stretch how I would expect. 当我拉伸四边形时,图像确实会拉伸到我期望的样子。 I seems like when I stretch the image there are two different triangles that the image is stretch over vs. one single quad. 我似乎在拉伸图像时,有两个不同的三角形与一个四边形相对。 Pixels in the upper left stretch together but they don't effect the pixels in the lower right. 左上方的像素会延伸在一起,但不会影响右下方的像素。 And vice verse. 反之亦然。 Is there a setting I should set to stretch across the entire quad. 是否有一个设置应该延伸到整个四边形。

Here is an image: 这是一张图片:

在此处输入图片说明

To work my code you can used the arrow keys to move the corners. 要使用我的代码,您可以使用箭头键移动拐角。 Press the space bar to switch which corner is being controlled. 按空格键可切换要控制的角。

my code 我的密码

// textureMapping.cpp
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>


static GLuint texName;
int mode = 0;
double tol = 0.2f;

double xLoc = 0.0;
double yLoc = 0.0;

double xLocLL = 0.0;
double yLocLL = 0.0;

double xLocUL = 0.0;
double yLocUL = 0.0;

double xLocLR = 0.0;
double yLocLR = 0.0;

double xLocUR = 0.0;
double yLocUR = 0.0;

void init(void)
{    

   cv::Mat image = cv::imread("lena.tiff");
  //cv::Mat flipped;
  //cv::flip(image, flipped, 0);
  //image = flipped;
  if(image.empty()){
      std::cout << "image empty" << std::endl;
  }else{
      cv::flip(image, image, 0);
      glGenTextures(1, &texName);
      glBindTexture(GL_TEXTURE_2D, texName);

      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        // Set texture clamping method
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);


      glTexImage2D(GL_TEXTURE_2D,     // Type of texture
                     0,                 // Pyramid level (for mip-mapping) - 0 is the top level
                     GL_RGB,            // Internal colour format to convert to
                     image.cols,          // Image width  i.e. 640 for Kinect in standard mode
                     image.rows,          // Image height i.e. 480 for Kinect in standard mode
                     0,                 // Border width in pixels (can either be 1 or 0)
                     GL_BGR, // Input image format (i.e. GL_RGB, GL_RGBA, GL_BGR etc.)
                     GL_UNSIGNED_BYTE,  // Image data type
                     image.ptr());        // The actual image data itself

      glGenerateMipmap(GL_TEXTURE_2D);
  }
}

void display(void)
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   glEnable(GL_TEXTURE_2D);
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
   glBindTexture(GL_TEXTURE_2D, texName);
   glBegin(GL_QUADS);
   glTexCoord2f(0.0, 0.0); glVertex3f(-1.0+xLoc+xLocLL, -1.0+yLoc+yLocLL, 0.0);
   glTexCoord2f(0.0, 1.0); glVertex3f(-1.0+xLoc+xLocUL, 1.0+yLoc+yLocUL, 0.0);
   glTexCoord2f(1.0, 1.0); glVertex3f(1.0+xLoc+xLocUR, 1.0+yLoc+yLocUR, 0.0);
   glTexCoord2f(1.0, 0.0); glVertex3f(1.0+xLoc+xLocLR, -1.0+yLoc+yLocLR, 0.0);
   //glTexCoord2f(0.0, 0.0); glVertex3f(-1.0+xLoc, -1.0+yLoc, 0.0);
   //glTexCoord2f(0.0, 1.0); glVertex3f(-1.0+xLoc, 1.0+yLoc, 0.0);
   //glTexCoord2f(1.0, 1.0); glVertex3f(1.0+xLoc, 1.0+yLoc, 0.0);
   //glTexCoord2f(1.0, 0.0); glVertex3f(1.0+xLoc, -1.0+yLoc, 0.0);
   glEnd();
   glFlush();
   glDisable(GL_TEXTURE_2D);
   glutSwapBuffers();
}

void reshape(int w, int h)
{
   glViewport(0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 30.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   glTranslatef(0.0, 0.0, -3.6);
}

void keyboard (unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         break;
      case 32:
         mode += 1;
         if (mode == 5)
         {
            mode = 0;
         }
         break;
      default:
         break;
   }
}

void processSpecialKeys(int key, int x, int y) {

   switch(key) {
      case GLUT_KEY_LEFT:
         switch(mode)
         {
            case 0:
               xLoc -= tol;
               break;
            case 1:
               xLocLL -= tol;
               break;
            case 2:
               xLocUL -= tol;
               break;
            case 3:
               xLocUR -= tol;
               break;
            case 4:
               xLocLR -= tol;
               break;
         }
         break;
      case GLUT_KEY_RIGHT:
         switch(mode)
         {
            case 0:
               xLoc += tol;
               break;
            case 1:
               xLocLL += tol;
               break;
            case 2:
               xLocUL += tol;
               break;
            case 3:
               xLocUR += tol;
               break;
            case 4:
               xLocLR += tol;
               break;
         }
         break;
      case GLUT_KEY_DOWN:
         switch(mode)
         {
            case 0:
               yLoc -= tol;
               break;
            case 1:
               yLocLL -= tol;
               break;
            case 2:
               yLocUL -= tol;
               break;
            case 3:
               yLocUR -= tol;
               break;
            case 4:
               yLocLR -= tol;
               break;
         }
         break;
      case GLUT_KEY_UP:
         switch(mode)
         {
            case 0:
               yLoc += tol;
               break;
            case 1:
               yLocLL += tol;
               break;
            case 2:
               yLocUL += tol;
               break;
            case 3:
               yLocUR += tol;
               break;
            case 4:
               yLocLR += tol;
               break;
         }
         break;
   }
}


int main(int argc, char** argv)
{
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
   glutInitWindowSize(500, 500);
   glutInitWindowPosition(100, 100);
   glutCreateWindow(argv[0]);
   init();
   glutDisplayFunc(display);
   glutReshapeFunc(reshape);
   glutIdleFunc(display);
   glutKeyboardFunc(keyboard);
   glutSpecialFunc(processSpecialKeys);

   glutMainLoop();
   return 0; 
}

Makefile Makefile文件

textureMapping: textureMapping.cpp
    g++ -o textureMapping textureMapping.cpp -L/usr/local/lib -I/usr/local/include -lopencv_core -lopencv_highgui -framework GLUT -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo

No, that's correct behaviour. 不,这是正确的行为。 The GL specification (prior to 3.0) permits quads to be drawn as pairs of triangles, which is what you're seeing. GL规范(3.0之前的版本)允许将四边形绘制为成对的三角形,这就是您所看到的。 Quads were removed from the spec entirely in 3.0. 在3.0版中将四边形完全从规范中删除。

If you're expecting it to look like a quad with perspective then you need actually to supply 3d coordinates. 如果您希望它看起来像一个带有透视图的四边形,那么您实际上需要提供3d坐标。

If you're expecting OpenGL to guess what perspective transform would have been applied to get a rectangle to bend to the 2d shape you're pushing then you're out of look. 如果您期望OpenGL猜测要应用哪种透视变换来使矩形弯曲成要推动的2d形状,那么您就显得格格不入。 That's a highly application-specific feature. 这是一个高度特定于应用程序的功能。 You should look up homography. 您应该查找单应性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM