3DS and normals
some1 here knows if 3DS saves the compution of the face normals. and if 3ds does saves it in the file what is the CHUNK ID? 10x in Advance BlackRyder
Don't know, 3ds is such an old format, so im not even shure they thought about it then, maybe they added it on later, in witch case older models might not have it.
It might be worth to check out http://www.wotsit.org/ just to be shure.
Either way, it's probobly better if you calcylate them yourself at load time.
It's fast, easy and you might even get better results if you do it right.
It might be worth to check out http://www.wotsit.org/ just to be shure.
Either way, it's probobly better if you calcylate them yourself at load time.
It's fast, easy and you might even get better results if you do it right.
www.flashbang.se | www.thegeekstate.com | nehe.gamedev.net | glAux fix for lesson 6 | [twitter]thegeekstate[/twitter]
i am computing the normals at loading but i got some crappy results maybe it worth if someone here could check it out for me:
calculating a face normal:
calculating a face normal:
inline Vector3D Object::computeFaceNormal(const Face &face){ Vector3D u(vertex_list.at(face[0]),vertex_list.at(face[1])); Vector3D v(vertex_list.at(face[0]),vertex_list.at(face[2])); return u.crossProduct(v);}Vector3D Vector3D::crossProduct(const Vector3D &v){ Vector3D result; result.x = (y*v.z) - (z*v.y); result.y = (z*v.x) - (x*v.z); result.z = (x*v.y) - (y*v.x); return result;}
looks ok, but i can't be shure.
a few things can happen to create crappy results.
1. the normal can get inverted
2. the normal might have the wrong magnitude
So normalize your normals to a magnitude of 1 or -1 depending on witch one looks the best.
But this will only get you half way, the normals will make your models look faceted.
So to make the normals smoother you must blend your normals with it's neighbours.
For every vertic on every face you test the facenormal with every neighbouring faces facenormal using a dot product.
if the result is larger than 0.71 then add that normal to the vertic normal.
And finaly normalize all the normals one last time to a magnitude of 1.
a few things can happen to create crappy results.
1. the normal can get inverted
2. the normal might have the wrong magnitude
So normalize your normals to a magnitude of 1 or -1 depending on witch one looks the best.
But this will only get you half way, the normals will make your models look faceted.
So to make the normals smoother you must blend your normals with it's neighbours.
For every vertic on every face you test the facenormal with every neighbouring faces facenormal using a dot product.
if the result is larger than 0.71 then add that normal to the vertic normal.
And finaly normalize all the normals one last time to a magnitude of 1.
www.flashbang.se | www.thegeekstate.com | nehe.gamedev.net | glAux fix for lesson 6 | [twitter]thegeekstate[/twitter]
your last algorithem is like O(n^2) you test every vertic to check the whole
conectivity.
isnt it faster to produce the normal list offline?
and load it when ever you need it...
conectivity.
isnt it faster to produce the normal list offline?
and load it when ever you need it...
it's allways faster to do that.
it's allways better to have your own format,instead of using another one that doesn't contain all the stuff you need.
But i did run this code once for every frame, it actuarly worked fairly well, but it didn't run as fast is i wanted to.
it's allways better to have your own format,instead of using another one that doesn't contain all the stuff you need.
But i did run this code once for every frame, it actuarly worked fairly well, but it didn't run as fast is i wanted to.
www.flashbang.se | www.thegeekstate.com | nehe.gamedev.net | glAux fix for lesson 6 | [twitter]thegeekstate[/twitter]
take a look at the code and comment it
[Edited by - BlackRyder on September 11, 2005 5:32:50 AM]
Vector3D Object::computeVertexBlendedNormal(unsigned int vertexNum,vector<Vector3D> &facesNormalList){ Face face; //Holds the current tested faces unsigned int faceNum; //Holds the current face number that we test. Vector3D vertexNormal; //Holds the result blended normal Vector3D faceNormal; //Holds the current face normal Vector3D blendNormal; //Holds the result blended normal bool first=true; //Holds indication if this is the first face that hold the vertex for(faceNum=0;faceNum<face_list.size();faceNum++) { face = face_list.at(faceNum); //if this is a neighbor face if((face[0]==vertexNum)||(face[1]==vertexNum)||(face[2]==vertexNum)) { faceNormal = facesNormalList.at(faceNum); if(first) { blendedNormal = faceNormal; vertexNormal = faceNormal; first = false; } else { if(vertexNormal.dotProduct(faceNormal)>=0.71) { blendNormal =vertexNormal+faceNormal; } } } } blendNormal.normalize(); return blendNormal;}
[Edited by - BlackRyder on September 11, 2005 5:32:50 AM]
um more like this perhaps
note: currentfaceNum should be the current face this normal is attatched to, this is important.
Allso remember that each face has 4 normals, the face normal and the individual vertex normals, witch are the blended ones, i cant tell if you have it this way, but you should.
note: currentfaceNum should be the current face this normal is attatched to, this is important.
Allso remember that each face has 4 normals, the face normal and the individual vertex normals, witch are the blended ones, i cant tell if you have it this way, but you should.
Vector3D Object::computeVertexBlendedNormal(unsigned int currentfaceNum,unsigned int vertexNum,vector<Vector3D> &facesNormalList){ Face face; //Holds the current tested faces unsigned int faceNum; //Holds the current face number that we test. Vector3D vertexNormal; //Holds the result blended normal Vector3D faceNormal; //Holds the current face normal Vector3D blendNormal; //Holds the result blended normal bool first=true; //Holds indication if this is the first face that hold the vertexvertexNormal = facesNormalList.at(currentfaceNum); for(faceNum=0;faceNum<face_list.size();faceNum++) { face = face_list.at(faceNum); //if this is a neighbor face if((face[0]==vertexNum)||(face[1]==vertexNum)||(face[2]==vertexNum)) { faceNormal = facesNormalList.at(faceNum); if(vertexNormal.dotProduct(faceNormal)>=0.71) { if(first) { blendedNormal = faceNormal; first = false; } else { blendNormal +=faceNormal; } } } } blendNormal.normalize(); return blendNormal;}
www.flashbang.se | www.thegeekstate.com | nehe.gamedev.net | glAux fix for lesson 6 | [twitter]thegeekstate[/twitter]
at first the facesNormalList has only the face normal
because at first each vertex has the same normal as its face normal
that is why i had the "first" indication because i take the first face that contains the vertex as the vertexNormal to work with and test according to it.
please correct me if i am wrong
because at first each vertex has the same normal as its face normal
that is why i had the "first" indication because i take the first face that contains the vertex as the vertexNormal to work with and test according to it.
please correct me if i am wrong
Well, you have to use the normal it had first(the face normal), before you started testing, .
But that doesn't mean that it will be the one that you encounter first in the list, it might be the second one or third or whatever.
let me post some of my code(witch BTW is old and uggly), it might explain things a bit better.
POLS.p_data is the polygon structure where each p_data is a polygon.
.v_ref is the vertex references of the polygon.
.p_n is the face normal of the polygon.
.n[ ] is the vertex normals of the polygon.
there is allso a .v_uv, but it's not use here.
i,j,k are integers.
But that doesn't mean that it will be the one that you encounter first in the list, it might be the second one or third or whatever.
let me post some of my code(witch BTW is old and uggly), it might explain things a bit better.
POLS.p_data is the polygon structure where each p_data is a polygon.
.v_ref is the vertex references of the polygon.
.p_n is the face normal of the polygon.
.n[ ] is the vertex normals of the polygon.
there is allso a .v_uv, but it's not use here.
i,j,k are integers.
float tn[3]; //temp normal storage int num,vn; i=0; while(i<cfmdfile->POLS.p_num) { k=0; while(k<3) { j=0; num=0; tn[0]=0; tn[1]=0; tn[2]=0; // first find and add all normals who share this point to tn while(j<cfmdfile->POLS.p_num) { if (cfmdfile->POLS.p_data[j].v_ref[0]==cfmdfile->POLS.p_data.v_ref[k]) { if (dotproduct(cfmdfile->POLS.p_data[j].p_n,cfmdfile->POLS.p_data.p_n)>0.71f) { tn[0]+=cfmdfile->POLS.p_data[j].p_n[0]; tn[1]+=cfmdfile->POLS.p_data[j].p_n[1]; tn[2]+=cfmdfile->POLS.p_data[j].p_n[2]; } } if (cfmdfile->POLS.p_data[j].v_ref[1]==cfmdfile->POLS.p_data.v_ref[k]) { if (dotproduct(cfmdfile->POLS.p_data[j].p_n,cfmdfile->POLS.p_data.p_n)>0.71f) { tn[0]+=cfmdfile->POLS.p_data[j].p_n[0]; tn[1]+=cfmdfile->POLS.p_data[j].p_n[1]; tn[2]+=cfmdfile->POLS.p_data[j].p_n[2]; } } if (cfmdfile->POLS.p_data[j].v_ref[2]==cfmdfile->POLS.p_data.v_ref[k]) { if (dotproduct(cfmdfile->POLS.p_data[j].p_n,cfmdfile->POLS.p_data.p_n)>0.71f) { tn[0]+=cfmdfile->POLS.p_data[j].p_n[0]; tn[1]+=cfmdfile->POLS.p_data[j].p_n[1]; tn[2]+=cfmdfile->POLS.p_data[j].p_n[2]; } } j++; } //normalize the values m=magnitude(tn); tn[0]=tn[0]/m; tn[1]=tn[1]/m; tn[2]=tn[2]/m; // Second, place it where it belongs cfmdfile->POLS.p_data.n[k][0]=tn[0]; cfmdfile->POLS.p_data.n[k][1]=tn[1]; cfmdfile->POLS.p_data.n[k][2]=tn[2]; k++; } i++; }
www.flashbang.se | www.thegeekstate.com | nehe.gamedev.net | glAux fix for lesson 6 | [twitter]thegeekstate[/twitter]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement