2019-02-19 16:16:13 +01:00
|
|
|
#pragma once
|
|
|
|
|
2019-03-16 20:12:35 +01:00
|
|
|
#include <assert.h>
|
2019-03-15 16:34:17 +01:00
|
|
|
#include <chrono>
|
2019-02-19 16:16:13 +01:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <ctime>
|
|
|
|
#include <fstream>
|
2019-03-15 16:34:17 +01:00
|
|
|
#include <glm/glm.hpp>
|
|
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
|
|
#include <glm/mat4x4.hpp>
|
2019-03-15 18:06:49 +01:00
|
|
|
#include <map>
|
2019-03-15 16:34:17 +01:00
|
|
|
#include <stack>
|
|
|
|
#include <stdbool.h>
|
2019-03-15 18:06:49 +01:00
|
|
|
#include <utilities/glutils.h>
|
2019-03-15 16:34:17 +01:00
|
|
|
#include <utilities/shader.hpp>
|
2019-03-19 20:13:51 +01:00
|
|
|
#include <utilities/material.hpp>
|
2019-03-15 16:34:17 +01:00
|
|
|
#include <vector>
|
2019-02-19 16:16:13 +01:00
|
|
|
|
2019-03-17 15:17:44 +01:00
|
|
|
using glm::vec2;
|
2019-03-15 18:06:49 +01:00
|
|
|
using glm::vec3;
|
2019-03-18 11:48:11 +01:00
|
|
|
using glm::vec4;
|
2019-03-15 18:06:49 +01:00
|
|
|
using glm::mat4;
|
|
|
|
using std::map;
|
|
|
|
using std::vector;
|
|
|
|
typedef unsigned int uint;
|
|
|
|
|
2019-02-19 16:16:13 +01:00
|
|
|
enum SceneNodeType {
|
2019-03-16 20:12:35 +01:00
|
|
|
GEOMETRY,
|
|
|
|
POINT_LIGHT,
|
|
|
|
SPOT_LIGHT,
|
2019-02-19 16:16:13 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct SceneNode {
|
2019-03-15 18:06:49 +01:00
|
|
|
SceneNode(SceneNodeType type = GEOMETRY) {
|
|
|
|
nodeType = type;
|
2019-03-14 12:43:41 +01:00
|
|
|
}
|
2019-03-15 18:06:49 +01:00
|
|
|
|
2019-03-18 11:48:11 +01:00
|
|
|
void setMesh(const Mesh* mesh) {
|
|
|
|
static map<const Mesh*, int> cache;
|
2019-03-15 18:06:49 +01:00
|
|
|
|
|
|
|
if (cache.find(mesh) == cache.end())
|
2019-03-16 20:12:35 +01:00
|
|
|
cache[mesh] = generateBuffer(*mesh, isNormalMapped || isDisplacementMapped);
|
2019-03-15 18:06:49 +01:00
|
|
|
|
|
|
|
vertexArrayObjectID = cache[mesh];
|
|
|
|
VAOIndexCount = mesh->indices.size();
|
2019-03-19 20:11:52 +01:00
|
|
|
isVertexColored = ! mesh->colors.empty();
|
2019-02-19 16:16:13 +01:00
|
|
|
}
|
2019-03-19 20:11:52 +01:00
|
|
|
void setTexture(
|
|
|
|
const PNGImage* diffuse,
|
|
|
|
const PNGImage* normal=nullptr,
|
|
|
|
const PNGImage* displacement=nullptr,
|
|
|
|
const PNGImage* reflection=nullptr,
|
|
|
|
bool texture_reset=true) {
|
2019-03-18 11:48:11 +01:00
|
|
|
static map<const PNGImage*, int> cache;
|
2019-03-19 20:11:52 +01:00
|
|
|
if (texture_reset){
|
|
|
|
isTextured = false;
|
|
|
|
isNormalMapped = false;
|
|
|
|
isDisplacementMapped = false;
|
2019-03-19 20:15:13 +01:00
|
|
|
isReflectionMapped = false;
|
2019-03-19 20:11:52 +01:00
|
|
|
}
|
2019-02-19 16:16:13 +01:00
|
|
|
|
2019-03-16 20:12:35 +01:00
|
|
|
if (diffuse) {
|
|
|
|
if (cache.find(diffuse) == cache.end())
|
|
|
|
cache[diffuse] = generateTexture(*diffuse);
|
|
|
|
diffuseTextureID = cache[diffuse];
|
|
|
|
isTextured = true;
|
|
|
|
}
|
2019-03-15 18:06:49 +01:00
|
|
|
|
2019-03-16 20:12:35 +01:00
|
|
|
if (normal) {
|
|
|
|
if (cache.find(normal) == cache.end())
|
|
|
|
cache[normal] = generateTexture(*normal);
|
|
|
|
normalTextureID = cache[normal];
|
|
|
|
isNormalMapped = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (displacement) {
|
|
|
|
if (cache.find(displacement) == cache.end())
|
|
|
|
cache[displacement] = generateTexture(*displacement);
|
|
|
|
displacementTextureID = cache[displacement];
|
|
|
|
isDisplacementMapped = true;
|
|
|
|
}
|
2019-03-19 20:15:13 +01:00
|
|
|
|
|
|
|
if (reflection) {
|
|
|
|
if (cache.find(reflection) == cache.end())
|
|
|
|
cache[reflection] = generateTexture(*reflection);
|
|
|
|
reflectionTextureID = cache[reflection];
|
|
|
|
isReflectionMapped = true;
|
|
|
|
}
|
2019-03-15 18:06:49 +01:00
|
|
|
}
|
2019-03-19 20:11:52 +01:00
|
|
|
void setMaterial(const Material& mat, bool recursive=false) {
|
2019-03-19 20:15:13 +01:00
|
|
|
reflexiveness = mat.reflexiveness;
|
2019-03-19 20:11:52 +01:00
|
|
|
if (!mat.ignore_diffuse) diffuse_color = mat.diffuse_color;
|
|
|
|
if (!mat.ignore_emissive) emissive_color = mat.emissive_color;
|
|
|
|
if (!mat.ignore_specular) specular_color = mat.specular_color;
|
|
|
|
if (!mat.ignore_specular) shininess = mat.shininess;
|
|
|
|
setTexture(
|
|
|
|
mat.diffuse_texture,
|
|
|
|
mat.normal_texture,
|
|
|
|
mat.displacement_texture,
|
|
|
|
mat.reflection_texture,
|
|
|
|
mat.texture_reset
|
|
|
|
);
|
|
|
|
if (recursive) for (SceneNode* child : children)
|
|
|
|
child->setMaterial(mat, true);
|
|
|
|
}
|
2019-03-15 18:06:49 +01:00
|
|
|
|
2019-03-16 20:12:35 +01:00
|
|
|
// this node
|
|
|
|
SceneNodeType nodeType;
|
2019-03-15 18:06:49 +01:00
|
|
|
vector<SceneNode*> children;
|
2019-02-19 16:16:13 +01:00
|
|
|
|
2019-03-16 20:12:35 +01:00
|
|
|
// light specific:
|
2019-03-19 20:11:52 +01:00
|
|
|
uint lightID = -1;
|
|
|
|
vec3 light_color = vec3(1.0);
|
|
|
|
vec3 attenuation = vec3(1.0, 0.0, 0.001); // 1 / (x + y*l + z*l*l)
|
|
|
|
vec3 spot_direction = vec3(0.0); // in MV space, must be normalized
|
|
|
|
float spot_cuttof_cos = glm::cos(glm::radians(1.5));
|
2019-03-16 20:12:35 +01:00
|
|
|
SceneNode* targeted_by = nullptr; // spot will follow this node
|
|
|
|
|
2019-02-19 16:16:13 +01:00
|
|
|
// The node's position and rotation relative to its parent
|
2019-03-16 16:33:20 +01:00
|
|
|
vec3 position = vec3(0, 0, 0);
|
2019-03-16 20:12:35 +01:00
|
|
|
vec3 rotation = vec3(0, 0, 0); // also used as spot-target
|
2019-03-16 16:33:20 +01:00
|
|
|
vec3 scale = vec3(1, 1, 1);
|
2019-03-16 20:12:35 +01:00
|
|
|
vec3 referencePoint = vec3(0, 0, 0); // center of rotation, in model space
|
2019-02-19 16:16:13 +01:00
|
|
|
|
2019-03-15 18:06:49 +01:00
|
|
|
// VAO IDs refering to a loaded Mesh and its length
|
2019-03-16 16:33:20 +01:00
|
|
|
int vertexArrayObjectID = -1;
|
|
|
|
uint VAOIndexCount = 0;
|
2019-03-16 20:12:35 +01:00
|
|
|
|
2019-03-19 20:11:52 +01:00
|
|
|
// textures and materials
|
|
|
|
float opacity = 1.0;
|
|
|
|
float shininess = 1.0; // specular power
|
2019-03-19 20:15:13 +01:00
|
|
|
float reflexiveness = 0.0; // 0 is no reflection, 1 is a mirror. Negative value will have it multiply with base instead
|
2019-03-19 20:11:52 +01:00
|
|
|
vec3 diffuse_color = vec3(1.0);
|
|
|
|
vec3 emissive_color = vec3(0.5);
|
|
|
|
vec3 specular_color = vec3(0.2);
|
2019-03-17 15:17:44 +01:00
|
|
|
vec2 uvOffset = vec2(0.0, 0.0); // specular power
|
2019-03-15 18:06:49 +01:00
|
|
|
uint diffuseTextureID;
|
|
|
|
uint normalTextureID;
|
2019-03-16 20:12:35 +01:00
|
|
|
uint displacementTextureID;
|
|
|
|
float displacementCoefficient = 0.1; // in units
|
2019-03-19 20:15:13 +01:00
|
|
|
uint reflectionTextureID;
|
2019-03-16 20:12:35 +01:00
|
|
|
|
2019-03-15 18:06:49 +01:00
|
|
|
// shader flags
|
2019-03-16 20:12:35 +01:00
|
|
|
bool isTextured = false;
|
2019-03-19 20:11:52 +01:00
|
|
|
bool isVertexColored = false;
|
2019-03-16 20:12:35 +01:00
|
|
|
bool isNormalMapped = false;
|
|
|
|
bool isDisplacementMapped = false;
|
2019-03-19 20:15:13 +01:00
|
|
|
bool isReflectionMapped = false;
|
2019-03-16 16:33:20 +01:00
|
|
|
bool isIlluminated = true;
|
|
|
|
bool isInverted = false;
|
2019-02-19 16:16:13 +01:00
|
|
|
|
2019-03-16 20:12:35 +01:00
|
|
|
// rendering
|
|
|
|
Gloom::Shader* shader = nullptr;
|
|
|
|
mat4 MVP; // MVP
|
|
|
|
mat4 MV; // MV
|
|
|
|
mat4 MVnormal; // transpose(inverse(MV))
|
|
|
|
|
2019-02-19 16:16:13 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
// Struct for keeping track of 2D coordinates
|
|
|
|
|
|
|
|
SceneNode* createSceneNode();
|
2019-03-14 12:43:41 +01:00
|
|
|
SceneNode* createSceneNode(SceneNodeType type);
|
2019-02-19 16:16:13 +01:00
|
|
|
void addChild(SceneNode* parent, SceneNode* child);
|
|
|
|
void printNode(SceneNode* node);
|