441 lines
13 KiB
C++
441 lines
13 KiB
C++
|
|
#include "pch.hpp"
|
|
|
|
#include "utils/Objects/Body.h"
|
|
|
|
#include <stb/stb_truetype.h>
|
|
#include <stb/stb_image_write.h>
|
|
|
|
#include <GL/glew.h>
|
|
|
|
namespace Archimedes {
|
|
|
|
class Text {
|
|
|
|
unsigned int tex;
|
|
|
|
std::vector<unsigned char> ttf;
|
|
|
|
stbtt_bakedchar bcdata[96];
|
|
|
|
std::string fontPath;
|
|
|
|
std::string vs = "#version 430 core\n"
|
|
"layout (location = 0) in vec3 aPos;\n"
|
|
"layout (location = 1) in vec2 aTex;\n"
|
|
"uniform mat4 model;\n"
|
|
"uniform mat4 view;\n"
|
|
"uniform mat4 proj;\n"
|
|
"out vec2 TexCoord;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_Position = proj * view * model * vec4(aPos.x, 1.0f - aPos.y, aPos.z, 1.0);\n"
|
|
" TexCoord = aTex;\n"
|
|
"}\0";
|
|
|
|
std::string fs = "#version 430 core\n"
|
|
"out vec4 FragColor;\n"
|
|
"in vec2 TexCoord;\n"
|
|
"uniform sampler2D tex;\n"
|
|
"uniform vec4 color;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" FragColor = vec4(color.rgb, texture(tex, TexCoord).r);\n"
|
|
"}\n\0";
|
|
|
|
|
|
public:
|
|
Shader shader;
|
|
Texture texture;
|
|
|
|
float fontSize = 200.0f;
|
|
|
|
Text() {}
|
|
~Text() {}
|
|
|
|
|
|
void textInit(std::string p) {
|
|
|
|
fontPath = p;
|
|
|
|
|
|
unsigned char temp_bitmap[1024*1024];
|
|
|
|
std::ifstream file(fontPath, std::ios::binary);
|
|
|
|
file.seekg(0, std::ios::end);
|
|
auto&& size = file.tellg();
|
|
file.seekg(0, std::ios::beg);
|
|
|
|
ttf.reserve(size);
|
|
|
|
if(!file.is_open()) {
|
|
std::cout << "ttf won't open!\n";
|
|
}
|
|
|
|
while(!file.eof()) {
|
|
|
|
ttf.push_back(file.get());
|
|
}
|
|
|
|
file.close();
|
|
|
|
stbtt_BakeFontBitmap(ttf.data(),0, fontSize, temp_bitmap,1024,1024, 32,96, bcdata);
|
|
|
|
std::vector<unsigned char> bin;
|
|
bin.reserve(1024 * 1024);
|
|
|
|
for(unsigned char c : temp_bitmap) {
|
|
bin.push_back(c);
|
|
}
|
|
|
|
texture = Texture(bin, 1024, 1024);
|
|
|
|
shader = Shader(vs, fs, Shader::LoadType::FromSource);
|
|
}
|
|
|
|
Body* genText(std::vector<std::string> texts) {
|
|
|
|
std::vector<float> v;
|
|
std::vector<unsigned int> i;
|
|
|
|
float x = 0, y = 0, oX = 0, dY = fontSize;
|
|
|
|
unsigned int k = 0;
|
|
|
|
for(std::string text : texts) {
|
|
for(unsigned int j = 0; j < text.length(); j++) {
|
|
if (text[j] >= 32) {
|
|
stbtt_aligned_quad q;
|
|
stbtt_GetBakedQuad(bcdata, 1024,1024, text[j]-32, &x,&y,&q,0);//1=opengl & d3d10+,0=d3d9
|
|
|
|
v.push_back(q.x0);
|
|
v.push_back(q.y0);
|
|
v.push_back(0.0f);
|
|
|
|
v.push_back(q.s0);
|
|
v.push_back(q.t0);
|
|
|
|
|
|
|
|
v.push_back(q.x1);
|
|
v.push_back(q.y0);
|
|
v.push_back(0.0f);
|
|
|
|
v.push_back(q.s1);
|
|
v.push_back(q.t0);
|
|
|
|
|
|
|
|
|
|
v.push_back(q.x1);
|
|
v.push_back(q.y1);
|
|
v.push_back(0.0f);
|
|
|
|
v.push_back(q.s1);
|
|
v.push_back(q.t1);
|
|
|
|
|
|
|
|
|
|
v.push_back(q.x0);
|
|
v.push_back(q.y1);
|
|
v.push_back(0.0f);
|
|
|
|
v.push_back(q.s0);
|
|
v.push_back(q.t1);
|
|
|
|
i.push_back(k * 4);
|
|
i.push_back(k * 4 + 1);
|
|
i.push_back(k * 4 + 2);
|
|
i.push_back(k * 4 + 2);
|
|
i.push_back(k * 4 + 3);
|
|
i.push_back(k * 4);
|
|
k++;
|
|
}
|
|
}
|
|
|
|
x = oX;
|
|
y += dY;
|
|
}
|
|
|
|
|
|
return new Body(
|
|
VertexBuffer(v),
|
|
IndexArray(i),
|
|
VertexLayout({
|
|
LayoutElement(LayoutElement::Type::Float, 3, 5 * sizeof(float), 0),
|
|
LayoutElement(LayoutElement::Type::Float, 2, 5 * sizeof(float), 3 * sizeof(float))
|
|
}),
|
|
shader,
|
|
texture,
|
|
RenderMode::Triangles,
|
|
glm::scale(glm::mat4(1.0f), glm::vec3(0.1f))
|
|
);
|
|
}
|
|
};
|
|
|
|
using json = nlohmann::json;
|
|
|
|
class JObject {
|
|
|
|
public:
|
|
JObject() {}
|
|
|
|
void load(std::string pathJSON, std::string pathFont) {
|
|
std::ifstream file(pathJSON);
|
|
if (!file.is_open()) goodJSON = false;
|
|
document = json::parse(file);
|
|
file.close();
|
|
goodJSON = true;
|
|
templates = document["Templates"];
|
|
objects = document["Objects"];
|
|
setup = document["Set Up"];
|
|
cameras = document["Cameras"];
|
|
lights = document["Lights"];
|
|
actions = document["Actions"];
|
|
|
|
text.textInit(pathFont);
|
|
}
|
|
|
|
bool isValid() const { return goodJSON; }
|
|
|
|
Body* createCircle(json& element, std::string name) {
|
|
std::vector<float> v;
|
|
std::vector<unsigned int> i;
|
|
|
|
float d = element["diameter"];
|
|
|
|
for(int it = 0; it < resolution; it++) {
|
|
v.push_back(d / 2.0f * glm::cos(it * 2.0f * glm::pi<float>() / resolution));
|
|
v.push_back(d / 2.0f * glm::sin(it * 2.0f * glm::pi<float>() / resolution));
|
|
v.push_back(0.0f);
|
|
|
|
i.push_back(it);
|
|
}
|
|
|
|
return new Body(
|
|
VertexBuffer(v),
|
|
IndexArray(i),
|
|
layout,
|
|
shader,
|
|
std::nullopt,
|
|
RenderMode::ConnectedLinesLooped
|
|
);
|
|
|
|
}
|
|
|
|
Body* createSquare(json& element, std::string name) {
|
|
std::vector<float> v;
|
|
std::vector<unsigned int> i;
|
|
|
|
float width = element["width"];
|
|
|
|
v.push_back(width / 2.0f);
|
|
v.push_back(width / 2.0f);
|
|
v.push_back(0.0f);
|
|
|
|
i.push_back(0);
|
|
|
|
v.push_back(-width / 2.0f);
|
|
v.push_back(width / 2.0f);
|
|
v.push_back(0.0f);
|
|
|
|
i.push_back(1);
|
|
|
|
v.push_back(-width / 2.0f);
|
|
v.push_back(-width / 2.0f);
|
|
v.push_back(0.0f);
|
|
|
|
i.push_back(2);
|
|
|
|
v.push_back(width / 2.0f);
|
|
v.push_back(-width / 2.0f);
|
|
v.push_back(0.0f);
|
|
|
|
i.push_back(3);
|
|
|
|
return new Body(
|
|
VertexBuffer(v),
|
|
IndexArray(i),
|
|
layout,
|
|
shader,
|
|
std::nullopt,
|
|
RenderMode::ConnectedLinesLooped
|
|
);
|
|
}
|
|
|
|
Body* createRect(json& element, std::string name) {
|
|
std::vector<float> v;
|
|
std::vector<unsigned int> i;
|
|
|
|
float width = element["width"];
|
|
float height = element["height"];
|
|
|
|
v.push_back(width / 2.0f);
|
|
v.push_back(height / 2.0f);
|
|
v.push_back(0.0f);
|
|
|
|
i.push_back(0);
|
|
|
|
v.push_back(-width / 2.0f);
|
|
v.push_back(height / 2.0f);
|
|
v.push_back(0.0f);
|
|
|
|
i.push_back(1);
|
|
|
|
v.push_back(-width / 2.0f);
|
|
v.push_back(-height / 2.0f);
|
|
v.push_back(0.0f);
|
|
|
|
i.push_back(2);
|
|
|
|
v.push_back(width / 2.0f);
|
|
v.push_back(-height / 2.0f);
|
|
v.push_back(0.0f);
|
|
|
|
i.push_back(3);
|
|
|
|
return new Body(
|
|
VertexBuffer(v),
|
|
IndexArray(i),
|
|
layout,
|
|
shader,
|
|
std::nullopt,
|
|
RenderMode::ConnectedLinesLooped
|
|
);
|
|
}
|
|
|
|
Body* createPoly(json& element, std::string name) {
|
|
std::vector<float> v;
|
|
std::vector<unsigned int> i;
|
|
|
|
json coords = element["coords"];
|
|
|
|
unsigned int j = 0;
|
|
for(json::const_iterator it = coords.cbegin(); it != coords.cend(); it++) {
|
|
json c = *it;
|
|
v.push_back(c["x"]);
|
|
v.push_back(c["y"]);
|
|
v.push_back(c["z"]);
|
|
|
|
i.push_back(j++);
|
|
}
|
|
|
|
return new Body(
|
|
VertexBuffer(v),
|
|
IndexArray(i),
|
|
layout,
|
|
shader,
|
|
std::nullopt,
|
|
RenderMode::ConnectedLinesLooped
|
|
);
|
|
}
|
|
|
|
Body* createText(json& element, std::string name) {
|
|
//do something
|
|
json lines = element["text"];
|
|
|
|
std::vector<std::string> theText;
|
|
for (json::const_iterator it = lines.cbegin(); it != lines.cend(); it++)
|
|
{
|
|
std::string line = *it;
|
|
theText.push_back(line);
|
|
}
|
|
|
|
return text.genText(theText);
|
|
}
|
|
|
|
void buildObjects() {
|
|
|
|
|
|
for (json::const_iterator it = objects.cbegin(); it != objects.cend(); it++)
|
|
{
|
|
json element = *it;
|
|
std::string name = element["name"];
|
|
std::string type = element["type"];
|
|
if (type == "CIRCLE") {
|
|
objectMap[name] = createCircle(element, name);
|
|
}
|
|
if (type == "SQUARE") {
|
|
objectMap[name] = createSquare(element, name);
|
|
}
|
|
if (type == "RECTANGLE") {
|
|
objectMap[name] = createRect(element, name);
|
|
}
|
|
if (type == "POLYGON") {
|
|
objectMap[name] = createPoly(element, name);
|
|
}
|
|
if (type == "TEXT") {
|
|
objectMap[name] = createText(element, name);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void objectActions()
|
|
{
|
|
for (json::const_iterator it = setup.cbegin(); it != setup.cend(); it++)
|
|
{
|
|
json element = *it;
|
|
std::string name = element["name"];
|
|
Body* o = objectMap[name];
|
|
if (o == nullptr) continue;
|
|
if (element.contains("moveto"))
|
|
{
|
|
json moveTo = element["moveto"];
|
|
float x = moveTo["x"];
|
|
float y = moveTo["y"];
|
|
float z = moveTo["z"];
|
|
o->moveTo(glm::vec3(x, y, z));
|
|
}
|
|
if (element.contains("moveby"))
|
|
{
|
|
json moveBy = element["moveby"];
|
|
float x = moveBy["x"];
|
|
float y = moveBy["y"];
|
|
float z = moveBy["z"];
|
|
o->moveRel(glm::vec3(x, y, z));
|
|
}
|
|
if (element.contains("rotateto"))
|
|
{
|
|
json rotateTo = element["rotateto"];
|
|
float p = rotateTo["pitch"];
|
|
float y = rotateTo["yaw"];
|
|
float r = rotateTo["roll"];
|
|
o->rotateTo(glm::vec3(p, y, r));
|
|
}
|
|
if (element.contains("rotateby"))
|
|
{
|
|
json rotateBy = element["rotateby"];
|
|
float p = rotateBy["pitch"];
|
|
float y = rotateBy["yaw"];
|
|
float r = rotateBy["roll"];
|
|
o->rotateRel(glm::vec3(p, y, r));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
std::unordered_map<std::string, Body*> objectMap;
|
|
Shader shader;
|
|
|
|
Text text;
|
|
private:
|
|
|
|
Archimedes::VertexLayout layout = Archimedes::VertexLayout({
|
|
Archimedes::LayoutElement(Archimedes::LayoutElement::Type::Float, 3, 0, 0)
|
|
});
|
|
|
|
std::unordered_map<std::string, Body> templateMap;
|
|
|
|
bool goodJSON = false;
|
|
|
|
|
|
unsigned int resolution = 50;
|
|
|
|
json document, templates, objects, setup, cameras, lights, actions;
|
|
};
|
|
}
|
|
|