> Jeff Slutter wrote:
> 
> Hi,
>     I'm currently porting Descent 3 to Linux using Mesa as the OpenGL
> renderer.  Using the same source code as the Windows version except for the
> initialization and any other glx specific things I have gotten it all ported.
> However, there seems to be some issues with the perspective texture mapping.
> I'm not quite sure if this is on our side, Mesa or maybe even glx (I'm using
> the NVidia glx X-Server for my TNT and the one for Matrox for my g400), but
> remember that this is the same source code as the Window's version.  I've also
> talked to John Carmack at Id on how they do their texture mapping coordinates
> for Quake (since Mesa and Quake get along quite well).  Where we are different
> is that Carmack uses OpenGL for transformation and clipping, while we don't.  I
> have found a hack of sort which improves the texture mapping for D3, however,
> it still isn't fixed.
>     It would be a great help to me if I could get in contact with someone to
> maybe help work out these problems.  At the end of this email I have included
> the source code to how we calculate our texture coordinates.
> 

Jeff, 

It's easiest to talk about a specific example - like a small demonstration
program.  Run something up in glut which does your mapping to a single triangle,
which can optionally be positioned at a screen edge.

I'll include one written by Eero Pajarre, which might come close to what you're
doing.

One note about the current g200 driver - if you are using the CVS version or
recent snapshot you are dealing with development code which tends to ignore
aspects of the GL state it doesn't like, projective textures (ie texcoords
specified with glTexCoord4f) being one of them.

Keith
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>

#ifdef __WIN32
#include <windows.h>
#else
#define APIENTRY 
#endif

#ifndef NDEBUG
static void EC(void)
{
  GLenum e=glGetError();                             
  if (e){                                           
    fprintf(stderr,"%s %d error %d %s\n",          
            __FILE__,__LINE__,e,gluErrorString(e));
    abort();
  }         
}
#else
#define EC()
#endif



#ifndef M_PI
#define M_PI 3.1415926535
#endif



GLuint add_texture(int sx,int sy,unsigned char *d)
{
  GLuint tex;

  GLenum gluerr;

  glGenTextures(1,&tex);
  glBindTexture(GL_TEXTURE_2D,tex);


  glPixelStorei(GL_UNPACK_ALIGNMENT,1);
  if((gluerr=(GLenum)gluBuild2DMipmaps(GL_TEXTURE_2D, 3,sx, sy, GL_RGB,
                                       GL_UNSIGNED_BYTE, (GLvoid *)d))) {
    fprintf(stderr,"GLULib%s\n",gluErrorString(gluerr));
    exit(-1);
  }

  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
  glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
  return tex;
}

GLuint tex1;

static void inittextures(void)
{
  const int TS=16;
  unsigned char tex[16][16][3];
  int x,y;
  for(x=0;x<TS;x++)
    for(y=0;y<TS;y++){
      tex[x][y][0]=x*3*256/TS;
      tex[x][y][1]=(x*7+y*8)*256/TS;
      tex[x][y][2]=(y*3)*256/TS;
    }
  tex1=add_texture(TS,TS,(unsigned char *)tex);
}



int SCREEN_WIDTH=640;
int SCREEN_HEIGHT=480;
static int win=0;
static float alpha=0;
static float beta=0;
static int draw_poly=1;
static int do_cva=0;
static int do_tex4=0;

void my_keyboard_func ( unsigned char key, int x, int y )
{
  if (key == 'x')
    draw_poly = !draw_poly;
  if (key == 'c')
    do_cva= !do_cva;
  if (key == '4')
    do_tex4=!do_tex4;
  glutPostRedisplay();
}

void my_keyboard_up_func ( unsigned char key, int x, int y )
{
  if (key == 'q' ||key == 'Q' || key == 27)
    exit(0);
}
 
static int left_key=0;
static int right_key=0;
static int up_key=0;
static int down_key=0;
void my_special_func ( int special_key, int x, int y )
{
  if (special_key == GLUT_KEY_LEFT)
    left_key=1;
  else if (special_key == GLUT_KEY_RIGHT)
    right_key=1;
  else if (special_key == GLUT_KEY_UP)
    up_key=1;
  else if (special_key == GLUT_KEY_DOWN)
    down_key=1;
}

void my_special_up_func ( int special_key, int x, int y )
{
  if (special_key == GLUT_KEY_LEFT) 
    left_key=0;
  else if (special_key == GLUT_KEY_RIGHT)
    right_key=0;
  else if (special_key == GLUT_KEY_UP)
    up_key=0;
  else if (special_key == GLUT_KEY_DOWN)
    down_key=0;
}


void idle_func(void)
{
   if (left_key) {
      alpha += 0.02;
      glutPostRedisplay();
   }
   if (right_key) {
      alpha -=0.02;
      glutPostRedisplay();
   } 
   if (down_key) {
      beta -= 0.02;
      glutPostRedisplay();
   } 
   if (up_key) {
      beta += 0.02;
      glutPostRedisplay();
   }     
} 



static void reshape_t(int width, int height)
{
  if (width>800)
    width=800;
  if (height>600)
    height=600;
  SCREEN_WIDTH=width;
  SCREEN_HEIGHT=height;

  glViewport(0,0,(GLint)width,(GLint)height);
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(60.0,width/(float)height,0.2,30.0);

  glMatrixMode(GL_MODELVIEW);

}




#define SX 1
#define SY 1

struct {
  GLfloat vx,vy,vz;
  GLfloat tx,ty;
} verts[(SX+1)*(SY+1)];




GLuint ind[2*SX*SY*3];



static void redraw(void)
{
  glShadeModel(GL_SMOOTH);
  glEnable(GL_DEPTH_TEST);
  EC();
  glEnable(GL_CULL_FACE);
  glEnable(GL_TEXTURE_2D);
  glBindTexture(GL_TEXTURE_2D,tex1);
  glCullFace(GL_BACK);
  glFrontFace(GL_CCW);


  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(2*sin(alpha)*cos(beta),1+2*sin(beta),
            2*cos(alpha)*cos(beta),
            0,1,0,
            0,1,0);
  glColor4f(0.8,0.8,0.8,0.8);
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

  glClearColor(0.2,0.2,0.2,1.0);

  if (!draw_poly)
    glPolygonMode(GL_FRONT,GL_LINE);


  glBegin(GL_TRIANGLES);
  glTexCoord2f(1,0);
  glVertex3f(0.2,0.3,0.2);
  if (do_tex4)
    glTexCoord4f(0,10,0,10);
  else
    glTexCoord2f(0,1);
  glVertex3f(-0.2,0.1,-0.2);
  glTexCoord2f(0,0);
  glVertex3f(0.3,-0.2,0.2);
  glEnd();


  glEnableClientState(GL_VERTEX_ARRAY);
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);


  glVertexPointer(3, GL_FLOAT, sizeof(verts[0]), &verts[0].vx);
  glTexCoordPointer(2, GL_FLOAT, sizeof(verts[0]), &verts[0].tx);
  if (do_cva){
    glLockArraysEXT(0,(SX+1)*(SY+1));
    fprintf(stderr,"after lock\n");
  }

  
    
  glDrawElements(GL_TRIANGLES,SX*SY*3,
                 GL_UNSIGNED_INT,
                 ind);
  fprintf(stderr,"after DrawElements 1\n"); 

  if (do_cva){
    fprintf(stderr,"before unlock\n");
    glUnlockArraysEXT();
    fprintf(stderr,"after unlock\n");
  }

  glDisableClientState(GL_VERTEX_ARRAY);
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);

  EC();


  if (!draw_poly)
    glPolygonMode(GL_FRONT,GL_FILL);
  fprintf(stderr,"before SwapBuffers\n");
  glutSwapBuffers();
  fprintf(stderr,"after SwapBuffers\n");
}


int main(int ac,char **av)
{
  int i,x,y;
  for(i=0;i<(SX+1)*(SY+1);i++){
    y = i / (SX+1);
    x = i -y*(SX+1);
    verts[i].vx=x-SX/2;
    verts[i].vy=y;
    verts[i].vz=0;
    verts[i].tx=verts[i].vx/2;
    verts[i].ty=verts[i].vy/2;
  }
  for(i=0;i<SX*SY;i++){
    y=i/SX;
    x=i-y*SX;
#define P(dx,dy) ((x+(dx))+(y+(dy))*(SX+1))
    ind[i*6]=P(0,0);
    ind[i*6+1]=P(1,0);
    ind[i*6+2]=P(0,1);
    ind[i*6+3]=P(1,0);
    ind[i*6+4]=P(1,1);
    ind[i*6+5]=P(0,1);
#undef P
  }
  glutInitWindowPosition(0,0);
  glutInitWindowSize(SCREEN_WIDTH,SCREEN_HEIGHT);
  glutInit(&ac,av);
  glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);
  if(!(win=glutCreateWindow("T"))) {
    fprintf(stderr,"Error opening a window.\n");
    exit(-1);
  }

  EC();
  reshape_t(SCREEN_WIDTH,SCREEN_HEIGHT);
  inittextures(); 

  EC();
  glutDisplayFunc(redraw);
  glutReshapeFunc(reshape_t);
  glutIdleFunc(idle_func);
  glutKeyboardFunc ( my_keyboard_func ) ;
  glutKeyboardUpFunc ( my_keyboard_up_func ) ;
  glutSpecialFunc  ( my_special_func  ) ;
  glutSpecialUpFunc  ( my_special_up_func  ) ;


  
  glutMainLoop();
  

  return 0;
}

Reply via email to