将SDL-Window的大小调整为从Wavefront OBJ文件生成的OpenGL对象

时间:2016-05-13 10:18:28

标签: c++ opengl sdl wavefront

我是OpenGL,SDL和OBJ文件的新手,现在正在与一个问题作斗争。

  1. 设置SDL-Window(我已经删除了基本的SDL-Init-stuff)

    sdl_window = SDL_CreateWindow( 
                               "Viewer", 
                               SDL_WINDOWPOS_UNDEFINED, 
                               SDL_WINDOWPOS_UNDEFINED, 
                               1024, 
                               768, 
                               SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE );
    if( sdl_window == NULL )
        printf("SDL_CreateWindow failed: %s\n", SDL_GetError());
    
    SDL_GLContext glContext = SDL_GL_CreateContext( sdl_window );
    if( glContext == NULL )
        printf("SDL_GL_CreateContext failed: %s\n", SDL_GetError());
    
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
    
  2. 启动OpenGL功能(其中" obj"是我的类,用于解析OBJ和加载纹理)

    int         my_object;
    objloader   obj;
    
    glClearColor( 0.5f, 0.5f, 0.5f, 1.0f );
    glViewport( 0, 0, 1024, 768 );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 45, 1024.0/768.0, 1.0, 500.0 );
    //glOrtho( 0, 512, 384, 0, -1, 1 );
    glMatrixMode( GL_MODELVIEW );
    glEnable( GL_DEPTH_TEST );
    
    my_object = obj.load( "D:\myfile.obj" );
    
    glEnable( GL_LIGHTING );
    glEnable( GL_LIGHT0 );
    float col[] = {1.0,1.0,1.0,1.0};
    glLightfv( GL_LIGHT0, GL_DIFFUSE, col );
    
  3. 简要介绍一下OBJ文件...(没有vn - 其中的法线)

    mtllib ./test.mtl
    usemtl Haufwerk
    v -0.388155 5.580893 2.490415
    v -0.336669 5.566026 2.507601
    v -0.408834 5.515674 2.533414
    v -0.403397 5.444500 2.540850
    v -0.482161 5.577362 2.447329
    .
    .
    .
    v -0.533898 5.328258 1.909646
    v -0.439773 5.344517 1.849366
    vt 0.710938 0.273924
    vt 0.711743 0.270957
    vt 0.712080 0.277021
    vt 0.713371 0.278851
    vt 0.711261 0.303822
    .
    .
    .
    vt 0.845899 0.687021
    vt 0.841930 0.687169
    f 5616/687 5617/688 4642/686
    f 5617/691 5618/692 4642/690
    f 5616/687 4642/686 5618/689
    f 5617/688 5616/687 5618/689
    f 12657/633 12659/634 13191/637
    .
    .
    .
    
  4. 纹理是BMP文件,分辨率为1024x1024

  5. OBJ纹理图像:

    enter image description here

    1. 运行显示循环

      while( running )
      {
          start = SDL_GetTicks();
      
          while( SDL_PollEvent(&event) )
          {
              switch(event.type)
              {
                  case SDL_QUIT:
                      running = false;
                      break;
              }
          }
      
          glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
          glLoadIdentity();
          float pos[] = {-1.0,1.0,-2.0,1.0};
          glLightfv( GL_LIGHT0, GL_POSITION, pos );
          //glScalef( 1.f, 1.f, 1.f );
          glTranslatef(0.0, -30.0,-20.0);
          //glTranslatef( 10.0, 10.0, -50.0 );
          //glTranslatef( 0.0, 1.0, -19.5 );
          glCallList( myobject ); //and display it
      
          SDL_GL_SwapWindow( sdl_window );
      
          if( 1000/30 > (SDL_GetTicks() - start) )
              SDL_Delay( 1000/30 - (SDL_GetTicks() - start) );
      }
      
    2. ...来到这个结果:

    3. 结果:SDL窗口中的OpenGL对象:

      enter image description here

      下图是将一个显示代码行更改为:

          glTranslatef( 0.0, 1.0, -19.5 );
      

      我的目标是'#34; fit"在" OpenGL的事情" (它叫做什么??模型?帧缓冲?对象?)进入SDL窗口的边界。或许"调整大小" SDL窗口到OpenGL对象。 为什么?因为在下一步中我会" m"导出"将整个SDL窗口转换为位图,该位图将用作GIS软件中的数字化背景,用于地理配准。

      我是否必须更改视图设置,或者是否有可能抓住"用于调整SDL主窗口的OpenGL对象的大小?

      例如,如果我将显示代码中的一行更改为:

          glTranslatef( 0.0, 1.0, -19.5 );
      

      "坐标是什么?#34;顶点" v"在OBJ文件中?哪个"测量单位"他们拥有?它是当地的coosys吗?

      什么是纹理化的OpenGL对象"像素大小" (因为纹理模板的像素大小是1024x1024)??

      我从在线教程中获取的许多代码行,但我不确定它们如何影响我的屏幕细节。我对所有改变观点等的可能性感到困惑。

      所以任何帮助都表示赞赏。这让我睡不好......

1 个答案:

答案 0 :(得分:1)

您可以这样做的一种方法是,找到对象尺寸(遍历所有像素并确定每个轴中的最小值和最大值),找到相对于相机视点的对象深度和视图平截头体尺寸那个深度。最后,您可以找到适用于您的对象的最佳比例,以便它覆盖整个屏幕。

但这很复杂。使用正交投影会更容易,然后玩#34;与您的对象的规模。您仍然可以找到上面提到的对象尺寸,以便直接执行此操作。 使用这些:

glOrtho( -512, 512, -384, 384, -16, 16 );

// Remove the translations you were applying to your object
glScalef( 100.0f, 100.0f, 1.0f );

这应该允许您使用正交投影查看对象。从这里你应该能够调整比例值,直到你得到你想要的。

  

你能解释一下" Z"值?

首先,我的错误。它不完全是Z值,而是深度值。

默认情况下,无论是使用正交投影还是透视投影,在OpenGL中指定查看卷时,"相机"将看向负Z轴的方向。您可以使用lookAt功能更改方向,但在您的示例中,您不会获得默认的查看方向。出于这个原因,您经常会看到 Z-Depth 被使用。

正交投影定义了立方体/棱镜观察体积,其效果是所有物体,无论距离观察者多远,都将以相同的比例出现。 glOrtho函数的最后两个参数是nearfar值,定义了查看卷的深度。在我使用的评论中提到:

glOrtho( -512, 512, -384, 384, -16, 16 )

默认情况下,由于摄像机在负Z方向上观察,以0为中心,因此我们可以看到体积内的物体的相对深度为[-16,16]。那就是:

近似值为|-16 * (0,0,-1)| = 16且远值为|16 * (0,0,-1)| = -16

Example ortho viewing volume

  

"坐标是什么?#34;顶点" v"在OBJ文件中?

它们可能位于对象坐标(对象空间)中,它们定义每个顶点相对于对象本身的位置,原点为0,0,0。所以是的,对象的局部坐标系。 将变换应用于对象(即平移)时,结果值将位于世界坐标(世界空间)中。

  

我是否必须更改视图设置,或者是否有可能抓住"用于调整SDL主窗口的OpenGL对象的大小?

由你来决定。但是,与对方相比,缩放对象以适应窗口可能更有意义。我向您展示了缩放对象的方法。

  

什么是纹理化的OpenGL对象"像素大小" (因为纹理模板的像素大小是1024x1024)??

当提到纹理像素时,我们称之为 texels 。但我不明白你在问什么。

  

(它叫什么......?Model?Framebuffer?Object?)

我猜你的意思是你用纹理渲染的3D物体/模型。 请参阅Default FramebufferFramebuffer以确定。