Allow collision surface to portal surface to be a many to many relationship

This commit is contained in:
James Lambert 2022-07-05 13:57:09 -06:00
parent 5dcef6b458
commit f7167ecd72
8 changed files with 103 additions and 41 deletions

View file

@ -123,16 +123,6 @@ std::unique_ptr<DataChunk> CollisionQuad::Generate() const {
return result;
}
#define FIXED_POINT_PRECISION 8
#define FIXED_POINT_SCALAR (1 << FIXED_POINT_PRECISION)
void CollisionQuad::ToLocalCoords(const aiVector3D& input, short& outX, short& outY) const {
aiVector3D relative = input - corner;
outX = (short)(relative * edgeA * FIXED_POINT_SCALAR + 0.5f);
outY = (short)(relative * edgeB * FIXED_POINT_SCALAR + 0.5f);
}
#define INSIDE_NORMAL_TOLERANCE 0.1f
bool CollisionQuad::IsCoplanar(ExtendedMesh& mesh, float relativeScale) const {

View file

@ -17,8 +17,6 @@ struct CollisionQuad {
std::unique_ptr<DataChunk> Generate() const;
void ToLocalCoords(const aiVector3D& input, short& outX, short& outY) const;
bool IsCoplanar(ExtendedMesh& mesh, float relativeScale) const;
bool IsCoplanar(const aiVector3D& input) const;

View file

@ -48,16 +48,49 @@ uint8_t getEdgeIndex(std::map<int, EdgeIndices>& edges, int edgeKey) {
return result->second.edgeIndex;
}
std::unique_ptr<StructureDataChunk> calculatePortalSingleSurface(CFileDefinition& fileDefinition, const CollisionQuad& quad, StaticMeshInfo& mesh, float scale) {
#define FIXED_POINT_PRECISION 8
#define FIXED_POINT_SCALAR (1 << FIXED_POINT_PRECISION)
void toLocalCoords(const aiVector3D& corner, const aiVector3D& edgeA, const aiVector3D& edgeB, const aiVector3D& input, short& outX, short& outY) {
aiVector3D relative = input - corner;
outX = (short)(relative * edgeA * FIXED_POINT_SCALAR + 0.5f);
outY = (short)(relative * edgeB * FIXED_POINT_SCALAR + 0.5f);
}
std::unique_ptr<StructureDataChunk> calculatePortalSingleSurface(CFileDefinition& fileDefinition, StaticMeshInfo& mesh, float scale) {
std::unique_ptr<StructureDataChunk> portalSurface(new StructureDataChunk());
std::unique_ptr<StructureDataChunk> vertices(new StructureDataChunk());
std::string name(mesh.staticMesh->mMesh->mName.C_Str());
aiVector3D origin = (mesh.staticMesh->bbMin + mesh.staticMesh->bbMax) * 0.5f * scale;
aiVector3D normal;
for (unsigned i = 0; i < mesh.staticMesh->mMesh->mNumVertices; ++i) {
normal = normal + mesh.staticMesh->mMesh->mNormals[i];
}
normal.Normalize();
aiVector3D right;
aiVector3D up;
if (fabsf(normal.z) < 0.7f) {
right = aiVector3D(0.0f, 1.0f, 0.0f) ^ normal;
right.Normalize();
up = normal ^ right;
} else {
right = aiVector3D(1.0f, 0.0f, 0.0f) ^ normal;
right.Normalize();
up = normal ^ right;
}
for (unsigned i = 0; i < mesh.staticMesh->mMesh->mNumVertices; ++i) {
short x, y;
quad.ToLocalCoords(mesh.staticMesh->mMesh->mVertices[i] * scale, x, y);
toLocalCoords(origin, right, up, mesh.staticMesh->mMesh->mVertices[i] * scale, x, y);
std::unique_ptr<StructureDataChunk> vertexWrapperWrapper(new StructureDataChunk());
std::unique_ptr<StructureDataChunk> vertexWrapper(new StructureDataChunk());
@ -180,9 +213,9 @@ std::unique_ptr<StructureDataChunk> calculatePortalSingleSurface(CFileDefinition
// shouldCleanup
portalSurface->AddPrimitive(0);
portalSurface->Add(std::unique_ptr<DataChunk>(new StructureDataChunk(quad.edgeA)));
portalSurface->Add(std::unique_ptr<DataChunk>(new StructureDataChunk(quad.edgeB)));
portalSurface->Add(std::unique_ptr<DataChunk>(new StructureDataChunk(quad.corner)));
portalSurface->Add(std::unique_ptr<DataChunk>(new StructureDataChunk(right)));
portalSurface->Add(std::unique_ptr<DataChunk>(new StructureDataChunk(up)));
portalSurface->Add(std::unique_ptr<DataChunk>(new StructureDataChunk(origin)));
std::string vertexBufferName = fileDefinition.GetVertexBuffer(
mesh.staticMesh,
@ -201,17 +234,39 @@ std::unique_ptr<StructureDataChunk> calculatePortalSingleSurface(CFileDefinition
void generatePortalSurfacesDefinition(const aiScene* scene, CFileDefinition& fileDefinition, StructureDataChunk& levelDef, const CollisionGeneratorOutput& collisionOutput, const StaticGeneratorOutput& staticOutput, const DisplayListSettings& settings) {
int surfaceCount = 0;
std::unique_ptr<StructureDataChunk> portalSurfaceIndices(new StructureDataChunk());
std::unique_ptr<StructureDataChunk> portalMappingRange(new StructureDataChunk());
std::unique_ptr<StructureDataChunk> portalSurfaces(new StructureDataChunk());
std::vector<int> staticToPortableSurfaceMapping;
for (auto mesh : staticOutput.staticMeshes) {
aiMaterial* material = scene->mMaterials[mesh.staticMesh->mMesh->mMaterialIndex];
std::string materialName = ExtendedMesh::GetMaterialName(material);
if (gPortalableSurfaces.find(materialName) == gPortalableSurfaces.end()) {
staticToPortableSurfaceMapping.push_back(-1);
continue;
}
portalSurfaces->Add(std::move(calculatePortalSingleSurface(fileDefinition, mesh, settings.mModelScale)));
staticToPortableSurfaceMapping.push_back(surfaceCount);
++surfaceCount;
}
int mappingIndex = 0;
std::unique_ptr<StructureDataChunk> portalMappingData(new StructureDataChunk());
for (auto& collision : collisionOutput.quads) {
int startSurfaceCount = surfaceCount;
int startMappingIndex = mappingIndex;
aiAABB collisionWithPadding = collision.BoundingBox();
collisionWithPadding.mMin = collisionWithPadding.mMin - aiVector3D(0.1f, 0.1f, 0.1f);
collisionWithPadding.mMax = collisionWithPadding.mMax + aiVector3D(0.1f, 0.1f, 0.1f);
for (auto mesh : staticOutput.staticMeshes) {
for (std::size_t staticMeshIndex = 0; staticMeshIndex < staticOutput.staticMeshes.size(); ++staticMeshIndex) {
const StaticMeshInfo& mesh = staticOutput.staticMeshes[staticMeshIndex];
aiMaterial* material = scene->mMaterials[mesh.staticMesh->mMesh->mMaterialIndex];
std::string materialName = ExtendedMesh::GetMaterialName(material);
@ -230,14 +285,19 @@ void generatePortalSurfacesDefinition(const aiScene* scene, CFileDefinition& fil
continue;
}
portalSurfaces->Add(std::move(calculatePortalSingleSurface(fileDefinition, collision, mesh, settings.mModelScale)));
++surfaceCount;
portalMappingData->AddPrimitive(staticToPortableSurfaceMapping[staticMeshIndex]);
++mappingIndex;
}
if (mappingIndex > 255) {
std::cerr << "Mapping index larger than 255" << std::endl;
exit(1);
}
std::unique_ptr<StructureDataChunk> indices(new StructureDataChunk());
indices->AddPrimitive(startSurfaceCount);
indices->AddPrimitive(surfaceCount);
portalSurfaceIndices->Add(std::move(indices));
indices->AddPrimitive(startMappingIndex);
indices->AddPrimitive(mappingIndex);
portalMappingRange->Add(std::move(indices));
}
std::string surfacesName = fileDefinition.GetUniqueName("portal_surfaces");
@ -246,10 +306,19 @@ void generatePortalSurfacesDefinition(const aiScene* scene, CFileDefinition& fil
fileDefinition.AddDefinition(std::move(portalSurfacesDef));
std::string surfaceMappingName = fileDefinition.GetUniqueName("collider_to_surface");
fileDefinition.AddDefinition(std::unique_ptr<FileDefinition>(new DataFileDefinition("struct PortalSurfaceMapping", surfaceMappingName, true, "_geo", std::move(portalSurfaceIndices))));
fileDefinition.AddDefinition(std::unique_ptr<FileDefinition>(new DataFileDefinition("struct PortalSurfaceMappingRange", surfaceMappingName, true, "_geo", std::move(portalMappingRange))));
std::string portalSurfaceMappingIndices = fileDefinition.AddDataDefinition(
"mapping_indices",
"u8",
true,
"_geo",
std::move(portalMappingData)
);
levelDef.AddPrimitive("portalSurfaces", surfacesName);
levelDef.AddPrimitive("portalSurfaceMapping", surfaceMappingName);
levelDef.AddPrimitive("portalSurfaceMappingRange", surfaceMappingName);
levelDef.AddPrimitive("portalSurfaceMappingIndices", portalSurfaceMappingIndices);
levelDef.AddPrimitive("portalSurfaceCount", surfaceCount);
}

View file

@ -136,7 +136,8 @@ struct LevelDefinition {
struct BoundingBoxs16* staticBoundingBoxes;
struct PortalSurface* portalSurfaces;
// maps index of a collisionQuads to indices in portalSurfaces
struct PortalSurfaceMapping* portalSurfaceMapping;
struct PortalSurfaceMappingRange* portalSurfaceMappingRange;
u8* portalSurfaceMappingIndices;
struct Trigger* triggers;
struct Cutscene* cutscenes;
struct Location* locations;

View file

@ -40,7 +40,7 @@ struct PortalSurface {
Gfx* triangles;
};
struct PortalSurfaceMapping {
struct PortalSurfaceMappingRange {
u8 minPortalIndex;
u8 maxPortalIndex;
};

View file

@ -261,19 +261,19 @@ enum IntersectionType portalSurfaceIntersect(struct Vector2s16* pointA, struct V
if (directionDot > 0) {
// pointing towards b
if (vector2s16DistSqr(edgeB, pointA) >= vector2s16MagSqr(pointDir)) {
// edge ends first
*intersection = *edgeB;
} else {
// point ends first
vector2s16Add(pointA, pointDir, intersection);
} else {
// edge ends first
*intersection = *edgeB;
}
} else {
if (vector2s16MagSqr(&originOffset) >= vector2s16MagSqr(pointDir)) {
// edge ends first
*intersection = *edgeA;
} else {
// point ends first
vector2s16Add(pointA, pointDir, intersection);
} else {
// edge ends first
*intersection = *edgeA;
}
}
@ -293,8 +293,10 @@ enum IntersectionType portalSurfaceIntersect(struct Vector2s16* pointA, struct V
return IntersectionTypeNone;
}
intersection->x = (short)((s64)pointDir->x * (s64)pointLerp / (s64)denominator) + pointA->x;
intersection->y = (short)((s64)pointDir->y * (s64)pointLerp / (s64)denominator) + pointA->y;
s64 halfDenominator = denominator >> 1;
intersection->x = (short)(((s64)edgeDir.x * (s64)edgeLerp + halfDenominator) / (s64)denominator) + edgeA->x;
intersection->y = (short)(((s64)edgeDir.y * (s64)edgeLerp + halfDenominator) / (s64)denominator) + edgeA->y;
return IntersectionTypePoint;
}

View file

@ -271,14 +271,16 @@ void sceneUpdate(struct Scene* scene) {
}
int sceneOpenPortal(struct Scene* scene, struct Transform* at, int portalIndex, int quadIndex, int roomIndex) {
struct PortalSurfaceMapping surfaceMapping = gCurrentLevel->portalSurfaceMapping[quadIndex];
struct PortalSurfaceMappingRange surfaceMapping = gCurrentLevel->portalSurfaceMappingRange[quadIndex];
for (int i = surfaceMapping.minPortalIndex; i < surfaceMapping.maxPortalIndex; ++i) {
struct PortalSurface* existingSurface = portalSurfaceGetOriginalSurface(i, portalIndex);
for (int indexIndex = surfaceMapping.minPortalIndex; indexIndex < surfaceMapping.maxPortalIndex; ++indexIndex) {
int surfaceIndex = gCurrentLevel->portalSurfaceMappingIndices[indexIndex];
struct PortalSurface* existingSurface = portalSurfaceGetOriginalSurface(surfaceIndex, portalIndex);
struct PortalSurface newSurface;
if (portalSurfaceGenerate(existingSurface, at, &newSurface)) {
portalSurfaceReplace(i, roomIndex, portalIndex, &newSurface);
portalSurfaceReplace(surfaceIndex, roomIndex, portalIndex, &newSurface);
soundPlayerPlay(soundsPortalOpen2, 1.0f, 1.0f, &at->position);