Mesh/MeshParams: Replace flipUVs by texCoordOffset and texCoordScale

This commit is contained in:
Lynix 2016-11-24 09:43:56 +01:00
parent 3ae5bfad63
commit 0c8128b7e4
6 changed files with 52 additions and 62 deletions

View File

@ -156,9 +156,10 @@ namespace Nz
params->animated = instance.CheckField<bool>("Animated", params->animated);
params->center = instance.CheckField<bool>("Center", params->center);
params->flipUVs = instance.CheckField<bool>("FlipUVs", params->flipUVs);
params->matrix = instance.CheckField<Matrix4f>("Matrix", params->matrix);
params->optimizeIndexBuffers = instance.CheckField<bool>("OptimizeIndexBuffers", params->optimizeIndexBuffers);
params->texCoordOffset = instance.CheckField<Vector2f>("TexCoordOffset", params->texCoordOffset);
params->texCoordScale = instance.CheckField<Vector2f>("TexCoordScale", params->texCoordScale);
return 1;
}

View File

@ -28,25 +28,15 @@ namespace Nz
{
struct NAZARA_UTILITY_API MeshParams : ResourceParameters
{
MeshParams(); // Vérifie que le storage par défaut est supporté (software autrement)
MeshParams();
// La transformation appliquée à tous les sommets du mesh
Matrix4f matrix = Matrix4f::Identity();
// Si ceci sera le stockage utilisé par les buffers
UInt32 storage = DataStorage_Hardware;
// Charger une version animée du mesh si possible ?
bool animated = true;
// Faut-il centrer le mesh autour de l'origine ?
bool center = false;
// Faut-il retourner les UV ?
bool flipUVs = false;
// Faut-il optimiser les index buffers ? (Rendu plus rapide, mais le chargement dure plus longtemps)
bool optimizeIndexBuffers = true;
Matrix4f matrix = Matrix4f::Identity(); ///< A matrix which will transform every vertex position
UInt32 storage = DataStorage_Hardware; ///< The place where the buffers will be allocated
Vector2f texCoordOffset = {0.f, 0.f}; ///< Offset to apply on the texture coordinates (not scaled)
Vector2f texCoordScale = {1.f, 1.f}; ///< Scale to apply on the texture coordinates
bool animated = true; ///< If true, will load an animated version of the model if possible
bool center = false; ///< If true, will center the mesh vertices around the origin
bool optimizeIndexBuffers = true; ///< Optimize the index buffers after loading, improve cache locality (and thus rendering speed) but increase loading time.
bool IsValid() const;
};

View File

@ -97,17 +97,14 @@ bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters)
unsigned int postProcess = aiProcess_CalcTangentSpace | aiProcess_JoinIdenticalVertices
| aiProcess_MakeLeftHanded | aiProcess_Triangulate
| aiProcess_RemoveComponent | aiProcess_GenSmoothNormals
| aiProcess_SplitLargeMeshes | aiProcess_LimitBoneWeights
| aiProcess_ImproveCacheLocality | aiProcess_RemoveRedundantMaterials
| aiProcess_FixInfacingNormals | aiProcess_SortByPType
| aiProcess_FindInvalidData | aiProcess_GenUVCoords
| aiProcess_TransformUVCoords | aiProcess_OptimizeMeshes
| aiProcess_OptimizeGraph | aiProcess_FlipWindingOrder
| aiProcess_SplitLargeMeshes | aiProcess_LimitBoneWeights
| aiProcess_ImproveCacheLocality | aiProcess_RemoveRedundantMaterials
| aiProcess_FixInfacingNormals | aiProcess_SortByPType
| aiProcess_FindInvalidData | aiProcess_GenUVCoords
| aiProcess_TransformUVCoords | aiProcess_OptimizeMeshes
| aiProcess_OptimizeGraph | aiProcess_FlipWindingOrder
| aiProcess_Debone;
if (parameters.flipUVs)
postProcess |= aiProcess_FlipUVs;
if (parameters.optimizeIndexBuffers)
postProcess |= aiProcess_ImproveCacheLocality;
@ -157,7 +154,7 @@ bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters)
if (animatedMesh)
{
mesh->CreateSkeletal(joints.size());
Skeleton* skeleton = mesh->GetSkeleton();
// First, assign names
@ -172,9 +169,9 @@ bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters)
else
{
mesh->CreateStatic();
// aiMaterial index in scene => Material index and data in Mesh
std::unordered_map<unsigned int, std::pair<unsigned int, ParameterList>> materials;
std::unordered_map<unsigned int, std::pair<std::size_t, ParameterList>> materials;
for (unsigned int i = 0; i < scene->mNumMeshes; ++i)
{
@ -219,7 +216,7 @@ bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters)
vertex->position = parameters.matrix * Vector3f(position.x, position.y, position.z);
vertex->normal.Set(normal.x, normal.y, normal.z);
vertex->tangent.Set(tangent.x, tangent.y, tangent.z);
vertex->uv.Set(uv.x, uv.y);
vertex->uv.Set(parameters.texCoordOffset + Vector2f(uv.x, uv.y) * parameters.texCoordScale);
vertex++;
}
@ -311,7 +308,7 @@ bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters)
mesh->AddSubMesh(subMesh);
}
mesh->SetMaterialCount(std::max<unsigned int>(materials.size(), 1));
mesh->SetMaterialCount(std::max<UInt32>(materials.size(), 1));
for (const auto& pair : materials)
mesh->SetMaterialData(pair.second.first, pair.second.second);
}

View File

@ -81,15 +81,14 @@ namespace Nz
return false;
}
/// Création du mesh
// Le moteur ne supporte plus les animations image-clé, nous ne pouvons charger qu'en statique
if (!mesh->CreateStatic()) // Ne devrait jamais échouer
// Since the engine no longer supports keyframe animations, let's make a static mesh
if (!mesh->CreateStatic())
{
NazaraInternalError("Failed to create mesh");
return false;
}
/// Chargement des skins
// Extract skins (texture name)
if (header.num_skins > 0)
{
mesh->SetMaterialCount(header.num_skins);
@ -109,16 +108,15 @@ namespace Nz
}
}
/// Chargement des submesh
// Actuellement le loader ne charge qu'un submesh
IndexBufferRef indexBuffer = IndexBuffer::New(false, header.num_tris*3, parameters.storage, BufferUsage_Static);
/// Lecture des triangles
// Extract triangles data
std::vector<MD2_Triangle> triangles(header.num_tris);
stream.SetCursorPos(header.offset_tris);
stream.Read(&triangles[0], header.num_tris*sizeof(MD2_Triangle));
// And convert them into an index buffer
BufferMapper<IndexBuffer> indexMapper(indexBuffer, BufferAccess_DiscardAndWrite);
UInt16* index = static_cast<UInt16*>(indexMapper.GetPointer());
@ -135,7 +133,7 @@ namespace Nz
SwapBytes(&triangles[i].texCoords[2], sizeof(UInt16));
#endif
// On respécifie le triangle dans l'ordre attendu
// Reverse winding order
*index++ = triangles[i].vertices[0];
*index++ = triangles[i].vertices[2];
*index++ = triangles[i].vertices[1];
@ -143,10 +141,11 @@ namespace Nz
indexMapper.Unmap();
// Optimize if requested (improves cache locality)
if (parameters.optimizeIndexBuffers)
indexBuffer->Optimize();
/// Lecture des coordonnées de texture
// Extracting texture coordinates
std::vector<MD2_TexCoord> texCoords(header.num_st);
stream.SetCursorPos(header.offset_st);
@ -168,15 +167,15 @@ namespace Nz
return false;
}
/// Chargement des vertices
// Extracting vertices
stream.SetCursorPos(header.offset_frames);
std::unique_ptr<MD2_Vertex[]> vertices(new MD2_Vertex[header.num_vertices]);
std::vector<MD2_Vertex> vertices(header.num_vertices);
Vector3f scale, translate;
stream.Read(scale, sizeof(Vector3f));
stream.Read(translate, sizeof(Vector3f));
stream.Read(nullptr, 16*sizeof(char)); // Nom de la frame, inutile ici
stream.Read(vertices.get(), header.num_vertices*sizeof(MD2_Vertex));
stream.Read(nullptr, 16*sizeof(char)); //< Frame name, unused
stream.Read(vertices.data(), header.num_vertices*sizeof(MD2_Vertex));
#ifdef NAZARA_BIG_ENDIAN
SwapBytes(&scale.x, sizeof(float));
@ -196,23 +195,26 @@ namespace Nz
BufferMapper<VertexBuffer> vertexMapper(vertexBuffer, BufferAccess_DiscardAndWrite);
MeshVertex* vertex = static_cast<MeshVertex*>(vertexMapper.GetPointer());
/// Chargement des coordonnées de texture
const unsigned int indexFix[3] = {0, 2, 1}; // Pour respécifier les indices dans le bon ordre
// Loading texture coordinates
const unsigned int indexFix[3] = {0, 2, 1};
Vector2f invSkinSize(1.f / header.skinwidth, 1.f / header.skinheight);
for (unsigned int i = 0; i < header.num_tris; ++i)
{
for (unsigned int j = 0; j < 3; ++j)
{
const unsigned int fixedIndex = indexFix[j];
const MD2_TexCoord& texC = texCoords[triangles[i].texCoords[fixedIndex]];
float u = static_cast<float>(texC.u) / header.skinwidth;
float v = static_cast<float>(texC.v) / header.skinheight;
const unsigned int fixedIndex = indexFix[j]; //< Reverse winding order
vertex[triangles[i].vertices[fixedIndex]].uv.Set(u, (parameters.flipUVs) ? 1.f - v : v);
const MD2_TexCoord& texC = texCoords[triangles[i].texCoords[fixedIndex]];
Vector2f uv(texC.u, texC.v);
uv *= invSkinSize;
vertex[triangles[i].vertices[fixedIndex]].uv.Set(parameters.texCoordOffset + uv * parameters.texCoordScale);
}
}
/// Chargement des positions
// Pour que le modèle soit correctement aligné, on génère un quaternion que nous appliquerons à chacune des vertices
// Loading vertex position
// Align the model to our coordinates system
Quaternionf rotationQuat = EulerAnglesf(-90.f, 90.f, 0.f);
Nz::Matrix4f matrix = Matrix4f::Transform(translate, rotationQuat, scale);
matrix *= parameters.matrix;

View File

@ -184,7 +184,7 @@ namespace Nz
}
vertices->position = finalPos;
vertices->uv.Set(vertex.uv.x, (parameters.flipUVs) ? 1.f - vertex.uv.y : vertex.uv.y); // Inversion des UV si demandé
vertices->uv.Set(parameters.texCoordOffset + vertex.uv * parameters.texCoordScale);
vertices++;
}
@ -254,7 +254,7 @@ namespace Nz
VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent), vertexCount, parameters.storage);
BufferMapper<VertexBuffer> vertexMapper(vertexBuffer, BufferAccess_WriteOnly);
MeshVertex* vertex = static_cast<MeshVertex*>(vertexMapper.GetPointer());
MeshVertex* vertices = static_cast<MeshVertex*>(vertexMapper.GetPointer());
for (const MD5MeshParser::Vertex& md5Vertex : md5Mesh.vertices)
{
// Skinning MD5 (Formule d'Id Tech)
@ -268,9 +268,9 @@ namespace Nz
}
// On retourne le modèle dans le bon sens
vertex->position = matrix * finalPos;
vertex->uv.Set(md5Vertex.uv.x, (parameters.flipUVs) ? 1.f - md5Vertex.uv.y : md5Vertex.uv.y); // Inversion des UV si demandé
vertex++;
vertices->position = matrix * finalPos;
vertices->uv.Set(parameters.texCoordOffset + md5Vertex.uv * parameters.texCoordScale);
vertices++;
}
vertexMapper.Unmap();

View File

@ -265,8 +265,8 @@ namespace Nz
if (vertexIndices.texCoord > 0)
{
const Vector3f& uvw = texCoords[vertexIndices.texCoord-1];
vertex.uv.Set(uvw.x, (parameters.flipUVs) ? 1.f - uvw.y : uvw.y); // Inversion des UVs si demandé
Vector2f uv = texCoords[vertexIndices.texCoord - 1];
vertex.uv.Set(parameters.texCoordOffset + uv * parameters.texCoordScale);
}
else
hasTexCoords = false;