Files
o3de/Code/CryEngine/Cry3DEngine/MeshCompiler/ForsythFaceReorderer.h
T
2021-03-08 14:30:57 -08:00

96 lines
3.5 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#pragma once
#include <vector>
#include <BaseTypes.h>
#include "CompileTimeAssert.h"
//
// Note: This implementation, in contrast to many other implementations
// of the Forsyth's algorithm, does not crash when the input faces contain
// duplicate indices, for example (8,3,8) or (1,1,9).
//
class ForsythFaceReorderer
{
public:
static const size_t sk_maxCacheSize = 50; // you can change it. note: making it higher will increase sizeof(*this)
static const size_t sk_minVerticesPerFace = 3;
static const size_t sk_maxVerticesPerFace = 4;
COMPILE_TIME_ASSERT(sk_minVerticesPerFace >= 3); // Bad min # of vertices per face
COMPILE_TIME_ASSERT(sk_minVerticesPerFace <= sk_maxVerticesPerFace); // Bad # of vertices per face
COMPILE_TIME_ASSERT(sk_maxVerticesPerFace <= sk_maxCacheSize); // Bad max cache size
private:
typedef uint16 valency_type;
static const valency_type sk_maxValency = 0xFFFF;
typedef int8 cachepos_type;
static const cachepos_type sk_maxCachePos = 127;
struct Vertex
{
uint32* m_pFaceList;
valency_type m_aliveFaceCount;
cachepos_type m_posInCache;
float m_score;
};
static const size_t sk_valencyTableSize = 32; // note: size_t is used instead of valency_type because valency_type overflows if sk_valencyTableSize == 1 + sk_maxValency
COMPILE_TIME_ASSERT(sk_valencyTableSize - 1 <= sk_maxValency); // Bad valency table size
COMPILE_TIME_ASSERT(sk_maxCacheSize <= 1 + (size_t)sk_maxCachePos); // Max cache size is too big
std::vector<Vertex> m_vertices;
std::vector<uint8> m_deadFacesBitArray;
std::vector<float> m_faceScores; // score of every face
std::vector<uint32> m_vertexFaceLists; // lists with indices of faces (each vertex has own list)
int m_cacheSize;
int m_cacheUsedSize;
uint32 m_cache[sk_maxCacheSize + sk_maxVerticesPerFace]; // +sk_maxVerticesPerFace is temporary storage for vertices of the incoming face
float m_scoreTable_valency[sk_valencyTableSize];
float m_scoreTable_cachePosition[sk_maxCacheSize];
public:
ForsythFaceReorderer();
// notes:
// 1) it's not allowed to pass same array for inVertexIndices and outVertexIndices
// 2) outFaceToOldFace is optional (pass 0 if you don't need this array filled)
bool reorderFaces(
const size_t cacheSize,
const uint verticesPerFace,
const size_t indexCount,
const uint32* const inVertexIndices,
uint32* const outVertexIndices,
uint32* const outFaceToOldFace);
private:
void clear();
void computeCacheScoreTable(const int verticesPerFace);
void computeValencyScoreTable();
void computeVertexScore(Vertex& v);
void moveVertexToCacheTop(const uint32 vertexIndex);
void removeFaceFromVertex(const uint32 vertexIndex, const uint32 faceIndex);
uint32 findBestFaceToAdd(uint32& faceSearchCursor) const;
};