Files
Archimedes/src/modules/Archimedes-Modules/Sandbox/JObject.h
2026-02-23 12:50:16 -06:00

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;
};
}