| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- // Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #include "Exporter.h"
- #include <cmath>
- enum class ComponentFormat : uint32_t
- {
- NONE,
- R8,
- R8G8,
- R8G8B8,
- R8G8B8A8,
- R16,
- R16G16,
- R16G16B16,
- R16G16B16A16,
- R32,
- R32G32,
- R32G32B32,
- R32G32B32A32,
- R10G10B10A2,
- COUNT
- };
- enum class FormatTransform : uint32_t
- {
- NONE,
- UNORM,
- SNORM,
- UINT,
- SINT,
- FLOAT,
- COUNT
- };
- struct Format
- {
- ComponentFormat m_components = ComponentFormat::NONE;
- FormatTransform m_transform = FormatTransform::NONE;
- };
- const uint32_t FLAG_QUADS = 1;
- struct Header
- {
- char m_magic[8]; ///< Magic word.
- uint32_t m_flags;
- uint32_t m_flags2;
- Format m_positionsFormat;
- Format m_normalsFormat;
- Format m_tangentsFormat;
- Format m_colorsFormat; ///< Vertex color.
- Format m_uvsFormat;
- Format m_boneWeightsFormat;
- Format m_boneIndicesFormat;
- Format m_indicesFormat; ///< Vertex indices.
- uint32_t m_totalIndicesCount;
- uint32_t m_totalVerticesCount;
- uint32_t m_uvsChannelCount;
- uint32_t m_subMeshCount;
- uint8_t m_padding[32];
- };
- struct SubMesh
- {
- uint32_t m_firstIndex = 0;
- uint32_t m_indicesCount = 0;
- };
- struct Vertex
- {
- float m_position[3];
- uint16_t m_uv[2];
- uint32_t m_normal;
- uint32_t m_tangent;
- };
- static uint16_t toF16(float f)
- {
- union Val32
- {
- int32_t i;
- float f;
- uint32_t u;
- };
- uint16_t out;
- Val32 v32;
- v32.f = f;
- int32_t i = v32.i;
- int32_t s = (i >> 16) & 0x00008000;
- int32_t e = ((i >> 23) & 0x000000ff) - (127 - 15);
- int32_t m = i & 0x007fffff;
- if(e <= 0)
- {
- if(e < -10)
- {
- out = 0;
- }
- else
- {
- m = (m | 0x00800000) >> (1 - e);
- if(m & 0x00001000)
- {
- m += 0x00002000;
- }
- out = s | (m >> 13);
- }
- }
- else if(e == 0xff - (127 - 15))
- {
- if(m == 0)
- {
- out = s | 0x7c00;
- }
- else
- {
- m >>= 13;
- out = s | 0x7c00 | m | (m == 0);
- }
- }
- else
- {
- if(m & 0x00001000)
- {
- m += 0x00002000;
- if(m & 0x00800000)
- {
- m = 0;
- e += 1;
- }
- }
- if(e > 30)
- {
- assert(0 && "Overflow");
- out = s | 0x7c00;
- }
- else
- {
- out = s | (e << 10) | (m >> 13);
- }
- }
- return out;
- }
- union SignedR10G10B10A10
- {
- struct
- {
- int m_x : 10;
- int m_y : 10;
- int m_z : 10;
- int m_w : 2;
- } m_unpacked;
- uint32_t m_packed;
- };
- uint32_t toR10G10B10A2Sint(float r, float g, float b, float a)
- {
- SignedR10G10B10A10 out;
- out.m_unpacked.m_x = int(round(r * 511.0));
- out.m_unpacked.m_y = int(round(g * 511.0));
- out.m_unpacked.m_z = int(round(b * 511.0));
- out.m_unpacked.m_w = int(round(a * 1.0));
- return out.m_packed;
- }
- void Exporter::exportMesh(const aiMesh& mesh, const aiMatrix4x4* transform, unsigned vertCountPerFace) const
- {
- std::string name = mesh.mName.C_Str();
- std::fstream file;
- LOGI("Exporting mesh %s", name.c_str());
- // Open file
- file.open(m_outputDirectory + name + ".ankimesh", std::ios::out | std::ios::binary);
- Header header;
- memset(&header, 0, sizeof(header));
- // Checks
- if(mesh.mNumFaces == 0)
- {
- ERROR("Incorrect face number");
- }
- if(mesh.mVertices == 0)
- {
- ERROR("Incorrect vertex count number");
- }
- if(!mesh.HasPositions())
- {
- ERROR("Missing positions");
- }
- if(!mesh.HasNormals())
- {
- ERROR("Missing normals");
- }
- if(!mesh.HasTangentsAndBitangents())
- {
- ERROR("Missing tangents");
- }
- if(!mesh.HasTextureCoords(0))
- {
- ERROR("Missing UVs");
- }
- // Write header
- static const char* magic = "ANKIMES3";
- memcpy(&header.m_magic, magic, 8);
- if(vertCountPerFace == 4)
- {
- header.m_flags = FLAG_QUADS;
- }
- header.m_positionsFormat.m_components = ComponentFormat::R32G32B32;
- header.m_positionsFormat.m_transform = FormatTransform::FLOAT;
- header.m_normalsFormat.m_components = ComponentFormat::R10G10B10A2;
- header.m_normalsFormat.m_transform = FormatTransform::SNORM;
- header.m_tangentsFormat.m_components = ComponentFormat::R10G10B10A2;
- header.m_tangentsFormat.m_transform = FormatTransform::SNORM;
- header.m_uvsFormat.m_components = ComponentFormat::R16G16;
- header.m_uvsFormat.m_transform = FormatTransform::FLOAT;
- header.m_indicesFormat.m_components = ComponentFormat::R16;
- header.m_indicesFormat.m_transform = FormatTransform::UINT;
- header.m_totalIndicesCount = mesh.mNumFaces * vertCountPerFace;
- header.m_totalVerticesCount = mesh.mNumVertices;
- header.m_uvsChannelCount = 1;
- header.m_subMeshCount = 1;
- file.write(reinterpret_cast<char*>(&header), sizeof(header));
- // Write sub meshes
- SubMesh smesh;
- smesh.m_firstIndex = 0;
- smesh.m_indicesCount = header.m_totalIndicesCount;
- file.write(reinterpret_cast<char*>(&smesh), sizeof(smesh));
- // Write indices
- for(unsigned i = 0; i < mesh.mNumFaces; i++)
- {
- const aiFace& face = mesh.mFaces[i];
- if(face.mNumIndices != vertCountPerFace)
- {
- ERROR("For some reason assimp returned wrong number of verts "
- "for a face (face.mNumIndices=%d). Probably degenerates in "
- "input file",
- face.mNumIndices);
- }
- for(unsigned j = 0; j < vertCountPerFace; j++)
- {
- uint32_t index32 = face.mIndices[j];
- if(index32 > 0xFFFF)
- {
- ERROR("Index too big");
- }
- uint16_t index = index32;
- file.write(reinterpret_cast<char*>(&index), sizeof(index));
- }
- }
- // Write vertices
- aiMatrix3x3 normalMat;
- if(transform)
- {
- normalMat = aiMatrix3x3(*transform);
- }
- for(unsigned i = 0; i < mesh.mNumVertices; i++)
- {
- aiVector3D pos = mesh.mVertices[i];
- aiVector3D n = mesh.mNormals[i];
- aiVector3D t = mesh.mTangents[i];
- aiVector3D b = mesh.mBitangents[i];
- const aiVector3D& uv = mesh.mTextureCoords[0][i];
- if(transform)
- {
- pos = (*transform) * pos;
- n = normalMat * n;
- t = normalMat * t;
- b = normalMat * b;
- }
- if(m_flipyz)
- {
- static const aiMatrix4x4 toLefthanded(1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1);
- pos = toLefthanded * pos;
- n = toLefthanded * n;
- t = toLefthanded * t;
- b = toLefthanded * b;
- }
- Vertex vert;
- // Position
- vert.m_position[0] = pos[0];
- vert.m_position[1] = pos[1];
- vert.m_position[2] = pos[2];
- // Tex coords
- vert.m_uv[0] = toF16(uv[0]);
- vert.m_uv[1] = toF16(uv[1]);
- // Normal
- vert.m_normal = toR10G10B10A2Sint(n[0], n[1], n[2], 0.0);
- // Tangent
- float w = ((n ^ t) * b < 0.0) ? 1.0 : -1.0;
- vert.m_tangent = toR10G10B10A2Sint(t[0], t[1], t[2], w);
- // Write
- file.write(reinterpret_cast<char*>(&vert), sizeof(vert));
- }
- }
|