| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 |
- #include <fstream>
- #include <cstring>
- #include <boost/lexical_cast.hpp>
- #include <boost/foreach.hpp>
- #include "anki/resource/MeshData.h"
- #include "anki/util/BinaryStream.h"
- namespace anki {
- //==============================================================================
- void MeshData::load(const char* filename)
- {
- // Try
- try
- {
- // Open the file
- std::fstream file(filename, std::fstream::in | std::fstream::binary);
- if(!file.is_open())
- {
- throw ANKI_EXCEPTION("Cannot open file \"" + filename + "\"");
- }
- BinaryStream bs(file.rdbuf());
- // Magic word
- char magic[8];
- bs.read(magic, 8);
- if(bs.fail() || memcmp(magic, "ANKIMESH", 8))
- {
- throw ANKI_EXCEPTION("Incorrect magic word");
- }
- // Mesh name
- std::string meshName = bs.readString();
- // Verts num
- uint vertsNum = bs.readUint();
- vertCoords.resize(vertsNum);
- // Vert coords
- BOOST_FOREACH(Vec3& vertCoord, vertCoords)
- {
- for(uint j = 0; j < 3; j++)
- {
- vertCoord[j] = bs.readFloat();
- }
- }
- // Faces num
- uint facesNum = bs.readUint();
- tris.resize(facesNum);
- // Faces IDs
- BOOST_FOREACH(Triangle& tri, tris)
- {
- for(uint j = 0; j < 3; j++)
- {
- tri.vertIds[j] = bs.readUint();
- // a sanity check
- if(tri.vertIds[j] >= vertCoords.size())
- {
- throw ANKI_EXCEPTION("Vert index out of bounds");
- }
- }
- }
- // Tex coords num
- uint texCoordsNum = bs.readUint();
- texCoords.resize(texCoordsNum);
- // Tex coords
- BOOST_FOREACH(Vec2& texCoord, texCoords)
- {
- for(uint i = 0; i < 2; i++)
- {
- texCoord[i] = bs.readFloat();
- }
- }
- // Vert weights num
- uint vertWeightsNum = bs.readUint();
- vertWeights.resize(vertWeightsNum);
- // Vert weights
- BOOST_FOREACH(VertexWeight& vw, vertWeights)
- {
- // get the bone connections num
- uint boneConnections = bs.readUint();
- // we treat as error if one vert doesnt have a bone
- if(boneConnections < 1)
- {
- throw ANKI_EXCEPTION("Vert sould have at least one bone");
- }
- // and here is another possible error
- if(boneConnections > VertexWeight::MAX_BONES_PER_VERT)
- {
- uint tmp = VertexWeight::MAX_BONES_PER_VERT;
- throw ANKI_EXCEPTION("Cannot have more than " +
- boost::lexical_cast<std::string>(tmp) +
- " bones per vertex");
- }
- vw.bonesNum = boneConnections;
- // for all the weights of the current vertes
- for(uint i = 0; i < vw.bonesNum; i++)
- {
- // read bone id
- uint boneId = bs.readUint();
- vw.boneIds[i] = boneId;
- // read the weight of that bone
- float weight = bs.readFloat();
- vw.weights[i] = weight;
- }
- } // end for all vert weights
- doPostLoad();
- }
- catch(Exception& e)
- {
- throw ANKI_EXCEPTION_R("File \"" + filename + "\"", e);
- }
- }
- //==============================================================================
- void MeshData::doPostLoad()
- {
- // Sanity checks
- if(vertCoords.size() < 1 || tris.size() < 1)
- {
- throw ANKI_EXCEPTION("Vert coords and tris must be filled");
- }
- if(texCoords.size() != 0 && texCoords.size() != vertCoords.size())
- {
- throw ANKI_EXCEPTION("Tex coords num must be "
- "zero or equal to the vertex "
- "coords num");
- }
- if(vertWeights.size() != 0 && vertWeights.size() != vertCoords.size())
- {
- throw ANKI_EXCEPTION("Vert weights num must be zero or equal to the "
- "vertex coords num");
- }
- createAllNormals();
- if(texCoords.size() > 0)
- {
- createVertTangents();
- }
- createVertIndeces();
- }
- //==============================================================================
- void MeshData::createVertIndeces()
- {
- vertIndeces.resize(tris.size() * 3);
- for(uint i = 0; i < tris.size(); i++)
- {
- vertIndeces[i * 3 + 0] = tris[i].vertIds[0];
- vertIndeces[i * 3 + 1] = tris[i].vertIds[1];
- vertIndeces[i * 3 + 2] = tris[i].vertIds[2];
- }
- }
- //==============================================================================
- void MeshData::createFaceNormals()
- {
- BOOST_FOREACH(Triangle& tri, tris)
- {
- const Vec3& v0 = vertCoords[tri.vertIds[0]];
- const Vec3& v1 = vertCoords[tri.vertIds[1]];
- const Vec3& v2 = vertCoords[tri.vertIds[2]];
- /*std::cout << v0 << std::endl;
- std::cout << v1 << std::endl;
- std::cout << v2 << std::endl;
- std::cout << std::endl;*/
- tri.normal = (v1 - v0).cross(v2 - v0);
- tri.normal.normalize();
- }
- }
- //==============================================================================
- void MeshData::createVertNormals()
- {
- vertNormals.resize(vertCoords.size());
- BOOST_FOREACH(Vec3& vertNormal, vertNormals)
- {
- vertNormal = Vec3(0.0, 0.0, 0.0);
- }
- BOOST_FOREACH(Triangle& tri, tris)
- {
- vertNormals[tri.vertIds[0]] += tri.normal;
- vertNormals[tri.vertIds[1]] += tri.normal;
- vertNormals[tri.vertIds[2]] += tri.normal;
- }
- BOOST_FOREACH(Vec3& vertNormal, vertNormals)
- {
- vertNormal.normalize();
- }
- }
- //==============================================================================
- void MeshData::createVertTangents()
- {
- vertTangents.resize(vertCoords.size(), Vec4(0.0)); // alloc
- std::vector<Vec3> bitagents(vertCoords.size(), Vec3(0.0));
- for(uint i = 0; i < tris.size(); i++)
- {
- const Triangle& tri = tris[i];
- const int i0 = tri.vertIds[0];
- const int i1 = tri.vertIds[1];
- const int i2 = tri.vertIds[2];
- const Vec3& v0 = vertCoords[i0];
- const Vec3& v1 = vertCoords[i1];
- const Vec3& v2 = vertCoords[i2];
- Vec3 edge01 = v1 - v0;
- Vec3 edge02 = v2 - v0;
- Vec2 uvedge01 = texCoords[i1] - texCoords[i0];
- Vec2 uvedge02 = texCoords[i2] - texCoords[i0];
- float det = (uvedge01.y() * uvedge02.x()) -
- (uvedge01.x() * uvedge02.y());
- if(Math::isZero(det))
- {
- //ANKI_WARNING(getRsrcName() << ": det == " << fixed << det);
- det = 0.0001;
- }
- else
- {
- det = 1.0 / det;
- }
- Vec3 t = (edge02 * uvedge01.y() - edge01 * uvedge02.y()) * det;
- Vec3 b = (edge02 * uvedge01.x() - edge01 * uvedge02.x()) * det;
- t.normalize();
- b.normalize();
- vertTangents[i0] += Vec4(t, 1.0);
- vertTangents[i1] += Vec4(t, 1.0);
- vertTangents[i2] += Vec4(t, 1.0);
- bitagents[i0] += b;
- bitagents[i1] += b;
- bitagents[i2] += b;
- }
- for(uint i = 0; i < vertTangents.size(); i++)
- {
- Vec3 t = Vec3(vertTangents[i]);
- const Vec3& n = vertNormals[i];
- Vec3& b = bitagents[i];
- //t = t - n * n.dot(t);
- t.normalize();
- b.normalize();
- float w = ((n.cross(t)).dot(b) < 0.0) ? 1.0 : -1.0;
- vertTangents[i] = Vec4(t, w);
- }
- }
- } // end namespace
|