Allow collision surface to portal surface to be a many to many relationship
This commit is contained in:
parent
5dcef6b458
commit
f7167ecd72
Binary file not shown.
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -40,7 +40,7 @@ struct PortalSurface {
|
|||
Gfx* triangles;
|
||||
};
|
||||
|
||||
struct PortalSurfaceMapping {
|
||||
struct PortalSurfaceMappingRange {
|
||||
u8 minPortalIndex;
|
||||
u8 maxPortalIndex;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue