The diffrence in OGL on Linux and win

I converted the mdl(half-life) file format to linux and made it alot easyer to use. I was just at a friends house who had win xp with MS VC++ 6.0. I was board so I ported my code to win, all I had to do was include windows.h and it ran :-D. In all the tutorials that I saw and displayed threw wine they always displayed better then mine. When I ran my code on win it displayed better then the code on linux. Half-life is only on win. I was wondering why mdl’s display better on win?

Here is a comparision a screen shot from Linux and win

Thanks
Nuke

[This message has been edited by nukem (edited 02-03-2003).]

Originally posted by nukem:
[b]I converted the mdl(half-life) file format to linux and made it alot easyer to use. I was just at a friends house who had win xp with MS VC++ 6.0. I was board so I ported my code to win, all I had to do was include windows.h and it ran :-D. In all the tutorials that I saw and displayed threw wine they always displayed better then mine. When I ran my code on win it displayed better then the code on linux. Half-life is only on win. I was wondering why mdl’s display better on win?

Here is a comparision a screen shot from Linux and win

Thanks
Nuke

[This message has been edited by nukem (edited 02-02-2003).][/b]

There are always small differences between platforms, and during a port these differences pop up. Most likely the bigest difference in your case is the compiler. Do pointers get set to null by default? etc.

It looks like you have come across one or a few of these porting problems.

I don’t understand exactly what is being ported here.It sounds like you’ve taken a half life model viewer, that runs under Windows, and ported it to Linux. Then back to windows.

If this is what you are doing, then you need to complete the port to Linux, finding all the porting problems and fixing them – this is your job as a porter

ya thats true. The weird part is that the skeleton draws perfect. Im not sure were the error is and theres about 1500 lines of code for this thing :\ Im thinking its in reading or displaying the uv stuff or the texture.

I can’t think of any reason why it would be different (without seeing code), but please… don’t use TGAs or BMPs, these formats aren’t meant to be used on the web.

Use PNG instead: good quality, good compression rate, good file size.

richardv: thanks for the tip I put a new version of the image in png form. I thought there should be no problem to I guess ill have to go threw the code line by line agien to check for runtime errors.

I also put up the source code if any one wants to take a look.

When you say skeleton you mean wireframe right?Any chance that some tris have incorrect winding order and get culled?Try disabling GL_CULL_FACE.Although I’m not sure why that should vary across ports.

zen: skeleton does mean wireframe. I dont think anything is incorrect since its the same exact code on both OS’s. I did try disableing GL_CULL_FACE but it looked the same. I was board so I tryed enabling it and it helped quite a bit. Take a look at this screenshot

Thanks for all your help so far!
Nuke

Do you know your Z-buffer precision? If you use a 16 BPP mode under Linux, you are likely to get only 16 bits for your Z buffer. If you use 32 BPP you usually get 24 bits for your Z buffer (is this the case under Windows?).

Your Linux screenshot seem to be suffering from poor Z buffer resolution. The fact that face culling helps is another indication.

You may also try changing the near & far Z planes. Try to make sure that Zfar/Znear < 100 (e.g. Znear=1.0, Zfar=50.0 or Znear=10.0, Zfar=500.0), and see if it helps.

And if that still doesn’t make biths shots look the same you could still use glPolygonOffset although I don’t think that should be necessary.
btw I think moving znear as far away from zero as possible is better for z precision.

Originally posted by zen:
btw I think moving znear as far away from zero as possible is better for z precision.

…that is what I meant with “Zfar/Znear < 100”. By moving Znear further away the quotient Zfar/Znear decreases, and it’s basically that quotient (together with the number of bits in your Z buffer) that decides your Z buffer precision (in terms of world coordinates).

Zfar/Znear small => better precision
Zfar/Znear large => worse precision

Im not sure that Im understanding how to do this, I do understand the concept though.

Here is my display funtion.

void DrawPoints()
{
int i;
int j;
Mesh* mesh;
BYTE* vertbone;
BYTE* normbone;
vect3* studioverts;
vect3* studionorms;
Texture* text;
float* av;
float* lv;
float lv_tmp;
short* skinref;

vertbone = ((BYTE*)header + model->vertinfoindex);
normbone = ((BYTE*)header + model->norminfoindex);
text = (Texture*)((BYTE*)texture + texture->textureindex);

mesh = (Mesh*)((BYTE*)header + model->meshindex);

studioverts = (vect3*)((BYTE*)header + model->vertindex);
studionorms = (vect3*)((BYTE*)header + model->normindex);

skinref = (short*)((BYTE*)texture + texture->skinindex);

if(skinnum != 0 && skinnum < texture->numskinfamilies)
{
  skinref += (skinnum * texture->numskinref);
}

for(i=0;i<model->numverts;i++)
{
  VectorTransform(studioverts[i], bonetransform[vertbone[i]], formverts[i]);
}

lv = (float*)lightvalues;

for(j=0;j<model->nummesh;j++)
{
  int flags;
  flags = text[skinref[mesh[j].skinref]].flags;

  for(i=0;i<mesh[j].numnorms;i++,lv+=3,studionorms++,normbone++)
  {
    Lighting(&lv_tmp, *normbone, flags, (float*)studionorms);

    if(flags & 0x0002)
    {
      Chrome(chrome[(float(*)[3])lv - lightvalues], *normbone, (float*)studionorms);
    }

    lv[0] = lv_tmp * lightcolor[0];
    lv[1] = lv_tmp * lightcolor[1];
    lv[2] = lv_tmp * lightcolor[2];
  }
}

glCullFace(GL_FRONT);

for(j=0;j<model->nummesh;j++)
{
  float s;
  float t;
  short* tricmds;

  mesh = (Mesh*)((BYTE*)header + model->meshindex) + j;
  tricmds = (short*)((BYTE*)header + mesh->triindex);

  s = 1.0 / (float)text[skinref[mesh->skinref]].width;
  t = 1.0 / (float)text[skinref[mesh->skinref]].height;

  glBindTexture(GL_TEXTURE_2D, text[skinref[mesh->skinref]].index);

  if(text[skinref[mesh->skinref]].flags & 0x0002)
  {
    while(i = *(tricmds++))
    {
      if(i < 0)
      {
        glBegin(GL_TRIANGLE_FAN);
        i = -i;
      }else{
        glBegin(GL_TRIANGLE_STRIP);
      }

      for(;i>0;i--,tricmds+=4)
      {
        glTexCoord2f(chrome[tricmds[1]][0] * s, chrome[tricmds[1]][1] * t);

        lv = lightvalues[tricmds[1]];
        glColor4f(lv[0], lv[1], lv[2], 1.0);

        av = formverts[tricmds[0]];
        glVertex3f(av[0], av[1], av[2]);
      }

      glEnd();
    }
  }else{

    while(i = *(tricmds++))
    {
      if(i < 0)
      {
        glBegin(GL_TRIANGLE_FAN);
        i = -i;
      }else{
        glBegin(GL_TRIANGLE_STRIP);
      }

      for(;i>0;i--,tricmds+=4)
      {
        glTexCoord2f(tricmds[2] * s, tricmds[3] * t);

        lv = lightvalues[tricmds[1]];
        glColor4f(lv[0], lv[1], lv[2], 1.0);

        av = formverts[tricmds[0]];

        glVertex3f(av[0], av[1], av[2]);
      }

      glEnd();
    }
  }
}

}

How could I determin Zfar and Znear? According to marcus(from what I got) zfar/znear should be less than 100, is that true?

I am thinking your talking about when I draw the coords with glVertex3f(av[0], av[1], av[2]) I should make av[2] less than 100 correct?

Please help me with this all the z axis stuff ive learned on my own

Thanks

Nuke

I just ran my program outputting the z axis that is being sent to glVertex3f(av[0], av[1], av[2]) av[2] was never greater then 100 infact it was always less then 80.

Now im really confused :\

please help!!!

thanks,

Nuke

You decide the near and far Z clipping planes (distances) when you set up your projection matrix, usually by calling gluPerspective() or glFrustum().

Check the MAN page for gluPerspective here: http://hem.passagen.se/opengl/man/glu/perspective.html

Hope this helps.

To me, it seems that the problem is not with the OpenGL stuff. It looks like the use of opengl by this view is pretty straight forward – textured polygons (triangles) and some lighting. Most likely no fancy blending modes or anything else. This leads me to believe that you should not focus your attention on the OpenGL code, but on things like how the arrarys are being defined and traversed. It looks like some polygons are being skipped somehow.

OpenGL is a very nice, well-put-together cross-platform API, and for the relatively simple use here there should be very little difference on the different platforms.

Jamie

It’s not a matter of different platforms, more like different drivers.Implementations can vary pretty much even on the same platform.But even this seems not to be the case here.The output is not simply different on linux as nukem says it’s wrong.
To me it seems that marcus will prove right after all.

amendol: I thought that at first as well and I went threw all my code and made sure it was all set up right, and it is.

zen: I ran the win port of my program threw winex recently and it looked the same as on win so I dont think the platform/driver is the problem.

marcus256: I think you maybe have the answer but for some reason Im screwing up with it. my gluPerspective was set to gluPerspective(50, 1, 0.1, 10); as you know zfar/znear = 1000 so I tryed your two examples at the top but both didnt work. I tryed a number of diffrent numbers all keeping in mind that zfar/znear <= 100 but it would make the model disappear. I tryed changing the aspect to a greater number but that did nothing. Then I played with the scalef stuff it was set to 0.01 if i raised that to over .5 I saw a little bit once I got up to 1.0 I saw a bit more. After .5 it seems to disappear.

Please help!!!

Thanks,
Nuke

[This message has been edited by nukem (edited 02-05-2003).]

You really need to figure out what you have in view. Your model occupies some portion of space, depending on:

  1. The size of the model (+/- X, +/- Y, +/- Z)
  2. The scaling of the model
  3. The location of the model

My suggestion is that, if you want to do a general model viewer (where the model can be any size), you should figure out the limits of the model (find out the min/max of X, Y and Z). Then use this information to confine the model to some predefined space (e.g. +/- 1.0 in all directions) using glScale & glTranslate (make sure that you glEnable(GL_NORMALIZE) when you use glScale and verices with normals, or lighting will not work).

Now! When you KNOW where your model is in space, and where your camera is, you also know exactly what your near and far clipping planes should be set to.

Example:

  1. Confine model to a box with the corners (-1,-1,-1) and (1,1,1)
  2. Place camera in (0,-5,0), looking at (0,0,0)

The distance from the camera to the closest possible model vertex is 4 units, and the distance from the camera to the most distant model vertex is 6 units. There you have your near and far Z clipping planes! In this case, Zfar/Znear = 6/4 = 1.5, which is much less than 100.

Note: The figure 100 is not a hard limit or something, just a guideline that I use myself that usually gives a decent Z buffer precision.

Here is some pseudo-code (I think it’s correct) for the method I mentioned in the previous post:

/* Find min and max of model in all directions */
minx = maxx = vertex[0].x;
miny = maxy = vertex[0].y;
minz = maxz = vertex[0].z;

for K in all vertices
minx = min( minx, vertex[K].x );
maxx = max( maxx, vertex[K].x );
miny = min( miny, vertex[K].y );
maxy = max( maxy, vertex[K].y );
minz = min( minz, vertex[K].z );
maxz = max( maxz, vertex[K].z );
end

/* Calculate model center */
centerx = (maxx+minx) / 2;
centery = (maxy+miny) / 2;
centerz = (maxz+minz) / 2;

/* Calculate scaling (the new max size is 2 units, or +/- 1 unit) */
scalex = 2 / (maxx-minx);
scaley = 2 / (maxy-miny);
scalez = 2 / (maxz-minz);
scale = min( scalex, scaley, scalez );

/* Apply model transformation */
glScalef( scale, scale, scale );
glTranslatef( -centerx, -centery, -centerz );

/* Draw model */

If you quickly want to see if this is going to help you can try znear=10,zfar=100 and glTranslatef your model 10 unit away in the z axis.This willmake it visible and you can see if you get a better result.Something along the lines of what marcus suggests is still a good idea of course.

marcus256: I tryed your code it draws really big I think it has something to do with the min in you code you use 3 parimaters but it only takes 2.

void Resize(float* scale, float* x, float* y, float* z)
{
float* av;
float minx;
float maxx;
float miny;
float maxy;
float minz;
float maxz;
float centerx;
float centery;
float centerz;
float scalex;
float scaley;
float scalez;
int i;

for(int a=0;i<header->numbodyparts;a++)
{
  SetupModel(a);

  for(int j=0;j<model->nummesh;j++)
  {
    //set up the vars to get the info
    Mesh* mesh = (Mesh*)((BYTE*)header + model->meshindex) + j;
    short* tricmds = (short*)((BYTE*)header + mesh->triindex);

    //start going threw the model
    while(i = *(tricmds++))
    {
      av = formverts[tricmds[0]];
      minx = maxx = av[0];
      miny = maxy = av[1];
      minz = maxz = av[2];

      //go threw each vertex
      for(;i>0;i--,tricmds+=4)
      {
        minx = min(minx, av[0]);
        maxx = max(maxx, av[0]);
        miny = min(miny, av[1]);
        maxy = max(maxy, av[1]);
        minz = min(minz, av[2]);
        maxz = max(maxz, av[2]);
      }
    }
  }
}

//get the center
centerx = (maxx + minx) / 2;
centery = (maxy + miny) / 2;
centerz = (maxz + minz) / 2;

//get the scale
scalex = 2 / (maxx - minx);
scaley = 2 / (maxy - miny);
scalez = 2 / (maxz - minz);

//set up the scale var
scale = new float;

//get the min of all of them
float tmp1 = min(scalex, scaley);
float tmp2 = min(scalex, scalez);
float tmp3 = min(scaley, scalez);

//see which one is the smallest and sent it to scale
if(tmp1 < tmp2)
{
  *scale = min(tmp2, tmp3);
}else{
  *scale = min(tmp1, tmp3);
}

//set up the x y z var and give them there values
x = y =  z = new float;
*x = (-centerx);
*y = (-centery);
*z = (-centerz);

}

When I use that code then I zoom out because for some reason that code makes the model appear really close it looks dismembared

zen: I also tryed your idea it helps but there seems to be things wrong with the model. I only worked on it for awhile since(heh no offence) marcuss idea seemed to be more useful and should do all the stuff i would have to figure out.

[This message has been edited by nukem (edited 02-06-2003).]