Add support for multiple worlds in a single cinematic
This commit is contained in:
parent
c7d87e9a9f
commit
d91c7d7221
12 changed files with 425 additions and 267 deletions
|
@ -53,7 +53,10 @@ set(GRAPH_SRC
|
|||
src/skypass.cpp
|
||||
src/shadowpass.cpp
|
||||
src/config.cpp
|
||||
src/stringutils.cpp)
|
||||
src/stringutils.cpp
|
||||
src/animationsystem.cpp
|
||||
src/worldmanager.cpp
|
||||
src/assetmanager.cpp)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(GRAPH_SRC
|
||||
|
@ -109,4 +112,5 @@ add_data(Graph
|
|||
data/tile.jpg
|
||||
data/graphics_presets.cfg
|
||||
data/test.world
|
||||
data/test.material)
|
||||
data/test.material
|
||||
data/empty.world)
|
||||
|
|
11
data/empty.world
Normal file
11
data/empty.world
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"meshes": [
|
||||
|
||||
],
|
||||
"lights": [
|
||||
{
|
||||
"position": "66,56,25",
|
||||
"type": 1
|
||||
}
|
||||
]
|
||||
}
|
|
@ -70,7 +70,7 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"world": "test.world",
|
||||
"world": "empty.world",
|
||||
"start": 5,
|
||||
"end": 10,
|
||||
"meshes": [
|
||||
|
|
20
include/animationsystem.h
Normal file
20
include/animationsystem.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "cinematic.h"
|
||||
|
||||
class AnimationSystem {
|
||||
public:
|
||||
Cinematic* loadCinematic(const std::string& path);
|
||||
|
||||
void update(Cinematic* cinematic, float deltaTime);
|
||||
|
||||
private:
|
||||
void preloadShot(Shot* shot);
|
||||
void loadShot(Shot* shot);
|
||||
void unloadShot(Shot* shot);
|
||||
|
||||
float animationTime = 0.0f;
|
||||
int currentShot = 0;
|
||||
};
|
22
include/assetmanager.h
Normal file
22
include/assetmanager.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
struct Mesh;
|
||||
struct Material;
|
||||
class Renderer;
|
||||
|
||||
class AssetManager {
|
||||
public:
|
||||
void setRenderer(Renderer* r) {
|
||||
renderer = r;
|
||||
}
|
||||
|
||||
Mesh* loadMesh(const std::string& path);
|
||||
Material* loadMaterial(const std::string& path);
|
||||
|
||||
private:
|
||||
Renderer* renderer = nullptr;
|
||||
};
|
||||
|
||||
inline AssetManager assetManager;
|
|
@ -19,15 +19,24 @@ enum class AnimationProperty {
|
|||
|
||||
struct Animation {
|
||||
Mesh* target = nullptr;
|
||||
std::string targetName;
|
||||
AnimationProperty property = AnimationProperty::Position;
|
||||
|
||||
std::vector<Keyframe> keyframes;
|
||||
};
|
||||
|
||||
struct CinematicMesh {
|
||||
std::string name, modelPath, materialPath;
|
||||
};
|
||||
|
||||
struct Shot {
|
||||
int start = 0, end = 0;
|
||||
bool loaded = false;
|
||||
|
||||
std::string world;
|
||||
|
||||
std::vector<Mesh*> meshes;
|
||||
std::vector<CinematicMesh> meshes;
|
||||
std::vector<Mesh*> loadedMeshes;
|
||||
std::vector<Animation*> animations;
|
||||
};
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
#include "camera.h"
|
||||
|
||||
class Mesh;
|
||||
class Light;
|
||||
|
||||
|
@ -9,4 +11,6 @@ class World {
|
|||
public:
|
||||
std::vector<Mesh*> meshes;
|
||||
std::vector<Light*> lights;
|
||||
|
||||
Camera camera;
|
||||
};
|
||||
|
|
23
include/worldmanager.h
Normal file
23
include/worldmanager.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
struct World;
|
||||
|
||||
class WorldManager {
|
||||
public:
|
||||
void loadWorld(const std::string& path);
|
||||
|
||||
void switchWorld(const std::string& path);
|
||||
|
||||
World* getCurrentWorld() {
|
||||
return currentWorld;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, World*> loadedWorlds;
|
||||
World* currentWorld = nullptr;
|
||||
};
|
||||
|
||||
inline WorldManager worldManager;
|
190
src/animationsystem.cpp
Normal file
190
src/animationsystem.cpp
Normal file
|
@ -0,0 +1,190 @@
|
|||
#include "animationsystem.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <json.hpp>
|
||||
|
||||
#include "mesh.h"
|
||||
#include "stringutils.h"
|
||||
#include "worldmanager.h"
|
||||
#include "world.h"
|
||||
#include "assetmanager.h"
|
||||
|
||||
Cinematic* AnimationSystem::loadCinematic(const std::string& path) {
|
||||
std::ifstream file("data/" + path);
|
||||
if(!file)
|
||||
return nullptr;
|
||||
|
||||
nlohmann::json json;
|
||||
file >> json;
|
||||
|
||||
auto cinematic = new Cinematic();
|
||||
for(auto shotObject : json["shots"]) {
|
||||
Shot* shot = new Shot();
|
||||
shot->start = shotObject["start"];
|
||||
shot->end = shotObject["end"];
|
||||
shot->world = shotObject["world"];
|
||||
|
||||
for(auto meshObject : shotObject["meshes"]) {
|
||||
CinematicMesh mesh;
|
||||
mesh.name = meshObject["name"];
|
||||
mesh.modelPath = meshObject["path"];
|
||||
mesh.materialPath = meshObject["material"];
|
||||
|
||||
shot->meshes.push_back(mesh);
|
||||
}
|
||||
|
||||
for(auto animationObject : shotObject["animations"]) {
|
||||
auto animation = new Animation();
|
||||
animation->targetName = animationObject["target"];
|
||||
|
||||
const auto property = animationObject["property"];
|
||||
if(property == "position")
|
||||
animation->property = AnimationProperty::Position;
|
||||
else if(property == "target")
|
||||
animation->property = AnimationProperty::Target;
|
||||
else if(property == "fov")
|
||||
animation->property = AnimationProperty::FoV;
|
||||
|
||||
for(auto keyframeObject : animationObject["keyframes"]) {
|
||||
Keyframe keyframe;
|
||||
keyframe.time = keyframeObject["time"];
|
||||
|
||||
if(animation->property == AnimationProperty::Position || animation->property == AnimationProperty::Target) {
|
||||
auto tokens = tokenize(keyframeObject["value"]);
|
||||
|
||||
keyframe.valueVec3[0] = atof(tokens[0].c_str());
|
||||
keyframe.valueVec3[1] = atof(tokens[1].c_str());
|
||||
keyframe.valueVec3[2] = atof(tokens[2].c_str());
|
||||
|
||||
animation->keyframes.push_back(keyframe);
|
||||
} else if(animation->property == AnimationProperty::FoV) {
|
||||
keyframe.valueInt = keyframeObject["value"];
|
||||
|
||||
animation->keyframes.push_back(keyframe);
|
||||
}
|
||||
}
|
||||
|
||||
shot->animations.push_back(animation);
|
||||
}
|
||||
|
||||
cinematic->shots.push_back(shot);
|
||||
}
|
||||
|
||||
preloadShot(cinematic->shots[0]);
|
||||
loadShot(cinematic->shots[0]);
|
||||
|
||||
return cinematic;
|
||||
}
|
||||
|
||||
void AnimationSystem::update(Cinematic* cinematic, float deltaTime) {
|
||||
float endTime = 0.0f;
|
||||
for(uint32_t i = 0; i < cinematic->shots.size(); i++) {
|
||||
// load the shot before it happens
|
||||
if((i + 1) <= cinematic->shots.size() && i == (currentShot + 1) && !cinematic->shots[currentShot + 1]->loaded) {
|
||||
preloadShot(cinematic->shots[currentShot + 1]);
|
||||
cinematic->shots[currentShot + 1]->loaded = true;
|
||||
}
|
||||
|
||||
if(i > currentShot && animationTime > cinematic->shots[i]->start) {
|
||||
unloadShot(cinematic->shots[currentShot]);
|
||||
currentShot = i;
|
||||
loadShot(cinematic->shots[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for(auto animation : cinematic->shots[currentShot]->animations) {
|
||||
unsigned int frameIndex = 0;
|
||||
for(size_t i = 0; i < animation->keyframes.size(); i++) {
|
||||
if(animationTime < animation->keyframes[i + 1].time) {
|
||||
frameIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto currentFrame = animation->keyframes[frameIndex];
|
||||
const auto nextFrame = animation->keyframes[(frameIndex + 1) % animation->keyframes.size()];
|
||||
|
||||
const float delta = (animationTime - currentFrame.time) / (nextFrame.time - currentFrame.time);
|
||||
|
||||
switch(animation->property) {
|
||||
case AnimationProperty::Position:
|
||||
{
|
||||
auto pos = currentFrame.valueVec3 + delta * (nextFrame.valueVec3 - currentFrame.valueVec3);
|
||||
|
||||
if(animation->target == nullptr)
|
||||
worldManager.getCurrentWorld()->camera.position = pos;
|
||||
else {
|
||||
animation->target->position = pos;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AnimationProperty::Target:
|
||||
{
|
||||
auto pos = currentFrame.valueVec3 + delta * (nextFrame.valueVec3 - currentFrame.valueVec3);
|
||||
|
||||
worldManager.getCurrentWorld()->camera.target = pos;
|
||||
}
|
||||
break;
|
||||
case AnimationProperty::FoV:
|
||||
{
|
||||
auto pos = currentFrame.valueInt + delta * (nextFrame.valueInt - currentFrame.valueInt);
|
||||
worldManager.getCurrentWorld()->camera.fov = pos;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
animationTime += deltaTime;
|
||||
}
|
||||
|
||||
void AnimationSystem::preloadShot(Shot* shot) {
|
||||
std::cout << "preloading shot..." << std::endl;
|
||||
|
||||
worldManager.loadWorld(shot->world);
|
||||
|
||||
for(auto cimMesh : shot->meshes) {
|
||||
Mesh* mesh = assetManager.loadMesh(cimMesh.modelPath);
|
||||
mesh->name = cimMesh.name;
|
||||
mesh->material = assetManager.loadMaterial(cimMesh.materialPath);
|
||||
mesh->tag = "cinematic";
|
||||
|
||||
for(auto animation : shot->animations) {
|
||||
if(animation->targetName == mesh->name)
|
||||
animation->target = mesh;
|
||||
}
|
||||
|
||||
shot->loadedMeshes.push_back(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationSystem::loadShot(Shot* shot) {
|
||||
std::cout << "loading shot..." << std::endl;
|
||||
|
||||
worldManager.switchWorld(shot->world);
|
||||
|
||||
for(auto mesh : shot->loadedMeshes)
|
||||
worldManager.getCurrentWorld()->meshes.push_back(mesh);
|
||||
}
|
||||
|
||||
void AnimationSystem::unloadShot(Shot* shot) {
|
||||
std::cout << "unloading shot..." << std::endl;
|
||||
|
||||
World* world = worldManager.getCurrentWorld();
|
||||
|
||||
for(auto mesh : world->meshes) {
|
||||
if(mesh->tag == "cinematic") {
|
||||
//renderer->destroyMaterialBuffers(mesh->material);
|
||||
delete mesh->material;
|
||||
|
||||
//renderer->destroyMeshBuffers(mesh);
|
||||
delete mesh;
|
||||
}
|
||||
}
|
||||
|
||||
world->meshes.erase(std::remove_if(world->meshes.begin(),
|
||||
world->meshes.end(),
|
||||
[](Mesh* m){return m->tag == "cinematic";}),
|
||||
world->meshes.end());
|
||||
}
|
61
src/assetmanager.cpp
Normal file
61
src/assetmanager.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
#include "assetmanager.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <json.hpp>
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/postprocess.h>
|
||||
|
||||
#include "mesh.h"
|
||||
#include "material.h"
|
||||
#include "renderer.h"
|
||||
|
||||
Mesh* AssetManager::loadMesh(const std::string& path) {
|
||||
std::string fixedPath = "data/" + path;
|
||||
|
||||
Assimp::Importer importer;
|
||||
const aiScene* scene = importer.ReadFile(fixedPath.c_str(), aiProcess_Triangulate);
|
||||
|
||||
Mesh* mesh = new Mesh();
|
||||
|
||||
unsigned int indexOffset = 0;
|
||||
for(unsigned mi = 0; mi < scene->mNumMeshes; mi++) {
|
||||
aiMesh* m = scene->mMeshes[mi];
|
||||
|
||||
for(unsigned int i = 0; i < m->mNumVertices; i++) {
|
||||
Vertex vertex;
|
||||
vertex.position = glm::vec3(m->mVertices[i].x, m->mVertices[i].y, m->mVertices[i].z);
|
||||
vertex.normal = glm::vec3(m->mNormals[i].x, m->mNormals[i].y, m->mNormals[i].z);
|
||||
vertex.uv = glm::vec2(m->mTextureCoords[0][i].x, m->mTextureCoords[0][i].y);
|
||||
|
||||
mesh->vertices.push_back(vertex);
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < m->mNumFaces; i++) {
|
||||
aiFace face = m->mFaces[i];
|
||||
for(unsigned int j = 0; j < face.mNumIndices; j++)
|
||||
mesh->indices.push_back(indexOffset + face.mIndices[j]);
|
||||
}
|
||||
|
||||
indexOffset += m->mNumVertices;
|
||||
}
|
||||
|
||||
renderer->fillMeshBuffers(mesh);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
Material* AssetManager::loadMaterial(const std::string& path) {
|
||||
std::ifstream file("data/" + path);
|
||||
|
||||
nlohmann::json json;
|
||||
file >> json;
|
||||
|
||||
Material* material = new Material();
|
||||
material->albedoTexturePath = "data/" + json["albedoTexture"].get<std::string>();
|
||||
|
||||
renderer->fillMaterialBuffers(material);
|
||||
|
||||
return material;
|
||||
}
|
286
src/main.cpp
286
src/main.cpp
|
@ -5,9 +5,6 @@
|
|||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <json.hpp>
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/postprocess.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <imgui.h>
|
||||
|
@ -19,10 +16,12 @@
|
|||
#include "mesh.h"
|
||||
#include "light.h"
|
||||
#include "camera.h"
|
||||
#include "cinematic.h"
|
||||
#include "animationsystem.h"
|
||||
#include "material.h"
|
||||
#include "config.h"
|
||||
#include "stringutils.h"
|
||||
#include "worldmanager.h"
|
||||
#include "assetmanager.h"
|
||||
|
||||
SDL_Window* window = nullptr;
|
||||
Renderer* renderer = nullptr;
|
||||
|
@ -49,8 +48,6 @@ int windowFullscreen = 0;
|
|||
std::string currentGraphicsPreset = "Medium";
|
||||
GraphicsConfig graphicsConfig;
|
||||
|
||||
World* world = nullptr;
|
||||
|
||||
int toInt(const std::string &str) {
|
||||
std::stringstream ss(str);
|
||||
|
||||
|
@ -105,161 +102,6 @@ void writeConfig() {
|
|||
config.save("user.cfg");
|
||||
}
|
||||
|
||||
Mesh* loadMesh(const std::string& path) {
|
||||
std::string fixedPath = "data/" + path;
|
||||
|
||||
Assimp::Importer importer;
|
||||
const aiScene* scene = importer.ReadFile(fixedPath.c_str(), aiProcess_Triangulate);
|
||||
|
||||
Mesh* mesh = new Mesh();
|
||||
|
||||
unsigned int indexOffset = 0;
|
||||
for(unsigned mi = 0; mi < scene->mNumMeshes; mi++) {
|
||||
aiMesh* m = scene->mMeshes[mi];
|
||||
|
||||
for(unsigned int i = 0; i < m->mNumVertices; i++) {
|
||||
Vertex vertex;
|
||||
vertex.position = glm::vec3(m->mVertices[i].x, m->mVertices[i].y, m->mVertices[i].z);
|
||||
vertex.normal = glm::vec3(m->mNormals[i].x, m->mNormals[i].y, m->mNormals[i].z);
|
||||
vertex.uv = glm::vec2(m->mTextureCoords[0][i].x, m->mTextureCoords[0][i].y);
|
||||
|
||||
mesh->vertices.push_back(vertex);
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < m->mNumFaces; i++) {
|
||||
aiFace face = m->mFaces[i];
|
||||
for(unsigned int j = 0; j < face.mNumIndices; j++)
|
||||
mesh->indices.push_back(indexOffset + face.mIndices[j]);
|
||||
}
|
||||
|
||||
indexOffset += m->mNumVertices;
|
||||
}
|
||||
|
||||
renderer->fillMeshBuffers(mesh);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
Material* loadMaterial(const std::string& path) {
|
||||
std::ifstream file("data/" + path);
|
||||
|
||||
nlohmann::json json;
|
||||
file >> json;
|
||||
|
||||
Material* material = new Material();
|
||||
material->albedoTexturePath = "data/" + json["albedoTexture"].get<std::string>();
|
||||
|
||||
renderer->fillMaterialBuffers(material);
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
World* loadWorld(const std::string& path) {
|
||||
std::ifstream file("data/" + path);
|
||||
|
||||
nlohmann::json json;
|
||||
file >> json;
|
||||
|
||||
World* world = new World();
|
||||
|
||||
for(auto meshObject : json["meshes"]) {
|
||||
Mesh* mesh = loadMesh(meshObject["path"]);
|
||||
mesh->material = loadMaterial(meshObject["material"]);
|
||||
|
||||
auto tokens = tokenize(meshObject["position"]);
|
||||
|
||||
mesh->position[0] = atof(tokens[0].c_str());
|
||||
mesh->position[1] = atof(tokens[1].c_str());
|
||||
mesh->position[2] = atof(tokens[2].c_str());
|
||||
|
||||
world->meshes.push_back(mesh);
|
||||
}
|
||||
|
||||
for(auto lightObject : json["lights"]) {
|
||||
Light* light = new Light();
|
||||
|
||||
auto tokens = tokenize(lightObject["position"]);
|
||||
|
||||
light->position[0] = atof(tokens[0].c_str());
|
||||
light->position[1] = atof(tokens[1].c_str());
|
||||
light->position[2] = atof(tokens[2].c_str());
|
||||
|
||||
world->lights.push_back(light);
|
||||
}
|
||||
|
||||
return world;
|
||||
}
|
||||
|
||||
Cinematic* loadCinematic(const std::string& path) {
|
||||
std::ifstream file("data/" + path);
|
||||
if(!file)
|
||||
return nullptr;
|
||||
|
||||
nlohmann::json json;
|
||||
file >> json;
|
||||
|
||||
auto cinematic = new Cinematic();
|
||||
for(auto shotObject : json["shots"]) {
|
||||
Shot* shot = new Shot();
|
||||
shot->start = shotObject["start"];
|
||||
shot->end = shotObject["end"];
|
||||
|
||||
// TODO: concurrent worlds not implemented, we just load the first one
|
||||
if(world == nullptr)
|
||||
world = loadWorld(shotObject["world"]);
|
||||
|
||||
for(auto meshObject : shotObject["meshes"]) {
|
||||
Mesh* mesh = loadMesh(meshObject["path"]);
|
||||
mesh->name = meshObject["name"];
|
||||
mesh->material = loadMaterial(meshObject["material"]);
|
||||
mesh->tag = "cinematic";
|
||||
|
||||
shot->meshes.push_back(mesh);
|
||||
}
|
||||
|
||||
for(auto animationObject : shotObject["animations"]) {
|
||||
auto animation = new Animation();
|
||||
for(auto mesh : shot->meshes) {
|
||||
if(mesh->name == animationObject["target"])
|
||||
animation->target = mesh;
|
||||
}
|
||||
|
||||
const auto property = animationObject["property"];
|
||||
if(property == "position")
|
||||
animation->property = AnimationProperty::Position;
|
||||
else if(property == "target")
|
||||
animation->property = AnimationProperty::Target;
|
||||
else if(property == "fov")
|
||||
animation->property = AnimationProperty::FoV;
|
||||
|
||||
for(auto keyframeObject : animationObject["keyframes"]) {
|
||||
Keyframe keyframe;
|
||||
keyframe.time = keyframeObject["time"];
|
||||
|
||||
if(animation->property == AnimationProperty::Position || animation->property == AnimationProperty::Target) {
|
||||
auto tokens = tokenize(keyframeObject["value"]);
|
||||
|
||||
keyframe.valueVec3[0] = atof(tokens[0].c_str());
|
||||
keyframe.valueVec3[1] = atof(tokens[1].c_str());
|
||||
keyframe.valueVec3[2] = atof(tokens[2].c_str());
|
||||
|
||||
animation->keyframes.push_back(keyframe);
|
||||
} else if(animation->property == AnimationProperty::FoV) {
|
||||
keyframe.valueInt = keyframeObject["value"];
|
||||
|
||||
animation->keyframes.push_back(keyframe);
|
||||
}
|
||||
}
|
||||
|
||||
shot->animations.push_back(animation);
|
||||
}
|
||||
|
||||
cinematic->shots.push_back(shot);
|
||||
}
|
||||
|
||||
return cinematic;
|
||||
}
|
||||
|
||||
Cinematic* cinematic = nullptr;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
|
@ -300,18 +142,19 @@ int main(int argc, char* argv[]) {
|
|||
SDL_Vulkan_CreateSurface(window, renderer->getInstance(), &surface);
|
||||
|
||||
RenderTarget* target = renderer->createSurfaceRenderTarget(surface);
|
||||
|
||||
assetManager.setRenderer(renderer);
|
||||
|
||||
AnimationSystem* animationSystem = new AnimationSystem();
|
||||
|
||||
if(cinematicMode)
|
||||
cinematic = loadCinematic(argv[2]);
|
||||
cinematic = animationSystem->loadCinematic(argv[2]);
|
||||
else {
|
||||
world = loadWorld("test.world");
|
||||
worldManager.loadWorld("test.world");
|
||||
worldManager.switchWorld("test.world");
|
||||
}
|
||||
|
||||
Camera camera;
|
||||
camera.position = {5.0, 5.0, 5.0};
|
||||
|
||||
float currentTime = 0.0f, lastTime = 0.0f, animationTime = 0.0f;
|
||||
Shot* currentShot = nullptr;
|
||||
float currentTime = 0.0f, lastTime = 0.0f;
|
||||
|
||||
bool running = true;
|
||||
while(running) {
|
||||
|
@ -347,93 +190,13 @@ int main(int argc, char* argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
if(cinematicMode) {
|
||||
float endTime = 0.0f;
|
||||
for(auto shot : cinematic->shots) {
|
||||
if(shot->end > endTime)
|
||||
endTime = shot->end;
|
||||
|
||||
if(animationTime >= shot->start && animationTime < shot->end && currentShot != shot) {
|
||||
if(currentShot != nullptr) {
|
||||
for(auto mesh : world->meshes) {
|
||||
if(mesh->tag == "cinematic") {
|
||||
renderer->destroyMaterialBuffers(mesh->material);
|
||||
delete mesh->material;
|
||||
|
||||
renderer->destroyMeshBuffers(mesh);
|
||||
delete mesh;
|
||||
}
|
||||
}
|
||||
|
||||
world->meshes.erase(std::remove_if(world->meshes.begin(),
|
||||
world->meshes.end(),
|
||||
[](Mesh* m){return m->tag == "cinematic";}),
|
||||
world->meshes.end());
|
||||
}
|
||||
|
||||
for(auto mesh : shot->meshes)
|
||||
world->meshes.push_back(mesh);
|
||||
|
||||
currentShot = shot;
|
||||
}
|
||||
}
|
||||
|
||||
// we have reached the end of the cinematic
|
||||
if(animationTime >= endTime) {
|
||||
currentShot = nullptr;
|
||||
|
||||
running = false;
|
||||
}
|
||||
|
||||
if(currentShot != nullptr) {
|
||||
for(auto animation : currentShot->animations) {
|
||||
unsigned int frameIndex = 0;
|
||||
for(size_t i = 0; i < animation->keyframes.size(); i++) {
|
||||
if(animationTime < animation->keyframes[i + 1].time) {
|
||||
frameIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto currentFrame = animation->keyframes[frameIndex];
|
||||
const auto nextFrame = animation->keyframes[(frameIndex + 1) % animation->keyframes.size()];
|
||||
|
||||
const float delta = (animationTime - currentFrame.time) / (nextFrame.time - currentFrame.time);
|
||||
|
||||
switch(animation->property) {
|
||||
case AnimationProperty::Position:
|
||||
{
|
||||
auto pos = currentFrame.valueVec3 + delta * (nextFrame.valueVec3 - currentFrame.valueVec3);
|
||||
|
||||
if(animation->target == nullptr)
|
||||
camera.position = pos;
|
||||
else {
|
||||
animation->target->position = pos;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AnimationProperty::Target:
|
||||
{
|
||||
auto pos = currentFrame.valueVec3 + delta * (nextFrame.valueVec3 - currentFrame.valueVec3);
|
||||
|
||||
camera.target = pos;
|
||||
}
|
||||
break;
|
||||
case AnimationProperty::FoV:
|
||||
{
|
||||
auto pos = currentFrame.valueInt + delta * (nextFrame.valueInt - currentFrame.valueInt);
|
||||
camera.fov = pos;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentTime = SDL_GetTicks() / 1000.0f;
|
||||
const float deltaTime = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
|
||||
if(cinematicMode)
|
||||
animationSystem->update(cinematic, deltaTime);
|
||||
|
||||
#ifdef DEBUG
|
||||
ImGui::NewFrame();
|
||||
|
||||
|
@ -448,21 +211,18 @@ int main(int argc, char* argv[]) {
|
|||
if(SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS)
|
||||
io.MousePos = ImVec2(static_cast<float>(mouseX), static_cast<float>(mouseY));
|
||||
|
||||
ImGui::DragFloat3("Light Position", &world->lights[0]->position[0]);
|
||||
ImGui::DragFloat3("Camera Position", &camera.position[0], 0.1f);
|
||||
ImGui::DragFloat3("Target", &camera.target[0], 0.1f);
|
||||
ImGui::DragFloat("Aperture", &camera.aperture, 0.01f, 0.0f, 1.0f);
|
||||
ImGui::DragFloat("Focus Distance", &camera.focusDistance);
|
||||
ImGui::Text("dpack[2] = %f", (100 - camera.focusDistance) / 100.0f);
|
||||
ImGui::DragFloat3("Light Position", &worldManager.getCurrentWorld()->lights[0]->position[0]);
|
||||
ImGui::DragFloat3("Camera Position", &worldManager.getCurrentWorld()->camera.position[0], 0.1f);
|
||||
ImGui::DragFloat3("Target", &worldManager.getCurrentWorld()->camera.target[0], 0.1f);
|
||||
ImGui::DragFloat("Aperture", &worldManager.getCurrentWorld()->camera.aperture, 0.01f, 0.0f, 1.0f);
|
||||
ImGui::DragFloat("Focus Distance", &worldManager.getCurrentWorld()->camera.focusDistance);
|
||||
ImGui::Text("dpack[2] = %f", (100 - worldManager.getCurrentWorld()->camera.focusDistance) / 100.0f);
|
||||
|
||||
ImGui::Render();
|
||||
#endif
|
||||
|
||||
renderer->render(*world, camera, target);
|
||||
renderer->render(*worldManager.getCurrentWorld(), worldManager.getCurrentWorld()->camera, target);
|
||||
|
||||
if(cinematicMode)
|
||||
animationTime += deltaTime;
|
||||
|
||||
if(record) {
|
||||
static int frameNum = 0;
|
||||
std::string screenshotName = "frame" + std::to_string(frameNum) + ".ppm";
|
||||
|
@ -472,7 +232,7 @@ int main(int argc, char* argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
for(auto mesh : world->meshes) {
|
||||
/*for(auto mesh : world->meshes) {
|
||||
renderer->destroyMaterialBuffers(mesh->material);
|
||||
delete mesh->material;
|
||||
|
||||
|
@ -484,7 +244,7 @@ int main(int argc, char* argv[]) {
|
|||
delete light;
|
||||
}
|
||||
|
||||
delete world;
|
||||
delete world;*/
|
||||
|
||||
renderer->destroyRenderTarget(target);
|
||||
|
||||
|
|
54
src/worldmanager.cpp
Normal file
54
src/worldmanager.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include "worldmanager.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <json.hpp>
|
||||
|
||||
#include "stringutils.h"
|
||||
#include "world.h"
|
||||
#include "assetmanager.h"
|
||||
#include "mesh.h"
|
||||
#include "light.h"
|
||||
|
||||
void WorldManager::loadWorld(const std::string& path) {
|
||||
std::ifstream file("data/" + path);
|
||||
if(!file)
|
||||
std::cout << "failed to load " << path << std::endl;
|
||||
|
||||
nlohmann::json json;
|
||||
file >> json;
|
||||
|
||||
World* world = new World();
|
||||
|
||||
for(auto meshObject : json["meshes"]) {
|
||||
Mesh* mesh = assetManager.loadMesh(meshObject["path"]);
|
||||
mesh->material = assetManager.loadMaterial(meshObject["material"]);
|
||||
|
||||
auto tokens = tokenize(meshObject["position"]);
|
||||
|
||||
mesh->position[0] = atof(tokens[0].c_str());
|
||||
mesh->position[1] = atof(tokens[1].c_str());
|
||||
mesh->position[2] = atof(tokens[2].c_str());
|
||||
|
||||
world->meshes.push_back(mesh);
|
||||
}
|
||||
|
||||
for(auto lightObject : json["lights"]) {
|
||||
Light* light = new Light();
|
||||
|
||||
auto tokens = tokenize(lightObject["position"]);
|
||||
|
||||
light->position[0] = atof(tokens[0].c_str());
|
||||
light->position[1] = atof(tokens[1].c_str());
|
||||
light->position[2] = atof(tokens[2].c_str());
|
||||
|
||||
world->lights.push_back(light);
|
||||
}
|
||||
|
||||
loadedWorlds[path] = world;
|
||||
}
|
||||
|
||||
void WorldManager::switchWorld(const std::string& path) {
|
||||
currentWorld = loadedWorlds[path];
|
||||
}
|
Reference in a new issue