md3 rendering: normals?!

Started by
3 comments, last by GameDev.net 18 years, 5 months ago
Hi there, i got some trouble with the rendering of md3 models. Some days ago, i tried the md2 format and everything was just fine. So, I tried the md3 format. But the rendered md3 model looks strange, or let's say "not very smooth": Take a look for yourself: md2 head: http://www.cbnl.de/model/md2.jpg md3 head: http://www.cbnl.de/model/md3.jpg I have no idea why is that, but - assuming my model loading is right - i could imagine that my calculation of the normals is not correct. (For md2 I'm using the precalculated normals in quake's anorms.h, btw.) The data structures

typedef struct {
	md3_mesh_header header;
	md3_skin *skins;
	md3_triangle *triangles;
	md3_tex_coords *tex_coords;
	md3_vertex *vertices;
	GLuint texture;
	bool set_texture;
} md3_mesh;

typedef struct {
	short coords[3];
	char normal[2];
} md3_vertex;

typedef struct {
	int vertex[3];
} md3_triangle;

float anorms[256][256][3];



calculating the normals:

	float a, b;
	for (int i = 0; i < 256; i++) {
		for (int j = 0; j < 256; j++) {
			a = i * 2.0 * 3.14159265358979 / 255.0;
			b = j * 2.0 * 3.14159265358979 / 255.0;
			anorms[j][0] = (float) (cos(b) * sin(a));
			anorms[j][1] = (float) (sin(b) * sin(a));
			anorms[j][2] = (float) cos(a);
		}
	}



Don't know where I got that from, but another way is that:

  vector norm_coords;
  char *norm = meshes[0].vertices[index].normal;
  double pi = 3.1415927;
  float lat = (norm[0] & 255) * (2.0 * pi) / 255.0;
  float lng = (norm[1] & 255)* ( 2.0 * pi) / 255.0;
  norm_coords[0] = cos(lng) * sin(lat);
  norm_coords[1] = sin(lng) * sin(lat);
  norm_coords[2] = cos(lat);
  glNormal3fv(norm_coords);



Pretty the same and the results are - of course - the same... The rendering:

glBegin(GL_TRIANGLES);
  float scale = 1.0 / 64.0;
  for (int i = 0; i < meshes[0].header.num_triangles; i++) {
    for (int j = 0; j < 3; j++) {
      int index = meshes[0].triangles.vertex[j];
      glVertex3f((GLfloat) meshes[0].vertices[index].coords[0] * scale,
		     (GLfloat) meshes[0].vertices[index].coords[1] * scale,
		       (GLfloat) meshes[0].vertices[index].coords[2] * scale);
      int u = meshes[0].vertices[index].normal[0];
      int v = meshes[0].vertices[index].normal[1];
      glNormal3f(anorms[v][0], anorms[v][1], anorms[v][2]);
    }
  }
glEnd();



It's just drawing the model's first frame without any textures or animation. It's kind of messy. Sorry for that :) (But I'm still testing) Maybe it's also important ... my lighting:

GLfloat amb[] = {1.0f, 1.0f, 1.0f, 1.0f};
GLfloat diff[] = {1.0f, 1.0f, 1.0f, 1.0f};
glLightfv(GL_LIGHT1, GL_AMBIENT, amb);
glLightfv(GL_LIGHT1, GL_DIFFUSE, diff);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHTING);



So, what am I doing wrong? Did I forget anything? regards
Advertisement
After a quick foray into the world of MD3, I found this snippet on decoding normals:
lat <- (normal binary-and 255) * (2 * pi) / 255lng <- ((normal shift-right 8) binary-and 255) * (2 * pi ) / 255x <- cos ( lat ) * sin ( lng )y <- sin ( lat ) * sin ( lng )z <- cos ( lng )

Looks to me like your lat and lng angles may be reversed, either in how you take the cosine and sine or how you extract them from the normal array. Try flipping stuff around until you get something that works. For instance, switch lat and lng or norm[0] and norm[1]. After all, there are only three more possible combinations and one of them has to work! [smile]
Hi :)

I did that before. I mean switching and stuff like that.
But everything else looks even more weird. I was just guessing that it's caused by my normal vectors, but probably it's something else?!

Could there anything else be the reason?
ok, that was funny. I tried some more things without any great effects and then, I simply put the normal calculation in the rendering _before_ the glVertex3f(). And now it works. *lol*

glBegin(GL_TRIANGLES);  float scale = 1.0 / 64.0;  for (int i = 0; i < meshes[0].header.num_triangles; i++) {    for (int j = 0; j < 3; j++) {      int index = meshes[0].triangles.vertex[j];      int u = meshes[0].vertices[index].normal[0];      int v = meshes[0].vertices[index].normal[1];      glNormal3f(anorms[v][0], anorms[v][1], anorms[v][2]);      glVertex3f((GLfloat) meshes[0].vertices[index].coords[0] * scale,		     (GLfloat) meshes[0].vertices[index].coords[1] * scale,		       (GLfloat) meshes[0].vertices[index].coords[2] * scale);    }  }glEnd();


I'm happy now, but it'll be great if anyone could tell me, why it does not work the other way ...

have a nice day :D
Because once you sent glVertex3f it was moving onto the next vertex and sending the normal for the current vertex to the next vertex.

This topic is closed to new replies.

Advertisement