Sign in to follow this  
mymo

md3 rendering: normals?!

Recommended Posts

mymo    122
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[i][j][0] = (float) (cos(b) * sin(a));
			anorms[i][j][1] = (float) (sin(b) * sin(a));
			anorms[i][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[i].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[u][v][0], anorms[u][v][1], anorms[u][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

Share this post


Link to post
Share on other sites
Zipster    2359
After a quick foray into the world of MD3, I found this snippet on decoding normals:

lat <- (normal binary-and 255) * (2 * pi) / 255
lng <- ((normal shift-right 8) binary-and 255) * (2 * pi ) / 255
x <- 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]

Share this post


Link to post
Share on other sites
mymo    122
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?

Share this post


Link to post
Share on other sites
mymo    122
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[i].vertex[j];
int u = meshes[0].vertices[index].normal[0];
int v = meshes[0].vertices[index].normal[1];
glNormal3f(anorms[u][v][0], anorms[u][v][1], anorms[u][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

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Because once you sent glVertex3f it was moving onto the next vertex and sending the normal for the current vertex to the next vertex.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this