|
|
|
@ -1,12 +1,51 @@
@@ -1,12 +1,51 @@
|
|
|
|
|
#include "level.h" |
|
|
|
|
#include "entity.h" |
|
|
|
|
#include "player.h" |
|
|
|
|
#include <glm/ext/vector_float3.hpp> |
|
|
|
|
|
|
|
|
|
#include "collision.h" |
|
|
|
|
#include <optional> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define DIRECTIONAL_LIGHT 0 |
|
|
|
|
#define POINT_LIGHT 1 |
|
|
|
|
#define SPOT_LIGHT 2 |
|
|
|
|
|
|
|
|
|
std::optional<physics_model> level::physics_from_json(json p) noexcept { |
|
|
|
|
|
|
|
|
|
if (!(p.count("position") && p.count("orientation"))) { |
|
|
|
|
return {}; |
|
|
|
|
} |
|
|
|
|
try { |
|
|
|
|
// anonymous physics obj
|
|
|
|
|
glm::vec3 position {p["position"][0], p["position"][1], p["position"][2]}; |
|
|
|
|
glm::mat4 orientation = glm::mat4(1.0); // identity matrix
|
|
|
|
|
orientation = glm::rotate(orientation, (float)p["orientation"][0], glm::vec3(1,0,0)); |
|
|
|
|
orientation = glm::rotate(orientation, (float)p["orientation"][1], glm::vec3(0,1,0)); |
|
|
|
|
orientation = glm::rotate(orientation, (float)p["orientation"][2], glm::vec3(0,0,1)); |
|
|
|
|
|
|
|
|
|
std::optional<glm::vec2> aabb {}; |
|
|
|
|
|
|
|
|
|
std::vector<collision::Collider> colliders {}; |
|
|
|
|
|
|
|
|
|
if (p.count("collision")) { |
|
|
|
|
for (json c : p["collision"]) { |
|
|
|
|
std::optional<collision::Collider> res = collision::Collider::from_json(c); |
|
|
|
|
if (res) { |
|
|
|
|
fmt::print("Added collision shape: {}\n", res->get_name()); |
|
|
|
|
colliders.push_back(*res); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return physics_model {.pos = position, .orientation = orientation, .colliders=colliders}; |
|
|
|
|
|
|
|
|
|
} catch (std::exception &e) { |
|
|
|
|
return {}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
auto LIGHT_TYPES = std::unordered_map<std::string, unsigned int> {{"directional", 0}, {"point", 1}, {"spot", 2}}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -51,6 +90,31 @@ void update_lights(Shader * shader, json &j) {
@@ -51,6 +90,31 @@ void update_lights(Shader * shader, json &j) {
|
|
|
|
|
glCheckError(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void level::load_physics(json j) { |
|
|
|
|
for (auto &p: j["physics"]) { |
|
|
|
|
auto id = phys_meshes.size(); |
|
|
|
|
auto id_slug = fmt::format("{}", id); |
|
|
|
|
if (j.count("id")) { |
|
|
|
|
id_slug = j.at("id"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (phys_ids.count(id_slug)) { |
|
|
|
|
fmt::print("warn::level::load_physics overwritten physics mesh: '{}'\n", id_slug); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto model = physics_from_json(p); |
|
|
|
|
if (model) { |
|
|
|
|
phys_meshes.push_back(*model); |
|
|
|
|
phys_ids.insert({id_slug, id}); |
|
|
|
|
} else { |
|
|
|
|
fmt::print("warn::level::load_physics failed to load physics {}\n", id_slug); |
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void level::load_entities(json j) { |
|
|
|
|
int i = 0;
|
|
|
|
|
for (auto &m: j["entities"]) { |
|
|
|
@ -59,9 +123,14 @@ void level::load_entities(json j) {
@@ -59,9 +123,14 @@ void level::load_entities(json j) {
|
|
|
|
|
bool model = false; |
|
|
|
|
bool physics = false; |
|
|
|
|
|
|
|
|
|
std::string entity_id = fmt::format("{}", i); |
|
|
|
|
if (m.count("id")) { |
|
|
|
|
entity_id = m.at("id"); |
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m.count("draw")) { |
|
|
|
|
model = true; |
|
|
|
|
if (m["draw"].count("model")) { |
|
|
|
|
model = true; |
|
|
|
|
e.model = model_ids.at(m["draw"].at("model")); |
|
|
|
|
e.type = entity_type::STATIC_MESH; |
|
|
|
|
} else if (m["draw"].count("billboardmodel")) { |
|
|
|
@ -72,27 +141,33 @@ void level::load_entities(json j) {
@@ -72,27 +141,33 @@ void level::load_entities(json j) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (m.count("physics")) { |
|
|
|
|
|
|
|
|
|
auto p = m["physics"]; |
|
|
|
|
physics = true; |
|
|
|
|
glm::vec3 position {p["position"][0], p["position"][1], p["position"][2]}; |
|
|
|
|
glm::mat4 orientation = glm::mat4(1.0); // identity matrix
|
|
|
|
|
orientation = glm::rotate(orientation, (float)p["orientation"][0], glm::vec3(1,0,0)); |
|
|
|
|
orientation = glm::rotate(orientation, (float)p["orientation"][1], glm::vec3(0,1,0)); |
|
|
|
|
orientation = glm::rotate(orientation, (float)p["orientation"][2], glm::vec3(0,0,1)); |
|
|
|
|
|
|
|
|
|
physics_model entity_physics {.pos = position, .orientation = orientation}; |
|
|
|
|
|
|
|
|
|
int model_id = phys_meshes.size(); |
|
|
|
|
phys_meshes.emplace_back(entity_physics); |
|
|
|
|
e.physics = model_id; |
|
|
|
|
physics_model entity_physics; |
|
|
|
|
if (p.count("id")) { |
|
|
|
|
e.physics = phys_ids[p.at("id")]; |
|
|
|
|
} else { |
|
|
|
|
auto ph = physics_from_json(p); |
|
|
|
|
if (ph) { |
|
|
|
|
entity_physics = *ph; |
|
|
|
|
int model_id = phys_meshes.size(); |
|
|
|
|
phys_meshes.emplace_back(entity_physics); |
|
|
|
|
e.physics = model_id; |
|
|
|
|
|
|
|
|
|
auto physics_id = fmt::format("{}", entity_id); |
|
|
|
|
phys_ids.insert({physics_id, model_id}); |
|
|
|
|
} else { |
|
|
|
|
throw std::exception {}; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (model && physics) { |
|
|
|
|
auto phys = phys_meshes.at(e.physics); |
|
|
|
|
auto model = models.at(e.model); |
|
|
|
|
} else { |
|
|
|
|
fmt::print("warn::level inivisible entity"); |
|
|
|
|
if (! (model && physics)) { |
|
|
|
|
fmt::print("warn::level invisible entity"); |
|
|
|
|
} |
|
|
|
|
entities.push_back(e); |
|
|
|
|
} |
|
|
|
@ -109,6 +184,8 @@ level::level(const std::string &json_source)
@@ -109,6 +184,8 @@ level::level(const std::string &json_source)
|
|
|
|
|
inp >> l; |
|
|
|
|
fmt::print("loading level{}", l["name"]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (l == nullptr) { |
|
|
|
|
A_ERROR("level | failed to parse json"); |
|
|
|
|
} |
|
|
|
@ -142,6 +219,7 @@ level::level(const std::string &json_source)
@@ -142,6 +219,7 @@ level::level(const std::string &json_source)
|
|
|
|
|
} |
|
|
|
|
stbi_set_flip_vertically_on_load(false); |
|
|
|
|
|
|
|
|
|
load_physics(l); |
|
|
|
|
load_entities(l); |
|
|
|
|
|
|
|
|
|
update_lights(shader, l); |
|
|
|
@ -161,30 +239,75 @@ level::level(const std::string &json_source)
@@ -161,30 +239,75 @@ level::level(const std::string &json_source)
|
|
|
|
|
|
|
|
|
|
void level::draw(const glm::mat4 view, const glm::mat4 projection) { |
|
|
|
|
|
|
|
|
|
std::multimap<float, int> order {}; |
|
|
|
|
// std::multimap<float, int> order {};
|
|
|
|
|
|
|
|
|
|
for (const entity &e: entities) { |
|
|
|
|
order.insert({phys_meshes[e.physics].pos.z, e.id}); |
|
|
|
|
} |
|
|
|
|
struct job { |
|
|
|
|
Mesh *m; |
|
|
|
|
physics_model phys; |
|
|
|
|
entity e; |
|
|
|
|
}; |
|
|
|
|
std::multimap<float, job> order {}; |
|
|
|
|
|
|
|
|
|
auto camera = player::get_camera(); |
|
|
|
|
auto camright = glm::vec3(view[0][0], view[1][0], view[2][0]); |
|
|
|
|
auto camup = camera->up; |
|
|
|
|
|
|
|
|
|
#ifdef SHOW_DRAW_ORDER |
|
|
|
|
static int prev = 0; |
|
|
|
|
static int ticks = 0; |
|
|
|
|
|
|
|
|
|
int timen = SDL_GetTicks() / 300; |
|
|
|
|
if (timen > ticks) { |
|
|
|
|
ticks = timen; |
|
|
|
|
prev++; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const entity &e: entities) { |
|
|
|
|
for (int i = 0; i < models[e.model]->meshes.size(); i++) { |
|
|
|
|
Mesh *m = &models[e.model]->meshes[0] + i; |
|
|
|
|
glm::vec3 pos = phys_meshes[e.physics].pos + m->average_position; |
|
|
|
|
pos = camera->pos - pos; |
|
|
|
|
float depth = glm::length(pos); |
|
|
|
|
|
|
|
|
|
order.insert({depth,
|
|
|
|
|
job {m, phys_meshes[e.physics], e} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int i = 0; |
|
|
|
|
for (auto iter = order.rbegin(); iter != order.rend(); ++iter) { |
|
|
|
|
#ifdef SHOW_DRAW_ORDER |
|
|
|
|
if (i++ >= prev % order.size() + 1) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
auto k = iter->first; |
|
|
|
|
auto v = iter->second; |
|
|
|
|
job v = iter->second; |
|
|
|
|
|
|
|
|
|
glm::mat4 draw_view = view; |
|
|
|
|
auto phys = phys_meshes[entities[v].physics]; |
|
|
|
|
auto model = v.phys.orientation; |
|
|
|
|
|
|
|
|
|
if (entities[v].type == entity_type::BILLBOARD) { |
|
|
|
|
if (v.e.type == entity_type::BILLBOARD) { |
|
|
|
|
// particle billboarding
|
|
|
|
|
// http://www.opengl-tutorial.org/intermediate-tutorials/billboards-particles/billboards/
|
|
|
|
|
phys.orientation = glm::mat4(glm::mat3(glm::inverse(view))); |
|
|
|
|
} else { |
|
|
|
|
} |
|
|
|
|
model = glm::mat4(glm::mat3(glm::inverse(view))); |
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
draw_objects(shader, {phys}, models[entities[v].model], draw_view, projection); |
|
|
|
|
setup_shader(shader, view, projection, v.phys.pos, model); |
|
|
|
|
v.m->draw(shader); |
|
|
|
|
|
|
|
|
|
// glm::mat4 draw_view = view;
|
|
|
|
|
// auto phys = phys_meshes[entities[v].physics];
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// draw_objects(shader, {phys}, models[entities[v].model], draw_view, projection);
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
@ -208,11 +331,13 @@ void level::update() {
@@ -208,11 +331,13 @@ void level::update() {
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shader->use(); |
|
|
|
|
|
|
|
|
|
update_lights(shader, l); |
|
|
|
|
entities.clear(); |
|
|
|
|
phys_meshes.clear(); |
|
|
|
|
phys_ids.clear(); |
|
|
|
|
load_physics(l); |
|
|
|
|
load_entities(l); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|