#include "pch.hpp" #include "utils/Objects/Body.h" #include #include #include namespace Archimedes { class Text { unsigned int tex; std::vector 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 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 texts) { std::vector v; std::vector 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 v; std::vector 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() / resolution)); v.push_back(d / 2.0f * glm::sin(it * 2.0f * glm::pi() / 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 v; std::vector 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 v; std::vector 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 v; std::vector 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 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 objectMap; Shader shader; Text text; private: Archimedes::VertexLayout layout = Archimedes::VertexLayout({ Archimedes::LayoutElement(Archimedes::LayoutElement::Type::Float, 3, 0, 0) }); std::unordered_map templateMap; bool goodJSON = false; unsigned int resolution = 50; json document, templates, objects, setup, cameras, lights, actions; }; }