Smooth polygon required
I am facing this problem for a long time now. I tried everything. Increased the light intensity and smooth polygon but still same result comes when I switch on the lighting.
before lighting
after lighting
It looks like your faces are detached. What's the source of the model? What do you know about its format?
In any case, you need per-vertex normals rather than per-face as you have now. The first step is to un-detach the faces (I can't be much more specific about that since I don't know what format you're working with). The next step will then be to compute vertex normals from the face normals; how to do this is currently being discussed in a thread in the 'graphics programming' forum (or at least was as of a couple of days ago.
In any case, you need per-vertex normals rather than per-face as you have now. The first step is to un-detach the faces (I can't be much more specific about that since I don't know what format you're working with). The next step will then be to compute vertex normals from the face normals; how to do this is currently being discussed in a thread in the 'graphics programming' forum (or at least was as of a couple of days ago.
Quote:Original post by nitinjavakidHm, I don't think that tells us enough to be very helpful. IIRC, the vertex normals for Q3 models are stored as compressed spherical coordinates and must be converted on load. Are you doing this step? How are you rendering the model - immediate mode, or arrays of some sort?
I am a using Quake 3 model
Anyway, we probably need a bit more info.
Actually I am storing the vertices and all animation info in a vector.
here is the code for storing data from file and for drawing it
here is the code for storing data from file and for drawing it
#include "N3DObject.h"#include <map>#include <string>#include <math.h>#ifndef _MD3OBJECT_Htypedef struct { short int x,y,z; short int normal;}m3dvertex;struct md3fileheader{int m_iId; //Must be IDP3 (860898377)int m_iVersion; //Must be 15char m_cFilename[68]; //Full filenameint m_iNumFrames; //Number of animation keyframesint m_iNumTags; //Number of tagsint m_iNumMeshes; //Number of sub-meshesint m_iMaxSkins; //Maximum number of skins for modelint m_iHeaderSize; //Size of this headerint m_iTagOffset; //File offset for tagsint m_iMeshOffset; //End of tagsint m_iFileSize; //Size of file};struct md3meshheader{ char m_cMeshId[4]; //Mesh ID char m_cName[68]; //Mesh name int m_iNumMeshFrames; //Number of animation frames in mesh int m_iNumSkins; //Number of skins for this mesh int m_iNumVerts; //Number of vertices int m_iNumTriangles; //Number of triangles int m_iTriOffset; //Offset for the triangles int m_iHeaderSize; //Size of this header int m_iUVOffset; //Texture coordinate offset int m_iVertexOffset; //Offset for the vertices int m_iMeshSize; //Total size of the mesh};typedef struct{ nvertex position; float matrix[9];}md3tag;typedef struct{ std::vector <md3tag>tags;}md3tagframe;typedef struct{ std::vector <nvertex> vertices; std::map<std::string,md3tag> tags;} md3keyframe;typedef struct{ md3meshheader header; std::vector <md3keyframe> keyframes; std::vector <ntexcoord> texcoords; std::vector <ntriangle> triangles; GLuint texture;} md3mesh;typedef struct{ unsigned int from; unsigned int to; unsigned int loops; unsigned int fps;}md3animinfo;typedef struct { nvertex minvertex; nvertex maxvertex; nvertex origin; float radius; char name[16];} md3boneframe;class MD3Model;class MD3Object:public N3DObject{ public: md3fileheader header; std::vector <md3boneframe> boneframes; std::vector <md3mesh> meshes; std::map <std::string,md3tagframe>tagframes; std::map <std::string,MD3Object*> attachments; double curkeyframe; MD3Object(const char *filename,const char *skin); void draw(); void notifyAll(); void attach(MD3Object *pmodel,const std::string &);};class MD3Model:public N3DObject{ public: std::map <std::string,MD3Object *> objects; std::map <std::string,md3animinfo> animations; MD3Model(); ~MD3Model(); void loadFromFolder(const char *,const char *); void draw(); void addObject(const std::string &,MD3Object*);};void MD3Init();void ReduceToUnit(float vector[3]);void calcNormal(float v[3][3], float out[3]);#define _MD3OBJECT_H#endifMD3Object::MD3Object(const char *filename,const char *skin):N3DObject(){ bool skinpresent = false; unsigned int temptexture=0; if(strcmpi(skin + (strlen(skin)-4),"skin")==0) { skinpresent = true; } else { temptexture = ilutGLLoadImage((char *)skin); skinpresent = false; } unsigned int counter; curkeyframe = 0.01; FILE *file; file = fopen(filename,"rb"); if(!file) { cout<<"\nUnable to access file"; return; } char *skinch; if(skinpresent) { FILE *skinfile; skinfile = fopen(skin,"r"); if(!skinfile) { cout<<"\nUnable to access skin file"; } else { skinch = new char[sizeof(char)*filelength(fileno(skinfile)) + 1]; fread(skinch,sizeof(char)*filelength(fileno(skinfile)),1,skinfile); skinch[sizeof(char)*filelength(fileno(skinfile))] = 0; fclose(skinfile); } } //Reading file fread(&header,sizeof(header),1,file); if(header.m_iId!=860898377 || header.m_iVersion!=15) { cout<<"\nInvalid file format"; return; } //Bone frames fseek(file,header.m_iHeaderSize,SEEK_SET); for(counter=0;counter<header.m_iNumFrames;++counter) { md3boneframe tempframe; fread(&tempframe,sizeof(tempframe),1,file); boneframes.push_back(tempframe); } //Meshes fseek(file,header.m_iMeshOffset,SEEK_SET); for(counter=0;counter<header.m_iNumMeshes;++counter) { md3mesh temp; long temppos = ftell(file); fread(&temp.header,sizeof(temp.header),1,file); //printf("%s\n",temp.header.m_cName); //loading texture if(skinpresent) { if(skinch!=NULL) { char *tempstr = strstr(skinch,temp.header.m_cName); std::string texfilename; temp.texture = 0; if(tempstr) { char tempfilename[2048]; texfilename = skin; if(texfilename.find_last_of("\\")>0) texfilename = texfilename.substr(0,texfilename.find_last_of("\\")) + "\\"; else if(texfilename.find_last_of("/")>0) texfilename = texfilename.substr(0,texfilename.find_last_of("/")) + "/"; if(strchr(tempstr,'\n')) strncpy(tempfilename,strchr(tempstr,',')+1,strchr(tempstr,'\n')-strchr(tempstr,',')+1); else strcpy(tempfilename,strchr(tempstr,',')+1); if(strrchr(tempfilename,'/')>0) texfilename += strrchr(tempfilename,'/') +1; else if(strrchr(tempfilename,'\\')>0) texfilename += strrchr(tempfilename,'\\') +1; else texfilename += tempfilename; texfilename = texfilename.substr(0,texfilename.find("\n")); //strcpy(tempfilename,texfilename.c_str()); // printf("%s\n",tempfilename); temp.texture = ilutGLLoadImage(const_cast<char *> (texfilename.c_str())); } else { printf("texture for mesh %s needs to be specified in skin file\n",temp.header.m_cName); } } //loaded } else { temp.texture = temptexture; } //keyframes fseek(file,temp.header.m_iVertexOffset + temppos,SEEK_SET); for(int i=0;i<temp.header.m_iNumMeshFrames;++i) { md3keyframe keyframe; for(int j=0;j<temp.header.m_iNumVerts;++j) { m3dvertex tempvertex; fread(&tempvertex,sizeof(tempvertex),1,file); nvertex tempnv; tempnv.x = tempvertex.x/ 64.0; tempnv.y = tempvertex.y/64.0; tempnv.z = tempvertex.z/64.0; keyframe.vertices.push_back(tempnv); } temp.keyframes.push_back(keyframe); } //triangles fseek(file,temp.header.m_iTriOffset + temppos,SEEK_SET); for(i=0;i<temp.header.m_iNumTriangles;++i) { ntriangle temptriangle; fread(&temptriangle,sizeof(ntriangle),1,file); temp.triangles.push_back(temptriangle); } //texcoords fseek(file,temp.header.m_iUVOffset + temppos,SEEK_SET); for(i=0;i<temp.header.m_iNumVerts;++i) { ntexcoord temptexcoord; fread(&temptexcoord,sizeof(ntexcoord),1,file); temp.texcoords.push_back(temptexcoord); } meshes.push_back(temp); fseek(file,temppos + temp.header.m_iMeshSize, SEEK_SET); } //Tags fseek(file,header.m_iTagOffset,SEEK_SET); for(counter=0;counter<header.m_iNumFrames;++counter) { for(int i=0;i<header.m_iNumTags;++i) { char name[64]; fread(name,sizeof(char)*64,1,file); md3tag temptag; fread(&temptag,sizeof(temptag),1,file); tagframes[name].tags.push_back(temptag); } } fclose(file); if(skinpresent) { try{ delete [] skinch; }catch(...) { } }}void MD3Object::draw(){ if(visible) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glMultMatrixd(matrix); float interpolation = curkeyframe - floor(curkeyframe); if(curkeyframe==0.0) curkeyframe =0.1; glEnable(GL_TEXTURE_2D); for(int i=0;i<meshes.size();++i) { glBindTexture(GL_TEXTURE_2D,meshes.texture); glBegin(GL_TRIANGLES); for(int j=0;j<meshes.triangles.size();++j) { float triangle[3][3]; ntexcoord coord[3]; for(int k=0;k<3;++k) { if(curkeyframe>=meshes.header.m_iNumMeshFrames-1) curkeyframe = header.m_iNumFrames-1; nvertex temp1; nvertex temp2; if(curkeyframe!=0) { temp1 = meshes.keyframes[(int)ceil(curkeyframe) - 1].vertices[meshes.triangles[j].vertices[k]]; temp2 = meshes.keyframes[(int)ceil(curkeyframe)].vertices[meshes.triangles[j].vertices[k]]; } else { temp1 = meshes.keyframes[0].vertices[meshes.triangles[j].vertices[k]]; temp2 = meshes.keyframes[0].vertices[meshes.triangles[j].vertices[k]]; } coord[k] = meshes.texcoords[meshes.triangles[j].vertices[k]]; float x = temp1.x + (temp2.x-temp1.x)*interpolation; float y = temp1.y + (temp2.y-temp1.y)*interpolation; float z = temp1.z + (temp2.z-temp1.z)*interpolation; triangle[k][0] = x; triangle[k][1] = y; triangle[k][2] = z; } float out[3]; calcNormal(triangle,out); glNormal3fv(out); for(k=0;k<3;k++) { glTexCoord2f(coord[k].u,coord[k].v); glVertex3fv(triangle[k]); } } glEnd(); } glDisable(GL_TEXTURE_2D); glPopMatrix(); }}
A quick look at your code indicates that you're ignoring the vertex normals stored with the model and instead calculating the normals on the fly on a per-triangle basis. The faceted shading that you're getting is exactly what you should expect in this case.
If you want smooth shading you will have to:
a) Read the normals from the model file along with the other data, decompress them, and store them with the vertex data.
b) Issue a normal per vertex when you render. I think this can still be done via immediate mode; you'll just have to make a call to glNormal3*() at the appropriate place.
Just to get you started, here's an example of what I mean. Instead of this:
If you want smooth shading you will have to:
a) Read the normals from the model file along with the other data, decompress them, and store them with the vertex data.
b) Issue a normal per vertex when you render. I think this can still be done via immediate mode; you'll just have to make a call to glNormal3*() at the appropriate place.
Just to get you started, here's an example of what I mean. Instead of this:
glNormal3fv(out);for(k=0;k<3;k++){ glTexCoord2f(coord[k].u,coord[k].v); glVertex3fv(triangle[k]);}
You need something like this:for(k=0;k<3;k++){ glNormal3f(coord[k].nx,coord[k].ny,coord[k].nz); glTexCoord2f(coord[k].u,coord[k].v); glVertex3fv(triangle[k]);}
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement