Refactor level generation code to be function instead of object oriented

This commit is contained in:
James Lambert 2022-06-04 23:06:18 -06:00
parent 8083c5082a
commit 6d1961fb55
19 changed files with 266 additions and 315 deletions

View file

@ -147,34 +147,31 @@ int main(int argc, char *argv[]) {
if (args.mIsLevel) {
NodeGroups nodesByGroup(scene);
std::cout << "Grouping objects by room" << std::endl;
RoomGenerator roomGenerator(settings);
roomGenerator.TraverseScene(scene);
roomGenerator.GenerateDefinitions(scene, fileDef);
auto roomOutput = generateRooms(scene, fileDef, settings, nodesByGroup);
std::cout << "Generating collider definitions" << std::endl;
CollisionGenerator colliderGenerator(settings, roomGenerator.GetOutput());
colliderGenerator.TraverseScene(scene);
colliderGenerator.GenerateDefinitions(scene, fileDef);
auto collisionOutput = generateCollision(scene, fileDef, settings, *roomOutput, nodesByGroup);
std::cout << "Generating static definitions" << std::endl;
StaticGenerator staticGenerator(settings, roomGenerator.GetOutput());
staticGenerator.TraverseScene(scene);
staticGenerator.GenerateDefinitions(scene, fileDef);
auto staticOutput = generateStatic(scene, fileDef, settings, *roomOutput, nodesByGroup);
TriggerGenerator triggerGenerator(settings, roomGenerator.GetOutput());
triggerGenerator.TraverseScene(scene);
triggerGenerator.GenerateDefinitions(scene, fileDef);
auto triggerOutput = generateTriggers(scene, fileDef, settings, *roomOutput, nodesByGroup);
std::cout << "Generating level definitions" << std::endl;
LevelGenerator levelGenerator(
generateLevel(
scene,
fileDef,
settings,
staticGenerator.GetOutput(),
colliderGenerator.GetOutput(),
triggerGenerator.GetOutput(),
roomGenerator.GetOutput()
*staticOutput,
*collisionOutput,
*triggerOutput,
*roomOutput
);
levelGenerator.GenerateDefinitions(scene, fileDef);
nodesByGroup.PrintUnusedTypes();
}
std::cout << "Writing output" << std::endl;

View file

@ -16,7 +16,7 @@ DisplayListSettings::DisplayListSettings():
mIncludeCulling(true) {
}
aiMatrix4x4 DisplayListSettings::CreateGlobalTransform() {
aiMatrix4x4 DisplayListSettings::CreateGlobalTransform() const {
aiMatrix4x4 scale;
aiMatrix4x4::Scaling(aiVector3D(1, 1, 1) * mGraphicsScale, scale);
aiMatrix4x4 rotation(mRotateModel.GetMatrix());
@ -24,7 +24,7 @@ aiMatrix4x4 DisplayListSettings::CreateGlobalTransform() {
return rotation * scale;
}
aiMatrix4x4 DisplayListSettings::CreateCollisionTransform() {
aiMatrix4x4 DisplayListSettings::CreateCollisionTransform() const {
aiMatrix4x4 scale;
aiMatrix4x4::Scaling(aiVector3D(1, 1, 1) * mCollisionScale, scale);
aiMatrix4x4 rotation(mRotateModel.GetMatrix());

View file

@ -25,8 +25,8 @@ struct DisplayListSettings {
bool mExportGeometry;
bool mIncludeCulling;
aiMatrix4x4 CreateGlobalTransform();
aiMatrix4x4 CreateCollisionTransform();
aiMatrix4x4 CreateGlobalTransform() const;
aiMatrix4x4 CreateCollisionTransform() const;
};
#endif

View file

@ -5,16 +5,6 @@
#include <algorithm>
CollisionGenerator::CollisionGenerator(const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput) :
DefinitionGenerator(),
mSettings(settings),
mRoomOutput(roomOutput) {}
bool CollisionGenerator::ShouldIncludeNode(aiNode* node) {
return StartsWith(node->mName.C_Str(), "@collision ");
}
CollisionGrid::CollisionGrid(const aiAABB& boundaries) {
x = floor(boundaries.mMin.x);
z = floor(boundaries.mMin.z);
@ -50,12 +40,14 @@ void CollisionGrid::AddToCells(const aiAABB& box, short value) {
}
}
void CollisionGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition) {
std::shared_ptr<CollisionGeneratorOutput> generateCollision(const aiScene* scene, CFileDefinition& fileDefinition, const DisplayListSettings& settings, RoomGeneratorOutput& roomOutput, NodeGroups& nodeGroups) {
std::shared_ptr<CollisionGeneratorOutput> output(new CollisionGeneratorOutput());
std::unique_ptr<StructureDataChunk> collidersChunk(new StructureDataChunk());
std::unique_ptr<StructureDataChunk> colliderTypeChunk(new StructureDataChunk());
std::unique_ptr<StructureDataChunk> collisionObjectChunk(new StructureDataChunk());
aiMatrix4x4 globalTransform = mSettings.CreateCollisionTransform();
aiMatrix4x4 globalTransform = settings.CreateCollisionTransform();
int meshCount = 0;
@ -63,20 +55,22 @@ void CollisionGenerator::GenerateDefinitions(const aiScene* scene, CFileDefiniti
std::string colliderTypesName = fileDefinition.GetUniqueName("collider_types");
std::string collisionObjectsName = fileDefinition.GetUniqueName("collision_objects");
sortNodesByRoom(mIncludedNodes, mRoomOutput);
std::vector<NodeWithArguments> nodes = nodeGroups.NodesForType("@collision");
sortNodesWithArgsByRoom(nodes, roomOutput);
std::vector<aiAABB> roomBoxes;
std::vector<int> quadRooms;
for (int i = 0; i < mRoomOutput.roomCount; ++i) {
for (int i = 0; i < roomOutput.roomCount; ++i) {
roomBoxes.push_back(aiAABB());
}
for (auto node : mIncludedNodes) {
for (unsigned i = 0; i < node->mNumMeshes; ++i) {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
for (auto nodeInfo : nodes) {
for (unsigned i = 0; i < nodeInfo.node->mNumMeshes; ++i) {
aiMesh* mesh = scene->mMeshes[nodeInfo.node->mMeshes[i]];
CollisionQuad collider(mesh, globalTransform * node->mTransformation);
CollisionQuad collider(mesh, globalTransform * nodeInfo.node->mTransformation);
collidersChunk->Add(std::move(collider.Generate()));
std::unique_ptr<StructureDataChunk> colliderType(new StructureDataChunk());
@ -94,9 +88,9 @@ void CollisionGenerator::GenerateDefinitions(const aiScene* scene, CFileDefiniti
collisionObjectChunk->Add(std::move(collisionObject));
mOutput.quads.push_back(collider);
output->quads.push_back(collider);
int room = mRoomOutput.RoomForNode(node);
int room = roomOutput.RoomForNode(nodeInfo.node);
quadRooms.push_back(room);
aiAABB bb = collider.BoundingBox();
@ -113,13 +107,13 @@ void CollisionGenerator::GenerateDefinitions(const aiScene* scene, CFileDefiniti
}
}
for (int i = 0; i < mRoomOutput.roomCount; ++i) {
mOutput.roomGrids.push_back(CollisionGrid(roomBoxes[i]));
for (int i = 0; i < roomOutput.roomCount; ++i) {
output->roomGrids.push_back(CollisionGrid(roomBoxes[i]));
}
int quadIndex = 0;
for (auto& quad : mOutput.quads) {
mOutput.roomGrids[quadRooms[quadIndex]].AddToCells(quad.BoundingBox(), quadIndex);
for (auto& quad : output->quads) {
output->roomGrids[quadRooms[quadIndex]].AddToCells(quad.BoundingBox(), quadIndex);
quadIndex++;
}
@ -155,9 +149,7 @@ void CollisionGenerator::GenerateDefinitions(const aiScene* scene, CFileDefiniti
fileDefinition.AddMacro(fileDefinition.GetMacroName("QUAD_COLLIDERS_COUNT"), std::to_string(meshCount));
mOutput.quadsName = collisionObjectsName;
}
output->quadsName = collisionObjectsName;
const CollisionGeneratorOutput& CollisionGenerator::GetOutput() const {
return mOutput;
return output;
}

View file

@ -27,19 +27,6 @@ struct CollisionGeneratorOutput {
std::vector<CollisionGrid> roomGrids;
};
class CollisionGenerator : public DefinitionGenerator {
public:
CollisionGenerator(const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput);
virtual bool ShouldIncludeNode(aiNode* node);
virtual void GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition);
const CollisionGeneratorOutput& GetOutput() const;
private:
DisplayListSettings mSettings;
RoomGeneratorOutput mRoomOutput;
CollisionGeneratorOutput mOutput;
};
std::shared_ptr<CollisionGeneratorOutput> generateCollision(const aiScene* scene, CFileDefinition& fileDefinition, const DisplayListSettings& settings, RoomGeneratorOutput& roomOutput, NodeGroups& nodeGroups);
#endif

View file

@ -104,7 +104,7 @@ CollisionQuad::CollisionQuad(aiMesh* mesh, const aiMatrix4x4& transform) {
}
}
std::unique_ptr<DataChunk> CollisionQuad::Generate() {
std::unique_ptr<DataChunk> CollisionQuad::Generate() const {
std::unique_ptr<StructureDataChunk> result(new StructureDataChunk());
result->Add(std::unique_ptr<DataChunk>(new StructureDataChunk(corner)));
@ -126,7 +126,7 @@ std::unique_ptr<DataChunk> CollisionQuad::Generate() {
#define FIXED_POINT_PRECISION 8
#define FIXED_POINT_SCALAR (1 << FIXED_POINT_PRECISION)
void CollisionQuad::ToLocalCoords(const aiVector3D& input, short& outX, short& outY) {
void CollisionQuad::ToLocalCoords(const aiVector3D& input, short& outX, short& outY) const {
aiVector3D relative = input - corner;
outX = (short)(relative * edgeA * FIXED_POINT_SCALAR + 0.5f);

View file

@ -14,9 +14,9 @@ struct CollisionQuad {
float edgeBLength;
aiVector3D normal;
std::unique_ptr<DataChunk> Generate();
std::unique_ptr<DataChunk> Generate() const;
void ToLocalCoords(const aiVector3D& input, short& outX, short& outY);
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

@ -1,5 +1,9 @@
#include "DefinitionGenerator.h"
#include <iostream>
#include "../StringUtils.h"
DefinitionGenerator::DefinitionGenerator() {}
DefinitionGenerator::~DefinitionGenerator() {}
@ -19,6 +23,36 @@ void DefinitionGenerator::TraverseScene(const aiScene* scene) {
void DefinitionGenerator::BeforeTraversal(const aiScene* scene) {}
NodeGroups::NodeGroups(const aiScene* scene) {
forEachNode(scene->mRootNode, [&](aiNode* node) -> void {
if (node->mName.data[0] == '@') {
AddNode(node);
}
});
}
std::vector<NodeWithArguments>& NodeGroups::NodesForType(const std::string& typeName) {
mTypesReferenced.insert(typeName);
return mNodesByType[typeName];
}
void NodeGroups::PrintUnusedTypes() {
for (auto& byType : mNodesByType) {
if (mTypesReferenced.find(byType.first) == mTypesReferenced.end()) {
std::cout << "The node type " << byType.first << " was never referenced." << std::endl;
}
}
}
void NodeGroups::AddNode(aiNode* node) {
NodeWithArguments result;
SplitString(node->mName.C_Str(), ' ', result.arguments);
std::string typeName = result.arguments[0];
result.node = node;
result.arguments.erase(result.arguments.begin());
mNodesByType[typeName].push_back(result);
}
void forEachNode(aiNode* node, const std::function<void(aiNode*)>& callback) {
if (!node) {

View file

@ -4,7 +4,10 @@
#include <assimp/scene.h>
#include <vector>
#include <map>
#include <string>
#include <functional>
#include <set>
#include "../CFileDefinition.h"
@ -23,6 +26,24 @@ protected:
std::vector<aiNode*> mIncludedNodes;
};
struct NodeWithArguments {
aiNode* node;
std::vector<std::string> arguments;
};
class NodeGroups {
public:
NodeGroups(const aiScene* scene);
std::vector<NodeWithArguments>& NodesForType(const std::string& typeName);
void PrintUnusedTypes();
private:
void AddNode(aiNode* node);
std::map<std::string, std::vector<NodeWithArguments>> mNodesByType;
std::set<std::string> mTypesReferenced;
};
void forEachNode(aiNode* node, const std::function<void(aiNode*)>& callback);
#endif

View file

@ -11,20 +11,6 @@ std::set<std::string> gPortalableSurfaces = {
"concrete_modular_floor001a",
};
LevelGenerator::LevelGenerator(
const DisplayListSettings& settings,
const StaticGeneratorOutput& staticOutput,
const CollisionGeneratorOutput& collisionOutput,
const TriggerGeneratorOutput& triggerOutput,
const RoomGeneratorOutput& roomOutput
) :
mSettings(settings),
mStaticOutput(staticOutput),
mCollisionOutput(collisionOutput),
mTriggerOutput(triggerOutput),
mRoomOutput(roomOutput) {}
int levelEdgeKey(int a, int b) {
return (std::max(a, b) << 8) | std::min(a, b);
}
@ -34,7 +20,7 @@ struct EdgeIndices {
uint8_t b;
};
std::unique_ptr<StructureDataChunk> LevelGenerator::CalculatePortalSingleSurface(CFileDefinition& fileDefinition, CollisionQuad& quad, ExtendedMesh& mesh, float scale) {
std::unique_ptr<StructureDataChunk> calculatePortalSingleSurface(CFileDefinition& fileDefinition, const CollisionQuad& quad, ExtendedMesh& mesh, float scale) {
std::unique_ptr<StructureDataChunk> portalSurface(new StructureDataChunk());
std::unique_ptr<StructureDataChunk> vertices(new StructureDataChunk());
@ -122,20 +108,20 @@ std::unique_ptr<StructureDataChunk> LevelGenerator::CalculatePortalSingleSurface
return portalSurface;
}
int LevelGenerator::CalculatePortalSurfaces(const aiScene* scene, CFileDefinition& fileDefinition, std::string& surfacesName, std::string& surfaceMappingName) {
int calculatePortalSurfaces(const aiScene* scene, CFileDefinition& fileDefinition, const CollisionGeneratorOutput& collisionOutput, const StaticGeneratorOutput& staticOutput, const DisplayListSettings& settings, std::string& surfacesName, std::string& surfaceMappingName) {
int surfaceCount = 0;
std::unique_ptr<StructureDataChunk> portalSurfaceIndices(new StructureDataChunk());
std::unique_ptr<StructureDataChunk> portalSurfaces(new StructureDataChunk());
for (auto& collision : mCollisionOutput.quads) {
for (auto& collision : collisionOutput.quads) {
int startSurfaceCount = surfaceCount;
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 : mStaticOutput.staticMeshes) {
for (auto mesh : staticOutput.staticMeshes) {
aiMaterial* material = scene->mMaterials[mesh->mMesh->mMaterialIndex];
std::string materialName = ExtendedMesh::GetMaterialName(material);
@ -144,9 +130,9 @@ int LevelGenerator::CalculatePortalSurfaces(const aiScene* scene, CFileDefinitio
continue;
}
aiAABB meshBB(mesh->bbMin * mSettings.mCollisionScale, mesh->bbMax * mSettings.mCollisionScale);
aiAABB meshBB(mesh->bbMin * settings.mCollisionScale, mesh->bbMax * settings.mCollisionScale);
if (!collision.IsCoplanar(*mesh, mSettings.mCollisionScale)) {
if (!collision.IsCoplanar(*mesh, settings.mCollisionScale)) {
continue;
}
@ -154,7 +140,7 @@ int LevelGenerator::CalculatePortalSurfaces(const aiScene* scene, CFileDefinitio
continue;
}
portalSurfaces->Add(std::move(CalculatePortalSingleSurface(fileDefinition, collision, *mesh, mSettings.mCollisionScale)));
portalSurfaces->Add(std::move(calculatePortalSingleSurface(fileDefinition, collision, *mesh, settings.mCollisionScale)));
++surfaceCount;
}
@ -175,19 +161,19 @@ int LevelGenerator::CalculatePortalSurfaces(const aiScene* scene, CFileDefinitio
return surfaceCount;
}
void LevelGenerator::CalculateBoundingBoxes(const aiScene* scene, CFileDefinition& fileDefinition, std::string& boundingBoxesName) {
void calculateBoundingBoxes(const aiScene* scene, CFileDefinition& fileDefinition, const StaticGeneratorOutput& staticOutput, const DisplayListSettings& settings, std::string& boundingBoxesName) {
std::unique_ptr<StructureDataChunk> boundingBoxes(new StructureDataChunk());
for (auto& mesh : mStaticOutput.staticMeshes) {
for (auto& mesh : staticOutput.staticMeshes) {
std::unique_ptr<StructureDataChunk> sphere(new StructureDataChunk());
sphere->AddPrimitive((short)(mesh->bbMin.x * mSettings.mGraphicsScale + 0.5f));
sphere->AddPrimitive((short)(mesh->bbMin.y * mSettings.mGraphicsScale + 0.5f));
sphere->AddPrimitive((short)(mesh->bbMin.z * mSettings.mGraphicsScale + 0.5f));
sphere->AddPrimitive((short)(mesh->bbMin.x * settings.mGraphicsScale + 0.5f));
sphere->AddPrimitive((short)(mesh->bbMin.y * settings.mGraphicsScale + 0.5f));
sphere->AddPrimitive((short)(mesh->bbMin.z * settings.mGraphicsScale + 0.5f));
sphere->AddPrimitive((short)(mesh->bbMax.x * mSettings.mGraphicsScale + 0.5f));
sphere->AddPrimitive((short)(mesh->bbMax.y * mSettings.mGraphicsScale + 0.5f));
sphere->AddPrimitive((short)(mesh->bbMax.z * mSettings.mGraphicsScale + 0.5f));
sphere->AddPrimitive((short)(mesh->bbMax.x * settings.mGraphicsScale + 0.5f));
sphere->AddPrimitive((short)(mesh->bbMax.y * settings.mGraphicsScale + 0.5f));
sphere->AddPrimitive((short)(mesh->bbMax.z * settings.mGraphicsScale + 0.5f));
boundingBoxes->Add(std::move(sphere));
}
@ -197,10 +183,10 @@ void LevelGenerator::CalculateBoundingBoxes(const aiScene* scene, CFileDefinitio
fileDefinition.AddDefinition(std::move(boundingBoxDef));
}
void LevelGenerator::CalculateTriggers(const aiScene* scene, CFileDefinition& fileDefinition, std::string& triggersName) {
void calculateTriggers(const aiScene* scene, CFileDefinition& fileDefinition, const TriggerGeneratorOutput& triggerOutput, std::string& triggersName) {
std::unique_ptr<StructureDataChunk> triggers(new StructureDataChunk());
for (auto& trigger : mTriggerOutput.triggers) {
for (auto& trigger : triggerOutput.triggers) {
std::unique_ptr<StructureDataChunk> triggerData(new StructureDataChunk());
std::unique_ptr<StructureDataChunk> cutsceneDef(new StructureDataChunk());
@ -219,12 +205,12 @@ void LevelGenerator::CalculateTriggers(const aiScene* scene, CFileDefinition& fi
fileDefinition.AddDefinition(std::move(triggersDef));
}
void LevelGenerator::CalculateLocations(const aiScene* scene, CFileDefinition& fileDefinition, std::string& locationsName) {
aiMatrix4x4 baseTransfrom = mSettings.CreateCollisionTransform();
void calculateLocations(const aiScene* scene, CFileDefinition& fileDefinition, const RoomGeneratorOutput& roomOuptut, const DisplayListSettings& settings, std::string& locationsName) {
aiMatrix4x4 baseTransfrom = settings.CreateCollisionTransform();
std::unique_ptr<StructureDataChunk> locations(new StructureDataChunk());
for (auto& location : mRoomOutput.namedLocations) {
for (auto& location : roomOuptut.namedLocations) {
aiMatrix4x4 nodeTransform = baseTransfrom * location.node->mTransformation;
aiVector3D position;
@ -240,7 +226,9 @@ void LevelGenerator::CalculateLocations(const aiScene* scene, CFileDefinition& f
transform->Add(std::unique_ptr<DataChunk>(new StructureDataChunk(scale)));
locationData->Add(std::move(transform));
locationData->AddPrimitive(mRoomOutput.roomIndexMapping[location.node]);
auto roomIndex = roomOuptut.roomIndexMapping.find(location.node);
locationData->AddPrimitive(roomIndex == roomOuptut.roomIndexMapping.end() ? 0 : roomIndex->second);
locations->Add(std::move(locationData));
}
@ -250,10 +238,10 @@ void LevelGenerator::CalculateLocations(const aiScene* scene, CFileDefinition& f
fileDefinition.AddDefinition(std::move(triggersDef));
}
void LevelGenerator::CalculateDoorwaysAndRooms(const aiScene* scene, CFileDefinition& fileDefinition, std::string& doorwaysName, std::string& roomsName) {
void calculateDoorwaysAndRooms(const aiScene* scene, CFileDefinition& fileDefinition, const RoomGeneratorOutput& roomOutput, const CollisionGeneratorOutput& collisionOutput, std::string& doorwaysName, std::string& roomsName) {
std::vector<std::vector<int>> roomDoorways;
for (int i = 0; i < mRoomOutput.roomCount; ++i) {
for (int i = 0; i < roomOutput.roomCount; ++i) {
roomDoorways.push_back(std::vector<int>());
}
@ -261,7 +249,7 @@ void LevelGenerator::CalculateDoorwaysAndRooms(const aiScene* scene, CFileDefini
std::unique_ptr<StructureDataChunk> doorways(new StructureDataChunk());
for (auto& doorway : mRoomOutput.doorways) {
for (auto& doorway : roomOutput.doorways) {
roomDoorways[doorway.roomA].push_back(doorwayIndex);
roomDoorways[doorway.roomB].push_back(doorwayIndex);
@ -284,7 +272,7 @@ void LevelGenerator::CalculateDoorwaysAndRooms(const aiScene* scene, CFileDefini
std::unique_ptr<StructureDataChunk> rooms(new StructureDataChunk());
for (int i = 0; i < mRoomOutput.roomCount; ++i) {
for (int i = 0; i < roomOutput.roomCount; ++i) {
std::unique_ptr<StructureDataChunk> doorwayList(new StructureDataChunk());
for (auto doorway : roomDoorways[i]) {
@ -304,7 +292,7 @@ void LevelGenerator::CalculateDoorwaysAndRooms(const aiScene* scene, CFileDefini
int startIndex = 0;
for (auto& zRange : mCollisionOutput.roomGrids[i].cells) {
for (auto& zRange : collisionOutput.roomGrids[i].cells) {
for (auto& indices : zRange) {
for (auto index : indices) {
quadIndices->AddPrimitive(index);
@ -341,10 +329,10 @@ void LevelGenerator::CalculateDoorwaysAndRooms(const aiScene* scene, CFileDefini
std::unique_ptr<StructureDataChunk> room(new StructureDataChunk());
room->AddPrimitive(std::move(quadIndicesName));
room->AddPrimitive(std::move(cellContentsName));
room->AddPrimitive(mCollisionOutput.roomGrids[i].spanX);
room->AddPrimitive(mCollisionOutput.roomGrids[i].spanZ);
room->AddPrimitive(mCollisionOutput.roomGrids[i].x);
room->AddPrimitive(mCollisionOutput.roomGrids[i].z);
room->AddPrimitive(collisionOutput.roomGrids[i].spanX);
room->AddPrimitive(collisionOutput.roomGrids[i].spanZ);
room->AddPrimitive(collisionOutput.roomGrids[i].x);
room->AddPrimitive(collisionOutput.roomGrids[i].z);
room->AddPrimitive(std::move(doorwayListName));
room->AddPrimitive(roomDoorways[i].size());
rooms->Add(std::move(room));
@ -359,12 +347,12 @@ void LevelGenerator::CalculateDoorwaysAndRooms(const aiScene* scene, CFileDefini
);
}
void LevelGenerator::CalculateDoors(const aiScene* scene, CFileDefinition& fileDefinition, std::string& doorsName) {
void calculateDoors(const aiScene* scene, CFileDefinition& fileDefinition, const RoomGeneratorOutput& roomOutput, const DisplayListSettings& settings, std::string& doorsName) {
std::unique_ptr<StructureDataChunk> doors(new StructureDataChunk());
aiMatrix4x4 baseTransform = mSettings.CreateCollisionTransform();
aiMatrix4x4 baseTransform = settings.CreateCollisionTransform();
for (auto& door : mRoomOutput.doors) {
for (auto& door : roomOutput.doors) {
std::unique_ptr<StructureDataChunk> doorData(new StructureDataChunk());
aiVector3D pos;
aiQuaternion rot;
@ -385,33 +373,40 @@ void LevelGenerator::CalculateDoors(const aiScene* scene, CFileDefinition& fileD
);
}
void LevelGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition) {
void generateLevel(
const aiScene* scene,
CFileDefinition& fileDefinition,
const DisplayListSettings& settings,
const StaticGeneratorOutput& staticOutput,
const CollisionGeneratorOutput& collisionOutput,
const TriggerGeneratorOutput& triggerOutput,
const RoomGeneratorOutput& roomOutput
) {
std::string portalSurfaces;
std::string portalSurfaceMapping;
int portalSurfacesCount = CalculatePortalSurfaces(scene, fileDefinition, portalSurfaces, portalSurfaceMapping);
int portalSurfacesCount = calculatePortalSurfaces(scene, fileDefinition, collisionOutput, staticOutput, settings, portalSurfaces, portalSurfaceMapping);
std::string boundingBoxes;
CalculateBoundingBoxes(scene, fileDefinition, boundingBoxes);
calculateBoundingBoxes(scene, fileDefinition, staticOutput, settings, boundingBoxes);
std::string triggers;
CalculateTriggers(scene, fileDefinition, triggers);
calculateTriggers(scene, fileDefinition, triggerOutput, triggers);
std::string locations;
CalculateLocations(scene, fileDefinition, locations);
calculateLocations(scene, fileDefinition, roomOutput, settings, locations);
std::string doorways;
std::string rooms;
CalculateDoorwaysAndRooms(scene, fileDefinition, doorways, rooms);
calculateDoorwaysAndRooms(scene, fileDefinition, roomOutput, collisionOutput, doorways, rooms);
std::string doors;
CalculateDoors(scene, fileDefinition, doors);
calculateDoors(scene, fileDefinition, roomOutput, settings, doors);
std::unique_ptr<StructureDataChunk> levelDef(new StructureDataChunk());
levelDef->AddPrimitive("collisionQuads", mCollisionOutput.quadsName);
levelDef->AddPrimitive("staticContent", mStaticOutput.staticContentName);
levelDef->AddPrimitive("roomStaticMapping", mStaticOutput.roomMappingName);
levelDef->AddPrimitive("collisionQuads", collisionOutput.quadsName);
levelDef->AddPrimitive("staticContent", staticOutput.staticContentName);
levelDef->AddPrimitive("roomStaticMapping", staticOutput.roomMappingName);
levelDef->AddPrimitive("staticBoundingBoxes", boundingBoxes);
levelDef->AddPrimitive("portalSurfaces", portalSurfaces);
levelDef->AddPrimitive("portalSurfaceMapping", portalSurfaceMapping);
@ -421,18 +416,18 @@ void LevelGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition&
std::unique_ptr<StructureDataChunk> worldDef(new StructureDataChunk());
worldDef->AddPrimitive("rooms", rooms);
worldDef->AddPrimitive("doorways", doorways);
worldDef->AddPrimitive("roomCount", mRoomOutput.roomCount);
worldDef->AddPrimitive("doorwayCount", mRoomOutput.doorways.size());
worldDef->AddPrimitive("roomCount", roomOutput.roomCount);
worldDef->AddPrimitive("doorwayCount", roomOutput.doorways.size());
levelDef->Add("world", std::move(worldDef));
levelDef->AddPrimitive("doors", doors);
levelDef->AddPrimitive("collisionQuadCount", mCollisionOutput.quads.size());
levelDef->AddPrimitive("staticContentCount", mStaticOutput.staticMeshes.size());
levelDef->AddPrimitive("collisionQuadCount", collisionOutput.quads.size());
levelDef->AddPrimitive("staticContentCount", staticOutput.staticMeshes.size());
levelDef->AddPrimitive("portalSurfaceCount", portalSurfacesCount);
levelDef->AddPrimitive("triggerCount", mTriggerOutput.triggers.size());
levelDef->AddPrimitive("locationCount", mRoomOutput.namedLocations.size());
levelDef->AddPrimitive("doorCount", mRoomOutput.doors.size());
levelDef->AddPrimitive("startLocation", mRoomOutput.FindLocationIndex("start"));
levelDef->AddPrimitive("triggerCount", triggerOutput.triggers.size());
levelDef->AddPrimitive("locationCount", roomOutput.namedLocations.size());
levelDef->AddPrimitive("doorCount", roomOutput.doors.size());
levelDef->AddPrimitive("startLocation", roomOutput.FindLocationIndex("start"));
fileDefinition.AddDefinition(std::unique_ptr<FileDefinition>(new DataFileDefinition("struct LevelDefinition", fileDefinition.GetUniqueName("level"), false, "_geo", std::move(levelDef))));
}

View file

@ -8,36 +8,14 @@
#include "TriggerGenerator.h"
#include "RoomGenerator.h"
class LevelGenerator {
public:
LevelGenerator(
void generateLevel(
const aiScene* scene,
CFileDefinition& fileDefinition,
const DisplayListSettings& settings,
const StaticGeneratorOutput& staticOutput,
const CollisionGeneratorOutput& collisionOutput,
const TriggerGeneratorOutput& triggerOutput,
const RoomGeneratorOutput& roomOutput
);
void GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition);
private:
DisplayListSettings mSettings;
StaticGeneratorOutput mStaticOutput;
CollisionGeneratorOutput mCollisionOutput;
TriggerGeneratorOutput mTriggerOutput;
RoomGeneratorOutput mRoomOutput;
std::unique_ptr<StructureDataChunk> CalculatePortalSingleSurface(CFileDefinition& fileDefinition, CollisionQuad& quad, ExtendedMesh& mesh, float scale);
int CalculatePortalSurfaces(const aiScene* scene, CFileDefinition& fileDefinition, std::string& surfacesName, std::string& surfaceMappingName);
void CalculateBoundingBoxes(const aiScene* scene, CFileDefinition& fileDefinition, std::string& boundingBoxesName);
void CalculateTriggers(const aiScene* scene, CFileDefinition& fileDefinition, std::string& triggersName);
void CalculateLocations(const aiScene* scene, CFileDefinition& fileDefinition, std::string& locationsName);
void CalculateDoorwaysAndRooms(const aiScene* scene, CFileDefinition& fileDefinition, std::string& doorwaysName, std::string& roomsName);
void CalculateDoors(const aiScene* scene, CFileDefinition& fileDefinition, std::string& doorsName);
};
);
#endif

View file

@ -31,7 +31,7 @@ bool MeshDefinitionGenerator::ShouldIncludeNode(aiNode* node) {
return node->mName.C_Str()[0] != '@' && node->mNumMeshes > 0;
}
void MeshDefinitionGenerator::AppendRenderChunks(const aiScene* scene, aiNode* node, CFileDefinition& fileDefinition, DisplayListSettings& settings, std::vector<RenderChunk>& renderChunks) {
void MeshDefinitionGenerator::AppendRenderChunks(const aiScene* scene, aiNode* node, CFileDefinition& fileDefinition, const DisplayListSettings& settings, std::vector<RenderChunk>& renderChunks) {
for (unsigned meshIndex = 0; meshIndex < node->mNumMeshes; ++meshIndex) {
std::shared_ptr<ExtendedMesh> mesh = fileDefinition.GetExtendedMesh(scene->mMeshes[node->mMeshes[meshIndex]]);

View file

@ -12,7 +12,7 @@ public:
virtual bool ShouldIncludeNode(aiNode* node);
virtual void GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition);
static void AppendRenderChunks(const aiScene* scene, aiNode* node, CFileDefinition& fileDefinition, DisplayListSettings& settings, std::vector<RenderChunk>& renderChunks);
static void AppendRenderChunks(const aiScene* scene, aiNode* node, CFileDefinition& fileDefinition, const DisplayListSettings& settings, std::vector<RenderChunk>& renderChunks);
private:
DisplayListSettings mSettings;
};

View file

@ -4,13 +4,13 @@
#include "../StringUtils.h"
#include "../MathUtl.h"
#define ROOM_PREFIX "@room "
#define ROOM_PREFIX "@room"
#define LOCATION_PREFIX "@location "
#define LOCATION_PREFIX "@location"
#define DOORWAY_PREFIX "@doorway"
#define DOOR_PREFIX "@door "
#define DOOR_PREFIX "@door"
Doorway::Doorway(const aiNode* node, const CollisionQuad& quad):
node(node), quad(quad), roomA(0), roomB(0) {
@ -19,8 +19,6 @@ Doorway::Doorway(const aiNode* node, const CollisionQuad& quad):
Door::Door(const aiNode* node): node(node) {}
RoomGenerator::RoomGenerator(const DisplayListSettings& settings): DefinitionGenerator(), mSettings(settings) {}
short RoomGeneratorOutput::FindLocationRoom(const std::string& name) const {
for (auto& location : namedLocations) {
if (location.name == name) {
@ -56,16 +54,18 @@ struct RoomBlock {
int roomIndex;
};
bool RoomGenerator::ShouldIncludeNode(aiNode* node) {
return true;
}
void sortNodesByRoom(std::vector<aiNode*>& nodes, const RoomGeneratorOutput& roomOutput) {
std::sort(nodes.begin(), nodes.end(), [&](const aiNode* a, const aiNode* b) -> bool {
return roomOutput.RoomForNode(a) < roomOutput.RoomForNode(b);
});
}
void sortNodesWithArgsByRoom(std::vector<NodeWithArguments>& nodes, const RoomGeneratorOutput& roomOutput) {
std::sort(nodes.begin(), nodes.end(), [&](const NodeWithArguments& a, const NodeWithArguments& b) -> bool {
return roomOutput.RoomForNode(a.node) < roomOutput.RoomForNode(b.node);
});
}
int findClosestRoom(const aiNode* node, const aiScene* scene, CFileDefinition& fileDefinition, const std::vector<RoomBlock>& roomBlocks, int ignoreRoom, const RoomBlock** foundBlock = NULL) {
float distance = INFINITY;
int closestRoom = 0;
@ -97,47 +97,53 @@ int findClosestRoom(const aiNode* node, const aiScene* scene, CFileDefinition& f
return closestRoom;
}
void RoomGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition) {
std::shared_ptr<RoomGeneratorOutput> generateRooms(const aiScene* scene, CFileDefinition& fileDefinition, const DisplayListSettings& settings, NodeGroups& nodeGroups) {
std::vector<RoomBlock> roomBlocks;
std::shared_ptr<RoomGeneratorOutput> output(new RoomGeneratorOutput());
aiMatrix4x4 collisionTransform = mSettings.CreateCollisionTransform();
aiMatrix4x4 collisionTransform = settings.CreateCollisionTransform();
mOutput.roomCount = 0;
output->roomCount = 0;
for (auto node : mIncludedNodes) {
std::string nodeName(node->mName.C_Str());
if (StartsWith(nodeName, ROOM_PREFIX) && node->mNumMeshes) {
auto mesh = fileDefinition.GetExtendedMesh(scene->mMeshes[node->mMeshes[0]]);
aiVector3D minPoint = node->mTransformation * mesh->bbMin;
aiVector3D maxPoint = node->mTransformation * mesh->bbMax;
struct RoomBlock roomBlock;
roomBlock.boundingBox.mMin = min(minPoint, maxPoint);
roomBlock.boundingBox.mMax = max(minPoint, maxPoint);
roomBlock.roomIndex = std::atoi(nodeName.substr(strlen(ROOM_PREFIX)).c_str());
roomBlocks.push_back(roomBlock);
for (auto& nodeInfo : nodeGroups.NodesForType(ROOM_PREFIX)) {
if (!nodeInfo.node->mNumMeshes) {
continue;
}
if (StartsWith(nodeName, LOCATION_PREFIX)) {
NamedLocation location;
location.node = node;
location.name = nodeName.substr(strlen(LOCATION_PREFIX));
location.index = mOutput.namedLocations.size();
auto mesh = fileDefinition.GetExtendedMesh(scene->mMeshes[nodeInfo.node->mMeshes[0]]);
aiVector3D minPoint = nodeInfo.node->mTransformation * mesh->bbMin;
aiVector3D maxPoint = nodeInfo.node->mTransformation * mesh->bbMax;
mOutput.namedLocations.push_back(location);
}
struct RoomBlock roomBlock;
roomBlock.boundingBox.mMin = min(minPoint, maxPoint);
roomBlock.boundingBox.mMax = max(minPoint, maxPoint);
roomBlock.roomIndex = nodeInfo.arguments.size() ? std::atoi(nodeInfo.arguments[0].c_str()) : 0;
roomBlocks.push_back(roomBlock);
}
if (StartsWith(nodeName, DOORWAY_PREFIX) && node->mNumMeshes) {
mOutput.doorways.push_back(Doorway(node, CollisionQuad(
scene->mMeshes[node->mMeshes[0]],
collisionTransform * node->mTransformation
)));
for (auto& nodeInfo : nodeGroups.NodesForType(LOCATION_PREFIX)) {
NamedLocation location;
location.node = nodeInfo.node;
if (nodeInfo.arguments.size()) {
location.name = nodeInfo.arguments[0];
} else {
std::cout << "@location without a name";
}
location.index = output->namedLocations.size();
if (StartsWith(nodeName, DOOR_PREFIX)) {
mOutput.doors.push_back(Door(node));
}
output->namedLocations.push_back(location);
}
for (auto& nodeInfo : nodeGroups.NodesForType(DOORWAY_PREFIX)) {
output->doorways.push_back(Doorway(nodeInfo.node, CollisionQuad(
scene->mMeshes[nodeInfo.node->mMeshes[0]],
collisionTransform * nodeInfo.node->mTransformation
)));
}
for (auto& nodeInfo : nodeGroups.NodesForType(DOOR_PREFIX)) {
output->doors.push_back(Door(nodeInfo.node));
}
if (roomBlocks.size() == 0) {
@ -146,14 +152,14 @@ void RoomGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition& f
roomBlocks.push_back(roomBlock);
}
for (auto node : mIncludedNodes) {
forEachNode(scene->mRootNode, [&](aiNode* node) -> void {
int closestRoom = findClosestRoom(node, scene, fileDefinition, roomBlocks, -1);
mOutput.roomIndexMapping[node] = closestRoom;
mOutput.roomCount = std::max(mOutput.roomCount, closestRoom + 1);
}
output->roomIndexMapping[node] = closestRoom;
output->roomCount = std::max(output->roomCount, closestRoom + 1);
});
for (auto& doorway : mOutput.doorways) {
doorway.roomA = mOutput.roomIndexMapping[doorway.node];
for (auto& doorway : output->doorways) {
doorway.roomA = output->roomIndexMapping[doorway.node];
const RoomBlock* roomB = NULL;
doorway.roomB = findClosestRoom(doorway.node, scene, fileDefinition, roomBlocks, doorway.roomA, &roomB);
@ -169,15 +175,15 @@ void RoomGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition& f
}
}
mOutput.roomCount = std::max(mOutput.roomCount, doorway.roomB + 1);
output->roomCount = std::max(output->roomCount, doorway.roomB + 1);
}
for (auto& door : mOutput.doors) {
for (auto& door : output->doors) {
int doorwayIndex = -1;
int index = 0;
for (auto& doorway : mOutput.doorways) {
for (auto& doorway : output->doorways) {
if (doorway.quad.IsCoplanar(door.node->mTransformation * aiVector3D(0.0f, 0.0f, 0.0f))) {
doorwayIndex = index;
break;
@ -188,8 +194,6 @@ void RoomGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition& f
door.doorwayIndex = doorwayIndex;
}
}
const RoomGeneratorOutput& RoomGenerator::GetOutput() const {
return mOutput;
return output;
}

View file

@ -41,18 +41,8 @@ struct RoomGeneratorOutput {
};
void sortNodesByRoom(std::vector<aiNode*>& nodes, const RoomGeneratorOutput& roomOutput);
void sortNodesWithArgsByRoom(std::vector<NodeWithArguments>& nodes, const RoomGeneratorOutput& roomOutput);
class RoomGenerator : public DefinitionGenerator {
public:
RoomGenerator(const DisplayListSettings& settings);
virtual bool ShouldIncludeNode(aiNode* node);
virtual void GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition);
const RoomGeneratorOutput& GetOutput() const;
private:
DisplayListSettings mSettings;
RoomGeneratorOutput mOutput;
};
std::shared_ptr<RoomGeneratorOutput> generateRooms(const aiScene* scene, CFileDefinition& fileDefinition, const DisplayListSettings& settings, NodeGroups& nodeGroups);
#endif

View file

@ -6,45 +6,41 @@
#include "MaterialGenerator.h"
#include "../RenderChunk.h"
StaticGenerator::StaticGenerator(const DisplayListSettings& settings, const RoomGeneratorOutput& roomMapping) : DefinitionGenerator(), mSettings(settings), mRoomMapping(roomMapping) {
std::shared_ptr<StaticGeneratorOutput> generateStatic(const aiScene* scene, CFileDefinition& fileDefinition, const DisplayListSettings& settings, RoomGeneratorOutput& roomMapping, NodeGroups& nodeGroups) {
DisplayListSettings settingsCopy = settings;
settingsCopy.mMaterials.clear();
}
bool StaticGenerator::ShouldIncludeNode(aiNode* node) {
return StartsWith(node->mName.C_Str(), "@static ") && node->mNumMeshes > 0;
}
void StaticGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition) {
DisplayListSettings settings = mSettings;
settings.mMaterials.clear();
std::shared_ptr<StaticGeneratorOutput> output(new StaticGeneratorOutput());
std::vector<StaticContentElement> elements;
BoneHierarchy unusedBones;
sortNodesByRoom(mIncludedNodes, mRoomMapping);
std::vector<NodeWithArguments> nodes = nodeGroups.NodesForType("@static");
for (auto node = mIncludedNodes.begin(); node != mIncludedNodes.end(); ++node) {
sortNodesWithArgsByRoom(nodes, roomMapping);
for (auto& nodeInfo : nodes) {
std::vector<RenderChunk> renderChunks;
MeshDefinitionGenerator::AppendRenderChunks(scene, *node, fileDefinition, mSettings, renderChunks);
MeshDefinitionGenerator::AppendRenderChunks(scene, nodeInfo.node, fileDefinition, settings, renderChunks);
for (auto& chunk : renderChunks) {
StaticContentElement element;
if (chunk.mMaterial) {
settings.mDefaultMaterialState = chunk.mMaterial->mState;
settingsCopy.mDefaultMaterialState = chunk.mMaterial->mState;
element.materialName = MaterialGenerator::MaterialIndexMacroName(chunk.mMaterial->mName);
} else {
element.materialName = "0";
}
std::vector<RenderChunk> singleChunk;
singleChunk.push_back(chunk);
element.meshName = generateMesh(scene, fileDefinition, singleChunk, settings, "_geo");
element.meshName = generateMesh(scene, fileDefinition, singleChunk, settingsCopy, "_geo");
elements.push_back(element);
mOutput.staticMeshes.push_back(chunk.mMesh);
mOutput.staticRooms.push_back(mRoomMapping.RoomForNode(*node));
output->staticMeshes.push_back(chunk.mMesh);
output->staticRooms.push_back(roomMapping.RoomForNode(nodeInfo.node));
}
}
@ -59,20 +55,20 @@ void StaticGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition&
staticContentList->Add(std::move(element));
}
mOutput.staticContentName = fileDefinition.GetUniqueName("static");
output->staticContentName = fileDefinition.GetUniqueName("static");
std::unique_ptr<FileDefinition> fileDef(new DataFileDefinition("struct StaticContentElement", mOutput.staticContentName, true, "_geo", std::move(staticContentList)));
std::unique_ptr<FileDefinition> fileDef(new DataFileDefinition("struct StaticContentElement", output->staticContentName, true, "_geo", std::move(staticContentList)));
fileDef->AddTypeHeader("\"levels/level_def_gen.h\"");
fileDefinition.AddDefinition(std::move(fileDef));
std::unique_ptr<StructureDataChunk> roomToStaticMapping(new StructureDataChunk());
int prevIndex = 0;
for (int roomIndex = 0; roomIndex < mRoomMapping.roomCount; ++roomIndex) {
for (int roomIndex = 0; roomIndex < roomMapping.roomCount; ++roomIndex) {
std::unique_ptr<StructureDataChunk> singleMapping(new StructureDataChunk());
int currentIndex = prevIndex;
while (currentIndex < (int)mOutput.staticRooms.size() && mOutput.staticRooms[currentIndex] <= roomIndex) {
while (currentIndex < (int)output->staticRooms.size() && output->staticRooms[currentIndex] <= roomIndex) {
++currentIndex;
}
@ -84,10 +80,8 @@ void StaticGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition&
roomToStaticMapping->Add(std::move(singleMapping));
}
mOutput.roomMappingName = fileDefinition.GetUniqueName("static_room_mapping");
fileDefinition.AddDefinition(std::unique_ptr<FileDefinition>(new DataFileDefinition("struct Rangeu16", mOutput.roomMappingName, true, "_geo", std::move(roomToStaticMapping))));
}
output->roomMappingName = fileDefinition.GetUniqueName("static_room_mapping");
fileDefinition.AddDefinition(std::unique_ptr<FileDefinition>(new DataFileDefinition("struct Rangeu16", output->roomMappingName, true, "_geo", std::move(roomToStaticMapping))));
const StaticGeneratorOutput& StaticGenerator::GetOutput() const {
return mOutput;
return output;
}

View file

@ -17,19 +17,6 @@ struct StaticGeneratorOutput {
std::string roomMappingName;
};
class StaticGenerator : public DefinitionGenerator {
public:
StaticGenerator(const DisplayListSettings& settings, const RoomGeneratorOutput& roomMapping);
virtual bool ShouldIncludeNode(aiNode* node);
virtual void GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition);
const StaticGeneratorOutput& GetOutput() const;
private:
DisplayListSettings mSettings;
StaticGeneratorOutput mOutput;
RoomGeneratorOutput mRoomMapping;
};
std::shared_ptr<StaticGeneratorOutput> generateStatic(const aiScene* scene, CFileDefinition& fileDefinition, const DisplayListSettings& settings, RoomGeneratorOutput& roomMapping, NodeGroups& nodeGroups);
#endif

View file

@ -2,9 +2,9 @@
#include "../StringUtils.h"
#include "../MathUtl.h"
#define TRIGGER_PREFIX "@trigger "
#define TRIGGER_PREFIX "@trigger"
#define CUTSCENE_PREFIX "@cutscene "
#define CUTSCENE_PREFIX "@cutscene"
CutsceneStep::CutsceneStep(
const std::string& command,
@ -33,13 +33,7 @@ float distanceFromStart(const CutsceneStep& startStep, const CutsceneStep& other
return relativeOffset.y;
}
TriggerGenerator::TriggerGenerator(const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput): DefinitionGenerator(), mSettings(settings), mRoomOutput(roomOutput) {}
bool TriggerGenerator::ShouldIncludeNode(aiNode* node) {
return (StartsWith(node->mName.C_Str(), TRIGGER_PREFIX) && node->mNumMeshes >= 1) || StartsWith(node->mName.C_Str(), CUTSCENE_PREFIX);
}
std::unique_ptr<StructureDataChunk> TriggerGenerator::GenerateCutsceneStep(CutsceneStep& step) {
std::unique_ptr<StructureDataChunk> generateCutsceneStep(CutsceneStep& step, const RoomGeneratorOutput& roomOutput) {
std::unique_ptr<StructureDataChunk> result(new StructureDataChunk());
if ((step.command == "play_sound" || step.command == "start_sound") && step.args.size() >= 1) {
@ -67,7 +61,7 @@ std::unique_ptr<StructureDataChunk> TriggerGenerator::GenerateCutsceneStep(Cutsc
result->AddPrimitive("delay", std::atof(step.args[0].c_str()));
return result;
} else if (step.command == "open_portal" && step.args.size() >= 1) {
short roomLocation = mRoomOutput.FindLocationIndex(step.args[0]);
short roomLocation = roomOutput.FindLocationIndex(step.args[0]);
if (roomLocation != -1) {
result->AddPrimitive<const char*>("CutsceneStepTypeOpenPortal");
@ -85,15 +79,12 @@ std::unique_ptr<StructureDataChunk> TriggerGenerator::GenerateCutsceneStep(Cutsc
return result;
}
void TriggerGenerator::GenerateCutscenes(std::map<std::string, std::shared_ptr<Cutscene>>& output, CFileDefinition& fileDefinition) {
void generateCutscenes(std::map<std::string, std::shared_ptr<Cutscene>>& output, CFileDefinition& fileDefinition, const RoomGeneratorOutput& roomOutput, NodeGroups& nodeGroups) {
std::vector<std::shared_ptr<CutsceneStep>> steps;
for (auto& node : mIncludedNodes) {
if (!StartsWith(node->mName.C_Str(), CUTSCENE_PREFIX)) {
continue;
}
for (auto& nodeInfo : nodeGroups.NodesForType(CUTSCENE_PREFIX)) {
std::vector<std::string> cutsceneParts;
SplitString(node->mName.C_Str(), ' ', cutsceneParts);
SplitString(nodeInfo.node->mName.C_Str(), ' ', cutsceneParts);
if (cutsceneParts.size() <= 1) {
continue;
@ -106,7 +97,7 @@ void TriggerGenerator::GenerateCutscenes(std::map<std::string, std::shared_ptr<C
aiVector3D scale;
aiVector3D pos;
aiQuaternion rot;
node->mTransformation.Decompose(scale, rot, pos);
nodeInfo.node->mTransformation.Decompose(scale, rot, pos);
std::shared_ptr<CutsceneStep> step(new CutsceneStep(command, cutsceneParts, pos, rot));
@ -142,7 +133,7 @@ void TriggerGenerator::GenerateCutscenes(std::map<std::string, std::shared_ptr<C
std::unique_ptr<StructureDataChunk> steps(new StructureDataChunk());
for (auto& step : cutscene.steps) {
steps->Add(std::move(GenerateCutsceneStep(*step)));
steps->Add(std::move(generateCutsceneStep(*step, roomOutput)));
}
std::string stepsName = fileDefinition.GetUniqueName(cutscene.name + "_steps");
@ -153,21 +144,19 @@ void TriggerGenerator::GenerateCutscenes(std::map<std::string, std::shared_ptr<C
}
}
void TriggerGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition) {
std::shared_ptr<TriggerGeneratorOutput> generateTriggers(const aiScene* scene, CFileDefinition& fileDefinition, const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput, NodeGroups& nodeGroups) {
std::shared_ptr<TriggerGeneratorOutput> output(new TriggerGeneratorOutput());
std::map<std::string, std::shared_ptr<Cutscene>> cutscenes;
GenerateCutscenes(cutscenes, fileDefinition);
generateCutscenes(cutscenes, fileDefinition, roomOutput, nodeGroups);
for (auto& node : mIncludedNodes) {
if (!StartsWith(node->mName.C_Str(), TRIGGER_PREFIX)) {
continue;
}
auto mesh = fileDefinition.GetExtendedMesh(scene->mMeshes[node->mMeshes[0]]);
for (auto& nodeInfo : nodeGroups.NodesForType(TRIGGER_PREFIX)) {
auto mesh = fileDefinition.GetExtendedMesh(scene->mMeshes[nodeInfo.node->mMeshes[0]]);
std::shared_ptr<Trigger> trigger(new Trigger());
std::string nodeName = node->mName.C_Str();
std::string nodeName = nodeInfo.node->mName.C_Str();
auto cutscene = cutscenes.find(nodeName.substr(strlen(TRIGGER_PREFIX)));
@ -179,16 +168,14 @@ void TriggerGenerator::GenerateDefinitions(const aiScene* scene, CFileDefinition
trigger->stepsCount = cutscene->second->steps.size();
}
aiVector3D minTransformed = node->mTransformation * mesh->bbMin * mSettings.mCollisionScale;
aiVector3D maxTransformed = node->mTransformation * mesh->bbMax * mSettings.mCollisionScale;
aiVector3D minTransformed = nodeInfo.node->mTransformation * mesh->bbMin * settings.mCollisionScale;
aiVector3D maxTransformed = nodeInfo.node->mTransformation * mesh->bbMax * settings.mCollisionScale;
trigger->bb.mMin = min(minTransformed, maxTransformed);
trigger->bb.mMax = max(minTransformed, maxTransformed);
mOutput.triggers.push_back(trigger);
output->triggers.push_back(trigger);
}
}
const TriggerGeneratorOutput& TriggerGenerator::GetOutput() const {
return mOutput;
return output;
}

View file

@ -31,21 +31,6 @@ struct Cutscene {
std::vector<std::shared_ptr<CutsceneStep>> steps;
};
class TriggerGenerator : public DefinitionGenerator {
public:
TriggerGenerator(const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput);
virtual bool ShouldIncludeNode(aiNode* node);
virtual void GenerateDefinitions(const aiScene* scene, CFileDefinition& fileDefinition);
const TriggerGeneratorOutput& GetOutput() const;
private:
DisplayListSettings mSettings;
TriggerGeneratorOutput mOutput;
RoomGeneratorOutput mRoomOutput;
void GenerateCutscenes(std::map<std::string, std::shared_ptr<Cutscene>>& output, CFileDefinition& fileDefinition);
std::unique_ptr<StructureDataChunk> GenerateCutsceneStep(CutsceneStep& step);
};
std::shared_ptr<TriggerGeneratorOutput> generateTriggers(const aiScene* scene, CFileDefinition& fileDefinition, const DisplayListSettings& settings, const RoomGeneratorOutput& roomOutput, NodeGroups& nodeGroups);
#endif