Refactor portal surface to remove faces and only deal with edges
This commit is contained in:
parent
40cdc0d02a
commit
92247567e0
|
@ -33,6 +33,8 @@ aiMesh* copyMesh(aiMesh* mesh) {
|
|||
}
|
||||
}
|
||||
|
||||
result->mName = mesh->mName;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,37 @@ int levelEdgeKey(int a, int b) {
|
|||
}
|
||||
|
||||
struct EdgeIndices {
|
||||
EdgeIndices();
|
||||
uint8_t a;
|
||||
uint8_t b;
|
||||
int edgeIndex;
|
||||
|
||||
int nextEdgeKey;
|
||||
int prevEdgeKey;
|
||||
int nextEdgeReverseKey;
|
||||
int prevEdgeReverseKey;
|
||||
};
|
||||
|
||||
EdgeIndices::EdgeIndices() :
|
||||
a(0), b(0),
|
||||
edgeIndex(-1),
|
||||
nextEdgeKey(-1),
|
||||
prevEdgeKey(-1),
|
||||
nextEdgeReverseKey(-1),
|
||||
prevEdgeReverseKey(-1) {
|
||||
|
||||
}
|
||||
|
||||
uint8_t getEdgeIndex(std::map<int, EdgeIndices>& edges, int edgeKey) {
|
||||
auto result = edges.find(edgeKey);
|
||||
|
||||
if (result == edges.end()) {
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
return result->second.edgeIndex;
|
||||
}
|
||||
|
||||
std::unique_ptr<StructureDataChunk> calculatePortalSingleSurface(CFileDefinition& fileDefinition, const CollisionQuad& quad, ExtendedMesh& mesh, float scale) {
|
||||
std::unique_ptr<StructureDataChunk> portalSurface(new StructureDataChunk());
|
||||
|
||||
|
@ -47,28 +74,69 @@ std::unique_ptr<StructureDataChunk> calculatePortalSingleSurface(CFileDefinition
|
|||
for (unsigned faceIndex = 0; faceIndex < mesh.mMesh->mNumFaces; ++faceIndex) {
|
||||
aiFace* face = &mesh.mMesh->mFaces[faceIndex];
|
||||
|
||||
std::vector<int> edgeKeys;
|
||||
std::vector<bool> isReverseEdge;
|
||||
|
||||
for (unsigned index = 0; index < face->mNumIndices; ++index) {
|
||||
unsigned currentIndex = face->mIndices[index];
|
||||
unsigned nextIndex = face->mIndices[(index + 1) % face->mNumIndices];
|
||||
|
||||
int key = levelEdgeKey(currentIndex, nextIndex);
|
||||
|
||||
edgeKeys.push_back(key);
|
||||
|
||||
if (edgeUseCount.find(key) == edgeUseCount.end()) {
|
||||
edgeUseCount.insert(std::make_pair(key, 1));
|
||||
EdgeIndices indices = {(uint8_t)currentIndex, (uint8_t)nextIndex};
|
||||
EdgeIndices indices;
|
||||
indices.a = currentIndex;
|
||||
indices.b = nextIndex;
|
||||
edgeDirection.insert(std::make_pair(key, indices));
|
||||
isReverseEdge.push_back(false);
|
||||
edgeOrder.push_back(key);
|
||||
} else {
|
||||
edgeUseCount[key] = edgeUseCount[key] + 1;
|
||||
isReverseEdge.push_back(true);
|
||||
}
|
||||
}
|
||||
|
||||
// connect faces in a loop
|
||||
for (int i = 0; i < (int)edgeKeys.size(); ++i) {
|
||||
int prevKey = edgeKeys[(i + edgeKeys.size() - 1) % edgeKeys.size()];
|
||||
int nextKey = edgeKeys[(i + 1) % edgeKeys.size()];
|
||||
|
||||
EdgeIndices& edge = edgeDirection[edgeKeys[i]];
|
||||
|
||||
if (isReverseEdge[i]) {
|
||||
edge.nextEdgeReverseKey = nextKey;
|
||||
edge.prevEdgeReverseKey = prevKey;
|
||||
} else {
|
||||
edge.nextEdgeKey = nextKey;
|
||||
edge.prevEdgeKey = prevKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// loops go first
|
||||
// edges go first
|
||||
std::sort(edgeOrder.begin(), edgeOrder.end(), [&](int a, int b) -> bool {
|
||||
return edgeUseCount[a] < edgeUseCount[b];
|
||||
int edgeDiff = edgeUseCount[a] - edgeUseCount[b];
|
||||
|
||||
if (edgeDiff != 0) {
|
||||
return edgeDiff < 0;
|
||||
}
|
||||
|
||||
// this is an attempt to make edges that are near each other
|
||||
// show up in memory near each other to improve cache
|
||||
// performance
|
||||
return edgeDirection[a].a < edgeDirection[b].a;
|
||||
});
|
||||
|
||||
int edgeIndex = 0;
|
||||
|
||||
for (auto key : edgeOrder) {
|
||||
edgeDirection[key].edgeIndex = edgeIndex;
|
||||
++edgeIndex;
|
||||
}
|
||||
|
||||
int sideCount = 0;
|
||||
|
||||
std::unique_ptr<StructureDataChunk> edges(new StructureDataChunk());
|
||||
|
@ -82,6 +150,10 @@ std::unique_ptr<StructureDataChunk> calculatePortalSingleSurface(CFileDefinition
|
|||
EdgeIndices indices = edgeDirection[key];
|
||||
edge->AddPrimitive((int)indices.a);
|
||||
edge->AddPrimitive((int)indices.b);
|
||||
edge->AddPrimitive((int)getEdgeIndex(edgeDirection, indices.nextEdgeKey));
|
||||
edge->AddPrimitive((int)getEdgeIndex(edgeDirection, indices.prevEdgeKey));
|
||||
edge->AddPrimitive((int)getEdgeIndex(edgeDirection, indices.nextEdgeReverseKey));
|
||||
edge->AddPrimitive((int)getEdgeIndex(edgeDirection, indices.prevEdgeReverseKey));
|
||||
edges->Add(std::move(edge));
|
||||
}
|
||||
|
||||
|
@ -92,15 +164,11 @@ std::unique_ptr<StructureDataChunk> calculatePortalSingleSurface(CFileDefinition
|
|||
portalSurface->AddPrimitive(verticesName);
|
||||
// edges
|
||||
portalSurface->AddPrimitive(edgesName);
|
||||
// triangles
|
||||
portalSurface->AddPrimitive<const char*>("NULL");
|
||||
|
||||
// sideCount
|
||||
portalSurface->AddPrimitive(sideCount);
|
||||
// edgesCount
|
||||
portalSurface->AddPrimitive(edgeOrder.size());
|
||||
// triangleCount
|
||||
portalSurface->AddPrimitive(0);
|
||||
|
||||
portalSurface->Add(std::unique_ptr<DataChunk>(new StructureDataChunk(quad.edgeA)));
|
||||
portalSurface->Add(std::unique_ptr<DataChunk>(new StructureDataChunk(quad.edgeB)));
|
||||
|
|
|
@ -19,23 +19,19 @@ struct Vector2s16 {
|
|||
struct SurfaceEdge {
|
||||
u8 aIndex;
|
||||
u8 bIndex;
|
||||
};
|
||||
|
||||
struct SurfaceFace {
|
||||
u8 aIndex;
|
||||
u8 bIndex;
|
||||
u8 cIndex;
|
||||
u8 nextEdge;
|
||||
u8 prevEdge;
|
||||
u8 nextEdgeReverse;
|
||||
u8 prevEdgeReverse;
|
||||
};
|
||||
|
||||
struct PortalSurface {
|
||||
struct Vector2s16* vertices;
|
||||
// first sideCount edges are on the side
|
||||
struct SurfaceEdge* edges;
|
||||
struct SurfaceFace* triangles;
|
||||
|
||||
u8 sideCount;
|
||||
u8 edgeCount;
|
||||
u8 triangleCount;
|
||||
|
||||
struct Vector3 right;
|
||||
struct Vector3 up;
|
||||
|
|
Loading…
Reference in a new issue