Compare commits
2 Commits
74c980adb0
...
a5c21ea30d
| Author | SHA1 | Date | |
|---|---|---|---|
| a5c21ea30d | |||
| ce43c56ea6 |
@@ -21,6 +21,8 @@
|
||||
glm
|
||||
nlohmann_json
|
||||
curl
|
||||
|
||||
stb
|
||||
];
|
||||
|
||||
buildPhase = ''
|
||||
|
||||
@@ -14,8 +14,8 @@ namespace Archimedes {
|
||||
public:
|
||||
Body(RenderTarget rt, glm::mat4 t = glm::mat4(1.0f)) : Object(t), mesh(rt) {};
|
||||
|
||||
Body(VertexBuffer vb, IndexArray ia, VertexLayout vl, Shader s, glm::mat4 t = glm::mat4(1.0f))
|
||||
: Object(t), mesh(vb, ia, vl, s) {}
|
||||
Body(VertexBuffer vb, IndexArray ia, VertexLayout vl, Shader s, std::optional<Texture> tex = std::nullopt, RenderMode rm = RenderMode::Triangles, glm::mat4 t = glm::mat4(1.0f))
|
||||
: Object(t), mesh(vb, ia, vl, s, tex, rm) {}
|
||||
|
||||
Body() : Object(glm::mat4(1.0f)) {}
|
||||
|
||||
|
||||
@@ -19,6 +19,11 @@ namespace Archimedes {
|
||||
|
||||
~Camera() {};
|
||||
|
||||
const glm::mat4& getPerspective() { return perspective; }
|
||||
void setPerspective(const glm::mat4 m) { perspective = m; }
|
||||
|
||||
private:
|
||||
glm::mat4 perspective = glm::mat4(1.0f);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ namespace Archimedes {
|
||||
float& getScale() { return scale; }
|
||||
|
||||
const glm::mat4& getTransform() { return worldTransform; }
|
||||
void setTransform(const glm::mat4 m) { worldTransform = m; }
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -7,32 +7,82 @@
|
||||
|
||||
namespace Archimedes {
|
||||
|
||||
enum class RenderMode {
|
||||
Points,
|
||||
Lines,
|
||||
ConnectedLines,
|
||||
ConnectedLinesLooped,
|
||||
Triangles,
|
||||
Quads,
|
||||
Polygon
|
||||
};
|
||||
|
||||
class Texture {
|
||||
|
||||
public:
|
||||
Texture() {}
|
||||
Texture(std::vector<unsigned char> bin, size_t width, size_t height)
|
||||
: bin(bin), width(width), height(height) {}
|
||||
|
||||
~Texture() {}
|
||||
|
||||
const void* getBin() { return bin.data(); }
|
||||
|
||||
void setActive(bool b) { active = b; }
|
||||
const bool getActive() const { return active; }
|
||||
|
||||
size_t getWidth() { return width; }
|
||||
size_t getHeight() { return height; }
|
||||
|
||||
unsigned int id;
|
||||
|
||||
private:
|
||||
std::vector<unsigned char> bin;
|
||||
|
||||
bool active = false;
|
||||
size_t width, height;
|
||||
};
|
||||
|
||||
class LayoutElement {
|
||||
|
||||
public:
|
||||
LayoutElement(unsigned int type, size_t count) : type(type), count(count) {}
|
||||
|
||||
enum class Type {
|
||||
Float,
|
||||
UInt,
|
||||
Int,
|
||||
Double
|
||||
};
|
||||
|
||||
LayoutElement(Type type, size_t count, size_t stride, size_t offset)
|
||||
: type(type), count(count), stride(stride), offset(offset) {}
|
||||
|
||||
~LayoutElement() {}
|
||||
|
||||
unsigned int getType() const { return type; }
|
||||
|
||||
size_t getSize() const { return size; }
|
||||
Type getType() const { return type; }
|
||||
|
||||
size_t getCount() const { return count; }
|
||||
|
||||
size_t getStride() const { return stride; }
|
||||
|
||||
size_t getOffset() const { return offset; }
|
||||
|
||||
private:
|
||||
|
||||
unsigned int type;
|
||||
size_t size;
|
||||
Type type;
|
||||
size_t count;
|
||||
size_t stride;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
class VertexLayout {
|
||||
|
||||
public:
|
||||
VertexLayout() {}
|
||||
VertexLayout(std::vector<LayoutElement> elements) : elements(elements) {}
|
||||
~VertexLayout() {}
|
||||
|
||||
const std::vector<LayoutElement>& getElements() const { return elements; }
|
||||
std::vector<LayoutElement>& getElements() { return elements; }
|
||||
|
||||
private:
|
||||
std::vector<LayoutElement> elements;
|
||||
@@ -48,11 +98,15 @@ namespace Archimedes {
|
||||
|
||||
~VertexBuffer() {}
|
||||
|
||||
void setActive(bool b) { active = b; }
|
||||
const bool getActive() const { return active; }
|
||||
|
||||
const void* getData() const { return data.data(); }
|
||||
size_t getSize() const { return data.size() * sizeof(float); }
|
||||
|
||||
unsigned int id;
|
||||
private:
|
||||
bool active = false;
|
||||
std::vector<float> data;
|
||||
};
|
||||
|
||||
@@ -64,9 +118,12 @@ namespace Archimedes {
|
||||
|
||||
~VertexArray() {}
|
||||
|
||||
void setActive(bool b) { active = b; }
|
||||
const bool getActive() const { return active; }
|
||||
|
||||
unsigned int id;
|
||||
private:
|
||||
bool active = false;
|
||||
};
|
||||
|
||||
class IndexArray {
|
||||
@@ -79,11 +136,15 @@ namespace Archimedes {
|
||||
|
||||
~IndexArray() {}
|
||||
|
||||
void setActive(bool b) { active = b; }
|
||||
const bool getActive() const { return active; }
|
||||
|
||||
const void* getIndicies() const { return indices.data(); }
|
||||
size_t getCount() const { return indices.size(); }
|
||||
|
||||
unsigned int id;
|
||||
private:
|
||||
bool active = false;
|
||||
std::vector<unsigned int> indices;
|
||||
};
|
||||
|
||||
@@ -108,14 +169,15 @@ namespace Archimedes {
|
||||
void init(const std::string& vs, const std::string& fs, LoadType loadType) {
|
||||
switch(loadType) {
|
||||
case LoadType::FromSource:
|
||||
this->vs = vs;
|
||||
this->fs = fs;
|
||||
this->shader = source { vs, fs };
|
||||
break;
|
||||
case LoadType::FromBin:
|
||||
break;
|
||||
case LoadType::FromFileSource:
|
||||
this->vs = readSourceFile(vs);
|
||||
this->fs = readSourceFile(fs);
|
||||
this->shader = source {
|
||||
readSourceFile(vs),
|
||||
readSourceFile(fs)
|
||||
};
|
||||
break;
|
||||
case LoadType::FromFileBin:
|
||||
break;
|
||||
@@ -124,13 +186,47 @@ namespace Archimedes {
|
||||
}
|
||||
}
|
||||
|
||||
std::string getVSource() const { return vs; }
|
||||
std::string getFSource() const { return fs; }
|
||||
void init(const std::vector<unsigned char>& vs, const std::vector<unsigned char>& fs, LoadType loadType) {
|
||||
switch(loadType) {
|
||||
case LoadType::FromSource:
|
||||
break;
|
||||
case LoadType::FromBin:
|
||||
this->shader = bin { vs, fs };
|
||||
break;
|
||||
case LoadType::FromFileSource:
|
||||
break;
|
||||
case LoadType::FromFileBin:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setActive(bool b) { active = b; }
|
||||
const bool getActive() const { return active; }
|
||||
|
||||
std::string getVSource() const { return std::get<source>(shader).vertex; }
|
||||
std::string getFSource() const { return std::get<source>(shader).fragment; }
|
||||
|
||||
std::vector<unsigned char>& getVbin() { return std::get<bin>(shader).vertex; }
|
||||
std::vector<unsigned char>& getFbin() { return std::get<bin>(shader).fragment; }
|
||||
|
||||
unsigned int id;
|
||||
private:
|
||||
std::string vs;
|
||||
std::string fs;
|
||||
|
||||
struct source {
|
||||
std::string vertex;
|
||||
std::string fragment;
|
||||
};
|
||||
|
||||
struct bin {
|
||||
std::vector<unsigned char> vertex;
|
||||
std::vector<unsigned char> fragment;
|
||||
};
|
||||
|
||||
std::variant<source, bin> shader;
|
||||
|
||||
bool active = false;
|
||||
|
||||
std::string readSourceFile(const std::string& path) {
|
||||
|
||||
@@ -149,24 +245,39 @@ namespace Archimedes {
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
std::vector<unsigned char> readBinFile(const std::string& path) {
|
||||
|
||||
std::ifstream file(path, std::ios::binary);
|
||||
|
||||
if(!file.is_open()) {
|
||||
return std::vector<unsigned char>();
|
||||
}
|
||||
|
||||
std::vector<unsigned char> s;
|
||||
|
||||
s.reserve(10000);
|
||||
|
||||
while(!file.eof()) {
|
||||
s.push_back(file.get());
|
||||
}
|
||||
|
||||
return s;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class RenderTarget {
|
||||
|
||||
public:
|
||||
RenderTarget(const std::vector<float> data, const std::vector<unsigned int> indices, VertexLayout layout, const std::string& vs, const std::string& fs)
|
||||
: vertexBuffer(data),
|
||||
indexArray(indices),
|
||||
layout(layout),
|
||||
shader(vs, fs, Shader::LoadType::FromFileSource) {
|
||||
|
||||
}
|
||||
|
||||
RenderTarget(VertexBuffer vb, IndexArray ia, VertexLayout vl, Shader s)
|
||||
RenderTarget(VertexBuffer vb, IndexArray ia, VertexLayout vl, Shader s, std::optional<Texture> t = std::nullopt, RenderMode rm = RenderMode::Triangles)
|
||||
: vertexBuffer(vb),
|
||||
indexArray(ia),
|
||||
layout(vl),
|
||||
shader(s) {
|
||||
shader(s),
|
||||
texture(t),
|
||||
renderMode(rm) {
|
||||
|
||||
}
|
||||
|
||||
@@ -174,6 +285,18 @@ namespace Archimedes {
|
||||
|
||||
~RenderTarget() {}
|
||||
|
||||
void setup(VertexBuffer vb, IndexArray ia, VertexLayout vl, Shader s, std::optional<Texture> t = std::nullopt, RenderMode rm = RenderMode::Triangles) {
|
||||
vertexBuffer = vb;
|
||||
indexArray = ia;
|
||||
layout = vl;
|
||||
shader = s;
|
||||
texture = t;
|
||||
renderMode = rm;
|
||||
}
|
||||
|
||||
void setActive(bool b) { active = b; }
|
||||
const bool getActive() const { return active; }
|
||||
|
||||
//private:
|
||||
|
||||
VertexBuffer vertexBuffer;
|
||||
@@ -186,6 +309,12 @@ namespace Archimedes {
|
||||
|
||||
Shader shader;
|
||||
|
||||
std::optional<Texture> texture;
|
||||
|
||||
RenderMode renderMode;
|
||||
|
||||
bool active = false;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -13,13 +13,6 @@ namespace Archimedes {
|
||||
|
||||
public:
|
||||
|
||||
enum class RenderMode {
|
||||
Triangles,
|
||||
Lines,
|
||||
ConnectedLines,
|
||||
ConnectedLinesLooped,
|
||||
Points
|
||||
};
|
||||
|
||||
int w, h;
|
||||
|
||||
@@ -33,16 +26,11 @@ namespace Archimedes {
|
||||
|
||||
virtual void render() = 0;
|
||||
|
||||
virtual Shader createShader(const std::string& vs, const std::string& fs, const Shader::LoadType& lt) = 0;
|
||||
virtual void setupShader(Shader& shader) = 0;
|
||||
|
||||
virtual void useShader(Shader& shader) = 0;
|
||||
virtual void setupTexture(Texture& texture) = 0;
|
||||
|
||||
virtual RenderTarget createRenderTarget(
|
||||
VertexBuffer vb,
|
||||
IndexArray ia,
|
||||
VertexLayout layout,
|
||||
Shader& s
|
||||
) = 0;
|
||||
virtual void updateTexture(Texture& texture) = 0;
|
||||
|
||||
virtual void setupRenderTarget(RenderTarget& rt) = 0;
|
||||
|
||||
@@ -55,8 +43,7 @@ namespace Archimedes {
|
||||
const glm::mat4 world = glm::mat4(1.0f),
|
||||
const glm::mat4 view = glm::mat4(1.0f),
|
||||
const glm::mat4 proj = glm::mat4(1.0f),
|
||||
glm::vec4 color = { 1.0f, 0.0f, 1.0f, 1.0f },
|
||||
RenderMode mode = RenderMode::Triangles
|
||||
const glm::vec4 color = { 1.0f, 0.0f, 1.0f, 1.0f }
|
||||
) = 0;
|
||||
|
||||
virtual Renderer* getRendererImpl() = 0;
|
||||
|
||||
@@ -39,60 +39,7 @@ namespace Archimedes {
|
||||
|
||||
}
|
||||
|
||||
Shader createShader(const std::string& vs, const std::string& fs, const Shader::LoadType& lt) override {
|
||||
|
||||
|
||||
Shader shader(vs, fs, lt);
|
||||
|
||||
std::string vss = shader.getVSource();
|
||||
std::string fss = shader.getFSource();
|
||||
|
||||
const char* vsc = vss.c_str();
|
||||
const char* fsc = fss.c_str();
|
||||
|
||||
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexShader, 1, &vsc, NULL);
|
||||
glCompileShader(vertexShader);
|
||||
// check for shader compile errors
|
||||
int success;
|
||||
char infoLog[512];
|
||||
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
|
||||
if (!success)
|
||||
{
|
||||
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
|
||||
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
|
||||
}
|
||||
// fragment shader
|
||||
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentShader, 1, &fsc, NULL);
|
||||
glCompileShader(fragmentShader);
|
||||
// check for shader compile errors
|
||||
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
|
||||
if (!success)
|
||||
{
|
||||
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
|
||||
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
|
||||
}
|
||||
// link shaders
|
||||
unsigned int shaderProgram = glCreateProgram();
|
||||
glAttachShader(shaderProgram, vertexShader);
|
||||
glAttachShader(shaderProgram, fragmentShader);
|
||||
glLinkProgram(shaderProgram);
|
||||
// check for linking errors
|
||||
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
|
||||
if (!success) {
|
||||
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
|
||||
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
|
||||
}
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
shader.id = shaderProgram;
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
void useShader(Shader& shader) override {
|
||||
void setupShader(Shader& shader) override {
|
||||
|
||||
std::string vss = shader.getVSource();
|
||||
std::string fss = shader.getFSource();
|
||||
@@ -141,37 +88,16 @@ namespace Archimedes {
|
||||
|
||||
}
|
||||
|
||||
RenderTarget createRenderTarget(VertexBuffer vb, IndexArray ia, VertexLayout layout, Shader& s) override {
|
||||
void setupTexture(Texture& texture) override {
|
||||
glGenTextures(1, &texture.id);
|
||||
updateTexture(texture);
|
||||
}
|
||||
|
||||
auto rt = RenderTarget(vb, ia, layout, s);
|
||||
|
||||
glGenVertexArrays(1, &rt.vertexArray.id);
|
||||
|
||||
glGenBuffers(1, &rt.vertexBuffer.id);
|
||||
|
||||
glBindVertexArray(rt.vertexArray.id);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, rt.vertexBuffer.id);
|
||||
glBufferData(GL_ARRAY_BUFFER, vb.getSize(), vb.getData(), GL_STATIC_DRAW);
|
||||
|
||||
|
||||
glGenBuffers(1, &rt.indexArray.id);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rt.indexArray.id);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, rt.indexArray.getCount() * sizeof(unsigned int), rt.indexArray.getIndicies(), GL_STATIC_DRAW);
|
||||
|
||||
|
||||
glUseProgram(s.id);
|
||||
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
return rt;
|
||||
};
|
||||
void updateTexture(Texture& texture) override {
|
||||
glBindTexture(GL_TEXTURE_2D, texture.id);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture.getWidth(), texture.getHeight(), 0, GL_ALPHA, GL_UNSIGNED_BYTE, texture.getBin());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
|
||||
void setupRenderTarget(RenderTarget& rt) override {
|
||||
|
||||
@@ -181,26 +107,85 @@ namespace Archimedes {
|
||||
|
||||
glGenBuffers(1, &rt.indexArray.id);
|
||||
|
||||
|
||||
rt.vertexArray.setActive(true);
|
||||
rt.vertexBuffer.setActive(true);
|
||||
rt.indexArray.setActive(true);
|
||||
|
||||
if(rt.texture.has_value()) {
|
||||
glGenTextures(1, &rt.texture.value().id);
|
||||
rt.texture.value().setActive(true);
|
||||
}
|
||||
|
||||
|
||||
updateRenderTarget(rt);
|
||||
|
||||
rt.setActive(true);
|
||||
};
|
||||
|
||||
void updateRenderTarget(RenderTarget& rt) override {
|
||||
|
||||
glBindVertexArray(rt.vertexArray.id);
|
||||
if(rt.vertexArray.getActive()) {
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, rt.vertexBuffer.id);
|
||||
glBufferData(GL_ARRAY_BUFFER, rt.vertexBuffer.getSize(), rt.vertexBuffer.getData(), GL_STATIC_DRAW);
|
||||
glBindVertexArray(rt.vertexArray.id);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rt.indexArray.id);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, rt.indexArray.getCount() * sizeof(unsigned int), rt.indexArray.getIndicies(), GL_STATIC_DRAW);
|
||||
if(rt.vertexBuffer.getActive()) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, rt.vertexBuffer.id);
|
||||
glBufferData(GL_ARRAY_BUFFER, rt.vertexBuffer.getSize(), rt.vertexBuffer.getData(), GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
glUseProgram(rt.shader.id);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
if(rt.indexArray.getActive()) {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, rt.indexArray.id);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, rt.indexArray.getCount() * sizeof(unsigned int), rt.indexArray.getIndicies(), GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
if(rt.texture.has_value()) {
|
||||
if(rt.texture.value().getActive()) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, rt.texture.value().id);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, rt.texture.value().getWidth(), rt.texture.value().getHeight(), 0, GL_ALPHA, GL_UNSIGNED_BYTE, rt.texture.value().getBin());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
if(rt.shader.getActive()) {
|
||||
glUseProgram(rt.shader.id);
|
||||
}
|
||||
|
||||
|
||||
unsigned int i = 0;
|
||||
for(LayoutElement e : rt.layout.getElements()) {
|
||||
|
||||
switch(e.getType()) {
|
||||
case LayoutElement::Type::Float:
|
||||
glVertexAttribPointer(i, e.getCount(), GL_FLOAT, GL_FALSE, e.getStride(), (void*)e.getOffset());
|
||||
glEnableVertexAttribArray(i);
|
||||
break;
|
||||
case LayoutElement::Type::Double:
|
||||
glVertexAttribPointer(i, e.getCount(), GL_DOUBLE, GL_FALSE, e.getStride(), (void*)e.getOffset());
|
||||
glEnableVertexAttribArray(i);
|
||||
break;
|
||||
case LayoutElement::Type::Int:
|
||||
glVertexAttribPointer(i, e.getCount(), GL_INT, GL_FALSE, e.getStride(), (void*)e.getOffset());
|
||||
glEnableVertexAttribArray(i);
|
||||
break;
|
||||
case LayoutElement::Type::UInt:
|
||||
glVertexAttribPointer(i, e.getCount(), GL_UNSIGNED_INT, GL_FALSE, e.getStride(), (void*)e.getOffset());
|
||||
glEnableVertexAttribArray(i);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -209,6 +194,12 @@ namespace Archimedes {
|
||||
glDeleteVertexArrays(1, &rt.vertexArray.id);
|
||||
glDeleteBuffers(1, &rt.vertexBuffer.id);
|
||||
glDeleteBuffers(1, &rt.indexArray.id);
|
||||
|
||||
rt.vertexArray.setActive(false);
|
||||
rt.vertexBuffer.setActive(false);
|
||||
rt.indexArray.setActive(false);
|
||||
|
||||
rt.setActive(false);
|
||||
};
|
||||
|
||||
void draw(
|
||||
@@ -216,8 +207,7 @@ namespace Archimedes {
|
||||
const glm::mat4 world = glm::mat4(1.0f),
|
||||
const glm::mat4 view = glm::mat4(1.0f),
|
||||
const glm::mat4 proj = glm::mat4(1.0f),
|
||||
glm::vec4 color = { 1.0f, 0.0f, 1.0f, 1.0f },
|
||||
RenderMode mode = RenderMode::Triangles
|
||||
const glm::vec4 color = { 1.0f, 0.0f, 1.0f, 1.0f }
|
||||
) override {
|
||||
|
||||
glUseProgram(rt.shader.id);
|
||||
@@ -234,9 +224,21 @@ namespace Archimedes {
|
||||
unsigned int colorLoc = glGetUniformLocation(rt.shader.id, "color");
|
||||
glUniform4f(colorLoc, color.r, color.g, color.b, color.a);
|
||||
|
||||
|
||||
if(rt.texture.has_value()) {
|
||||
if(rt.texture.value().getActive()) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, rt.texture.value().id);
|
||||
|
||||
glUniform1i(glGetUniformLocation(rt.shader.id, "tex"), 0);
|
||||
}
|
||||
}
|
||||
|
||||
glBindVertexArray(rt.vertexArray.id);
|
||||
|
||||
switch(mode) {
|
||||
switch(rt.renderMode) {
|
||||
case RenderMode::Triangles:
|
||||
glDrawElements(GL_TRIANGLES, rt.indexArray.getCount(), GL_UNSIGNED_INT, nullptr);
|
||||
break;
|
||||
@@ -249,6 +251,12 @@ namespace Archimedes {
|
||||
case RenderMode::ConnectedLinesLooped:
|
||||
glDrawElements(GL_LINE_LOOP, rt.indexArray.getCount(), GL_UNSIGNED_INT, nullptr);
|
||||
break;
|
||||
case RenderMode::Quads:
|
||||
glDrawElements(GL_QUADS, rt.indexArray.getCount(), GL_UNSIGNED_INT, nullptr);
|
||||
break;
|
||||
case RenderMode::Polygon:
|
||||
glDrawElements(GL_POLYGON, rt.indexArray.getCount(), GL_UNSIGNED_INT, nullptr);
|
||||
break;
|
||||
case RenderMode::Points:
|
||||
glDrawElements(GL_POINTS, rt.indexArray.getCount(), GL_UNSIGNED_INT, nullptr);
|
||||
break;
|
||||
|
||||
@@ -1,76 +1,278 @@
|
||||
|
||||
#include "pch.hpp"
|
||||
|
||||
#include "utils/Objects/Body.h"
|
||||
|
||||
#include <stb/stb_truetype.h>
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
namespace Archimedes {
|
||||
|
||||
Body readOBJ(std::string path, Shader shader) {
|
||||
class Text {
|
||||
|
||||
std::ifstream file(path);
|
||||
unsigned int tex;
|
||||
|
||||
if(!file.is_open()) return Body();
|
||||
std::vector<unsigned char> ttf;
|
||||
stbtt_bakedchar cdata[96];
|
||||
|
||||
std::string s;
|
||||
std::string fontPath;
|
||||
|
||||
std::vector<float> verticies;
|
||||
std::vector<unsigned int> indicies;
|
||||
std::string vs = "#version 330 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, aPos.y, aPos.z, 1.0);\n"
|
||||
" TexCoord = aTex;\n"
|
||||
"}\0";
|
||||
|
||||
unsigned int i = 0;
|
||||
unsigned int j = 0;
|
||||
std::string fs = "#version 330 core\n"
|
||||
"out vec4 FragColor;\n"
|
||||
"in vec2 TexCoord;\n"
|
||||
"uniform sampler2D tex;\n"
|
||||
"uniform vec4 color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" FragColor = vec4(0.6f, 0.1f, 0.1f, texture(tex, TexCoord).a);\n"
|
||||
//" FragColor = vec4(1.0f);\n"
|
||||
"}\n\0";
|
||||
|
||||
float point;
|
||||
unsigned int idx;
|
||||
|
||||
while(!file.eof()) {
|
||||
getline(file, s, ' ');
|
||||
public:
|
||||
Shader shader;
|
||||
Texture texture;
|
||||
|
||||
//std::cout << "\nline start: " << s << std::endl;
|
||||
Text() {}
|
||||
~Text() {}
|
||||
|
||||
if(s == "v") {
|
||||
file >> point;
|
||||
verticies.push_back(point);
|
||||
//std::cout << "point1: " << point << std::endl;
|
||||
//////////////////////////////////////
|
||||
|
||||
file >> point;
|
||||
verticies.push_back(point);
|
||||
//std::cout << "point2: " << point << std::endl;
|
||||
// Load a TTF file into a texture and return the character data.
|
||||
stbtt_packedchar* LoadFont(const char* filename) {
|
||||
// Load TTF file into memory.
|
||||
std::ifstream file(filename, std::ios::ate | std::ios::binary);
|
||||
size_t fileSize = (size_t)file.tellg();
|
||||
char* ttfData = (char*)calloc(fileSize + 1, sizeof(char));
|
||||
file.seekg(0);
|
||||
file.read(ttfData, fileSize);
|
||||
file.close();
|
||||
|
||||
file >> point;
|
||||
verticies.push_back(point);
|
||||
//std::cout << "point3: " << point << std::endl;
|
||||
// Pack TTF into pixel data using stb_truetype.
|
||||
stbtt_pack_context packContext;
|
||||
stbtt_packedchar *charData = (stbtt_packedchar*)calloc(126, sizeof(stbtt_packedchar));
|
||||
unsigned char* pixels = (unsigned char*)calloc(1024 * 1024, sizeof(char));
|
||||
stbtt_PackBegin(&packContext, pixels, 1024, 1024, 1024, 1, NULL);
|
||||
|
||||
//std::cout << "index: " << j << std::endl;
|
||||
// Pack unicode codepoints 0 to 125 into the texture and character data. If a different starting
|
||||
// point than 0 is picked then lookups in charData array must be offset by that number.
|
||||
// With 0-125 the uppercase A will be at charData[65].
|
||||
// With 32-125 the uppercase A will be at charData[65-32].
|
||||
stbtt_PackFontRange(&packContext, (unsigned char*)ttfData, 0, 200.0f, 0, 125, charData);
|
||||
stbtt_PackEnd(&packContext);
|
||||
|
||||
getline(file, s);
|
||||
//file.ignore();
|
||||
} else if(s == "f") {
|
||||
// Create OpenGL texture with the font pack pixel data.
|
||||
// Only uses one color channel since font data is a monochrome alpha mask.
|
||||
GLuint fontTexture;
|
||||
glGenTextures(1, &fontTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, fontTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, 1024, 1024, 0, GL_RED, GL_UNSIGNED_BYTE, pixels);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
file >> idx;
|
||||
indicies.push_back(--idx);
|
||||
file.ignore(5, ' ');
|
||||
return charData;
|
||||
}
|
||||
|
||||
file >> idx;
|
||||
indicies.push_back(--idx);
|
||||
file.ignore(5, ' ');
|
||||
// Calculate pixel width of a string.
|
||||
float TextWidth(const char* text, float height, stbtt_packedchar *charData) {
|
||||
float w = 0.0f;
|
||||
|
||||
file >> idx;
|
||||
indicies.push_back(--idx);
|
||||
getline(file, s);
|
||||
for (int i = 0; i < strlen(text); i++) {
|
||||
stbtt_packedchar c = charData[text[i]];
|
||||
w += c.xadvance;
|
||||
}
|
||||
// Scale width by rendered height to texture generated height ratio for final size.
|
||||
return w * (height / 200.0f);
|
||||
}
|
||||
|
||||
} else {
|
||||
getline(file, s);
|
||||
|
||||
// Render string using glDrawArrays.
|
||||
// X indicates the leftmost, center or rightmost point of the based on align (0:left, 1:center, 2:rigght).
|
||||
// Y is the baseline of the text.
|
||||
void RenderString(const char* text, float x, float y, float height, int align, stbtt_packedchar *charData, GLuint program) {
|
||||
// Scale of actual text compared to size on stb_truetype generated texture.
|
||||
float scale = height / 200.0f;
|
||||
|
||||
// Resolution of window/display for shader position calculations.
|
||||
float resolution[2] = { 1024, 1024 };
|
||||
|
||||
float position[2] = {x, y};
|
||||
if (align == 1) {
|
||||
// Center align
|
||||
position[0] -= TextWidth(text, height, charData) / 2.0f;
|
||||
} else if (align == 2) {
|
||||
// Right align
|
||||
position[0] -= TextWidth(text, height, charData);
|
||||
}
|
||||
|
||||
glUniform2fv(glGetUniformLocation(program, "resolution"), 1, resolution);
|
||||
for (int i = 0; i < strlen(text); i++) {
|
||||
// Lookup current character data from stb_truetype.
|
||||
stbtt_packedchar c = charData[text[i]];
|
||||
|
||||
// Position of character in texture.
|
||||
float charPosition[4] = {static_cast<float>(c.x0), static_cast<float>(c.y0), static_cast<float>(c.x1), static_cast<float>(c.y1)};
|
||||
|
||||
// Find the actual size of character since fonts can be variable width.
|
||||
// 'M' usually is wider than '!', 'L' taller than 'o', etc.
|
||||
// Calculated by substracting start-offset from end-offset.
|
||||
// xoff is start offset from the left.
|
||||
// xoff2 is end offset from the left.
|
||||
// yoff is start offset from the baseline (will be negative if above baseline).
|
||||
// yoff2 is end offset from the baseline.
|
||||
float size[2] = {(c.xoff2 - c.xoff) * scale, (c.yoff2 - c.yoff) * scale};
|
||||
|
||||
// The actual position of character based on its offset form left/baseline.
|
||||
float renderPos[2] = {position[0] + c.xoff * scale, position[1] - c.yoff2 * scale};
|
||||
|
||||
glUniform4fv(glGetUniformLocation(program, "charPosition"), 1, charPosition);
|
||||
glUniform2fv(glGetUniformLocation(program, "position"), 1, renderPos);
|
||||
glUniform2fv(glGetUniformLocation(program, "size"), 1, size);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
// Advance x position to start of next character.
|
||||
position[0] += c.xadvance * scale;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////
|
||||
|
||||
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, 200.0f, temp_bitmap,1024,1024, 32,96, cdata);
|
||||
|
||||
std::vector<unsigned char> bin;
|
||||
bin.reserve(1024 * 1024);
|
||||
|
||||
for(unsigned char c : temp_bitmap) {
|
||||
bin.push_back(c);
|
||||
}
|
||||
|
||||
shader = Shader(vs, fs, Shader::LoadType::FromSource);
|
||||
texture = Texture(bin, 1024, 1024);
|
||||
}
|
||||
|
||||
file.close();
|
||||
Body* genText(std::vector<std::string> texts) {
|
||||
// assume orthographic projection with units = screen pixels, origin at top left
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
return Body(
|
||||
VertexBuffer(verticies),
|
||||
IndexArray(indicies),
|
||||
VertexLayout(),
|
||||
shader
|
||||
);
|
||||
}
|
||||
std::vector<float> v;
|
||||
std::vector<unsigned int> i;
|
||||
|
||||
float x = 0, y = 0, oX = 0, dY = 0;
|
||||
|
||||
std::string text = "";
|
||||
|
||||
for(std::string s : texts) {
|
||||
text += s + " ";
|
||||
}
|
||||
|
||||
for(unsigned int j = 0; j < text.length(); j++) {
|
||||
if (text[j] >= 32) {
|
||||
stbtt_aligned_quad q;
|
||||
stbtt_GetBakedQuad(cdata, 512,512, text[j]-32, &x,&y,&q,1);//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(j * 4);
|
||||
i.push_back(j * 4 + 1);
|
||||
i.push_back(j * 4 + 2);
|
||||
i.push_back(j * 4 + 2);
|
||||
i.push_back(j * 4 + 3);
|
||||
i.push_back(j * 4);
|
||||
|
||||
dY = q.y1 - q.y0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
@@ -79,59 +281,174 @@ namespace Archimedes {
|
||||
public:
|
||||
JObject() {}
|
||||
|
||||
void load(std::string path) {
|
||||
std::ifstream file(path);
|
||||
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) {
|
||||
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(glm::cos(2.0f * glm::pi<float>() / resolution));
|
||||
v.push_back(glm::sin(2.0f * glm::pi<float>() / resolution));
|
||||
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 Body(
|
||||
return new Body(
|
||||
VertexBuffer(v),
|
||||
IndexArray(i),
|
||||
VertexLayout(),
|
||||
shader
|
||||
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) {
|
||||
return Body();
|
||||
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) {
|
||||
return Body();
|
||||
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) {
|
||||
return Body();
|
||||
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);
|
||||
}
|
||||
|
||||
std::vector<Body> buildObjects() {
|
||||
|
||||
std::vector<Body> v;
|
||||
void buildObjects() {
|
||||
|
||||
|
||||
for (json::const_iterator it = templates.cbegin(); it != templates.cend(); it++)
|
||||
for (json::const_iterator it = objects.cbegin(); it != objects.cend(); it++)
|
||||
{
|
||||
json element = *it;
|
||||
std::string name = element["name"];
|
||||
@@ -139,27 +456,84 @@ namespace Archimedes {
|
||||
if (type == "CIRCLE") {
|
||||
objectMap[name] = createCircle(element, name);
|
||||
}
|
||||
if (type == "SQUARE") {}
|
||||
if (type == "RECTANGLE") {}
|
||||
if (type == "POLYGON") {}
|
||||
if (type == "TEXT") {}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
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:
|
||||
|
||||
std::unordered_map<std::string, Body> objectMap;
|
||||
Archimedes::VertexLayout layout = Archimedes::VertexLayout({
|
||||
Archimedes::LayoutElement(Archimedes::LayoutElement::Type::Float, 3, 0, 0)
|
||||
});
|
||||
|
||||
std::unordered_map<std::string, Body> templateMap;
|
||||
|
||||
bool goodJSON = true;
|
||||
bool goodJSON = false;
|
||||
|
||||
Shader shader;
|
||||
|
||||
unsigned int resolution = 50;
|
||||
|
||||
json document, templates, objects, setup, cameras, lights, actions;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
|
||||
#include "Sandbox.h"
|
||||
#include "JObject.h"
|
||||
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#include <stb/stb_truetype.h>
|
||||
|
||||
Sandbox::Sandbox(Archimedes::App* a, void* h) : Archimedes::Module(a, h) {
|
||||
|
||||
@@ -54,12 +55,12 @@ void Sandbox::onLoad() {
|
||||
|
||||
cubeShader = Archimedes::Shader(cubeVS, cubeFS, Archimedes::Shader::LoadType::FromSource);
|
||||
|
||||
window->getRenderer()->useShader(cubeShader);
|
||||
window->getRenderer()->setupShader(cubeShader);
|
||||
|
||||
cube = Archimedes::Body(
|
||||
Archimedes::VertexBuffer(vertices),
|
||||
Archimedes::IndexArray(indices),
|
||||
Archimedes::VertexLayout(),
|
||||
layout,
|
||||
cubeShader
|
||||
);
|
||||
|
||||
@@ -68,7 +69,7 @@ void Sandbox::onLoad() {
|
||||
grid = Archimedes::Body(
|
||||
Archimedes::VertexBuffer(gridVertices),
|
||||
Archimedes::IndexArray(gridIndices),
|
||||
Archimedes::VertexLayout(),
|
||||
layout,
|
||||
cubeShader
|
||||
);
|
||||
|
||||
@@ -79,12 +80,22 @@ void Sandbox::onLoad() {
|
||||
window->getSize(w, h);
|
||||
app->emitEvent(new Archimedes::ResizeWindowEvent(w, h));
|
||||
|
||||
hexagon = Archimedes::readOBJ("/home/nathan/Projects/tests/buildzone/hexagon_pad.obj", cubeShader);
|
||||
hexagon = readOBJ("/home/nathan/Projects/tests/buildzone/hexagon_pad.obj", cubeShader);
|
||||
|
||||
window->getRenderer()->setupRenderTarget(hexagon.getMesh());
|
||||
|
||||
|
||||
hexagon.scaleTo(0.01f);
|
||||
|
||||
|
||||
camera.setTransform(glm::lookAt(
|
||||
glm::vec3(0.0f, 0.0f, 3.0f),
|
||||
glm::vec3(0.0f, 0.0f, 0.0f),
|
||||
glm::vec3(0.0f, 1.0f, 0.0f)
|
||||
));
|
||||
|
||||
camera.setPerspective(glm::perspective(glm::radians(45.0f), (float)w/(float)h, 0.1f, 100.0f));
|
||||
//camera.setPerspective(glm::ortho(-(float)w / 2.0f, (float)w / 2.0f, -(float)h / 2.0f, (float)h / 2.0f, 0.1f, 100.0f));
|
||||
}
|
||||
|
||||
void Sandbox::run() {
|
||||
@@ -94,37 +105,35 @@ void Sandbox::run() {
|
||||
static glm::vec3 pos(0), rot(0);
|
||||
static glm::vec3 posPrev(0), rotPrev(0);
|
||||
|
||||
static glm::vec3 camPos(0.0f, 0.0f, 3.0f), camRot(0.0f, glm::pi<float>(), 0.0f);
|
||||
static glm::vec3 camPosPrev(0.0f, 0.0f, 3.0f), camRotPrev(0.0f, glm::pi<float>(), 0.0f);
|
||||
|
||||
static glm::vec4 color = { 0.4f, 0.0f, 0.3f, 1.0f };
|
||||
|
||||
static glm::vec3 camPos(0.0f, 0.0f, 3.0f), camRot(0.0f, glm::pi<float>(), 0.0f);
|
||||
|
||||
static glm::mat4 orthoMat, perspMat, cameraTransform;
|
||||
|
||||
cameraTransform = glm::lookAt(
|
||||
camPos,
|
||||
camPos + glm::normalize(glm::vec3(glm::sin(camRot.y) * glm::cos(camRot.x), glm::sin(camRot.x), glm::cos(camRot.y) * glm::cos(camRot.x))),
|
||||
glm::vec3(0.0f, 1.0f, 0.0f)
|
||||
);
|
||||
|
||||
int w, h;
|
||||
static int w, h;
|
||||
window->getSize(w, h);
|
||||
//camPos = camera.moveRel(camPos - camPosPrev);
|
||||
//camRot = camera.rotateRel(camRot - camRotPrev);
|
||||
|
||||
orthoMat = glm::ortho(-(float)w / 2.0f, (float)w / 2.0f, -(float)h / 2.0f, (float)h / 2.0f, 0.1f, 100.0f);
|
||||
camera.setTransform(glm::lookAt(
|
||||
camPos,
|
||||
camPos + glm::normalize(glm::vec3(glm::cos(camRot.x) * glm::sin(camRot.y), glm::sin(camRot.x), glm::cos(camRot.x) * glm::cos(camRot.y))),
|
||||
glm::vec3(0.0f, 1.0f, 0.0f)
|
||||
));
|
||||
|
||||
perspMat = glm::perspective(glm::radians(45.0f), (float)w/(float)h, 0.1f, 100.0f);
|
||||
camPosPrev = camPos;
|
||||
camRotPrev = camRot;
|
||||
|
||||
pos = cube.moveRel(pos - posPrev);
|
||||
rot = cube.rotateRel(rot - rotPrev);
|
||||
scale = cube.scaleRel(scale / scalePrev);
|
||||
|
||||
posPrev = pos;
|
||||
rotPrev = rot;
|
||||
scalePrev = scale;
|
||||
|
||||
//window->getRenderer()->draw(grid.getMesh(), grid.getTransform(), cameraTransform, perspMat, glm::vec4(0.7f));
|
||||
//window->getRenderer()->draw(cube.getMesh(), cube.getTransform(), cameraTransform, perspMat, color, Archimedes::Renderer::RenderMode::Triangles);
|
||||
window->getRenderer()->draw(hexagon.getMesh(), hexagon.getTransform(), cameraTransform, perspMat, color);
|
||||
|
||||
/*
|
||||
window->getRenderer()->draw(
|
||||
hexagon.getMesh(),
|
||||
hexagon.getTransform(),
|
||||
camera.getTransform(),
|
||||
camera.getPerspective(),
|
||||
color
|
||||
);
|
||||
*/
|
||||
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
@@ -139,22 +148,94 @@ void Sandbox::run() {
|
||||
ImGui::SliderFloat("clear b", &clearColor.b, 0.0f, 1.0f);
|
||||
ImGui::SliderFloat("clear a", &clearColor.a, 0.0f, 1.0f);
|
||||
|
||||
ImGui::Text("Properties");
|
||||
if(jObject.isValid()) {
|
||||
ImGui::Text("Object Properties");
|
||||
|
||||
ImGui::SliderFloat("pitch", &rot.x, -glm::pi<float>(), glm::pi<float>());
|
||||
ImGui::SliderFloat("yaw", &rot.y, -glm::pi<float>(), glm::pi<float>());
|
||||
ImGui::SliderFloat("roll", &rot.z, -glm::pi<float>(), glm::pi<float>());
|
||||
static std::string object = jObject.objectMap.begin()->first;
|
||||
|
||||
ImGui::SliderFloat("scale", &scale, 0.1f, 10.0f);
|
||||
if(ImGui::BeginCombo("Object", object.c_str())) {
|
||||
for (auto it : jObject.objectMap)
|
||||
{
|
||||
|
||||
ImGui::SliderFloat("x", &pos.x, -10.0f, 10.0f);
|
||||
ImGui::SliderFloat("y", &pos.y, -10.0f, 10.0f);
|
||||
ImGui::SliderFloat("z", &pos.z, -10.0f, 10.0f);
|
||||
const bool is_selected = (object == it.first);
|
||||
if (ImGui::Selectable(it.first.c_str(), is_selected)) {
|
||||
object = it.first;
|
||||
}
|
||||
|
||||
ImGui::SliderFloat("r", &color.r, 0.0f, 1.0f);
|
||||
ImGui::SliderFloat("g", &color.g, 0.0f, 1.0f);
|
||||
ImGui::SliderFloat("b", &color.b, 0.0f, 1.0f);
|
||||
ImGui::SliderFloat("a", &color.a, 0.0f, 1.0f);
|
||||
// Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
for (auto it : jObject.objectMap) {
|
||||
if(it.second != nullptr) {
|
||||
window->getRenderer()->draw(
|
||||
it.second->getMesh(),
|
||||
it.second->getTransform(),
|
||||
camera.getTransform(),
|
||||
camera.getPerspective(),
|
||||
color
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ImGui::SliderFloat("pitch", &rot.x, -glm::pi<float>(), glm::pi<float>());
|
||||
ImGui::SliderFloat("yaw", &rot.y, -glm::pi<float>(), glm::pi<float>());
|
||||
ImGui::SliderFloat("roll", &rot.z, -glm::pi<float>(), glm::pi<float>());
|
||||
|
||||
ImGui::SliderFloat("scale", &scale, 0.001f, 10.0f);
|
||||
|
||||
ImGui::SliderFloat("x", &pos.x, -10.0f, 10.0f);
|
||||
ImGui::SliderFloat("y", &pos.y, -10.0f, 10.0f);
|
||||
ImGui::SliderFloat("z", &pos.z, -10.0f, 10.0f);
|
||||
|
||||
ImGui::SliderFloat("r", &color.r, 0.0f, 1.0f);
|
||||
ImGui::SliderFloat("g", &color.g, 0.0f, 1.0f);
|
||||
ImGui::SliderFloat("b", &color.b, 0.0f, 1.0f);
|
||||
ImGui::SliderFloat("a", &color.a, 0.0f, 1.0f);
|
||||
|
||||
if(ImGui::Button("Apply") && jObject.objectMap[object] != nullptr) {
|
||||
pos = jObject.objectMap[object]->moveRel(pos - posPrev);
|
||||
rot = jObject.objectMap[object]->rotateRel(rot - rotPrev);
|
||||
//scale = jObject.objectMap[object]->scaleRel(scale / scalePrev);
|
||||
jObject.objectMap[object]->scaleTo(scale / (float)h);
|
||||
|
||||
|
||||
posPrev = pos;
|
||||
rotPrev = rot;
|
||||
//scalePrev = scale;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
static std::string pathJSON = "/home/nathan/Projects/tests/buildzone/test.json";
|
||||
static std::string pathFont = "/nix/store/05zf1s3wlw0k90l34iaby4ysrafv6w95-nerd-fonts-fira-code-3.4.0+6.2/share/fonts/truetype/NerdFonts/FiraCode/FiraCodeNerdFontMono-Regular.ttf";
|
||||
ImGui::InputText("JSON Path", &pathJSON);
|
||||
ImGui::InputText("Font Path", &pathFont);
|
||||
if(ImGui::Button("load")) {
|
||||
|
||||
jObject.shader = cubeShader;
|
||||
|
||||
jObject.load(pathJSON, pathFont);
|
||||
|
||||
window->getRenderer()->setupShader(jObject.text.shader);
|
||||
//window->getRenderer()->setupTexture(jObject.text.texture);
|
||||
|
||||
jObject.buildObjects();
|
||||
|
||||
for(auto o : jObject.objectMap) {
|
||||
if(o.second != nullptr) {
|
||||
o.second->scaleTo(1.0f / (float)h);
|
||||
window->getRenderer()->setupRenderTarget(o.second->getMesh());
|
||||
}
|
||||
}
|
||||
|
||||
jObject.objectActions();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Text("Camera Properties");
|
||||
|
||||
@@ -184,7 +265,15 @@ bool Sandbox::onEvent(const Archimedes::Event& e) {
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
|
||||
if(type == app->getEventType(Archimedes::KeyPressedWindowEvent()) && !io.WantCaptureKeyboard) {
|
||||
if(type == app->getEventType(Archimedes::ResizeWindowEvent())) {
|
||||
Archimedes::ResizeWindowEvent event = (Archimedes::ResizeWindowEvent&) e;
|
||||
|
||||
for(auto o : jObject.objectMap) {
|
||||
if(o.second != nullptr) {
|
||||
o.second->scaleRel(1.0f / (float)event.height);
|
||||
}
|
||||
}
|
||||
} else if(type == app->getEventType(Archimedes::KeyPressedWindowEvent()) && !io.WantCaptureKeyboard) {
|
||||
|
||||
return false;
|
||||
} else if(type == app->getEventType(Archimedes::KeyReleasedWindowEvent()) && !io.WantCaptureKeyboard) {
|
||||
@@ -213,3 +302,6 @@ bool Sandbox::onEvent(const Archimedes::Event& e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// This only works with opengl!!!!
|
||||
|
||||
#ifndef JOBJECT_H
|
||||
#define JOBJECT_H
|
||||
|
||||
#include "Archimedes.h"
|
||||
|
||||
@@ -9,6 +11,8 @@
|
||||
#include "utils/Objects/Body.h"
|
||||
#include "utils/Objects/Camera.h"
|
||||
|
||||
#include "JObject.h"
|
||||
|
||||
class Sandbox : public Archimedes::Module {
|
||||
|
||||
public:
|
||||
@@ -50,10 +54,17 @@ class Sandbox : public Archimedes::Module {
|
||||
" FragColor = color;\n"
|
||||
"}\n\0";
|
||||
|
||||
Archimedes::JObject jObject;
|
||||
|
||||
Archimedes::Shader cubeShader, gridShader;
|
||||
Archimedes::Body cube, grid, hexagon;
|
||||
|
||||
Archimedes::VertexLayout layout = Archimedes::VertexLayout({
|
||||
Archimedes::LayoutElement(Archimedes::LayoutElement::Type::Float, 3, 0, 0)
|
||||
});
|
||||
|
||||
Archimedes::Camera camera;
|
||||
|
||||
std::vector<float> gridVertices = {
|
||||
-1.0f, 0.0f, 1.0f,
|
||||
1.0f, 0.0f, 1.0f,
|
||||
@@ -134,9 +145,82 @@ class Sandbox : public Archimedes::Module {
|
||||
|
||||
};
|
||||
|
||||
Archimedes::Body readOBJ(std::string path, Archimedes::Shader shader) {
|
||||
|
||||
std::ifstream file(path);
|
||||
|
||||
if(!file.is_open()) return Archimedes::Body();
|
||||
|
||||
std::string s;
|
||||
|
||||
std::vector<float> verticies;
|
||||
std::vector<unsigned int> indicies;
|
||||
|
||||
verticies.reserve(3 * 100);
|
||||
indicies.reserve(100);
|
||||
|
||||
unsigned int i = 0;
|
||||
unsigned int j = 0;
|
||||
|
||||
float point;
|
||||
unsigned int idx;
|
||||
|
||||
while(!file.eof()) {
|
||||
getline(file, s, ' ');
|
||||
|
||||
//std::cout << "\nline start: " << s << std::endl;
|
||||
|
||||
if(s == "v") {
|
||||
file >> point;
|
||||
verticies.push_back(point);
|
||||
//std::cout << "point1: " << point << std::endl;
|
||||
|
||||
file >> point;
|
||||
verticies.push_back(point);
|
||||
//std::cout << "point2: " << point << std::endl;
|
||||
|
||||
file >> point;
|
||||
verticies.push_back(point);
|
||||
//std::cout << "point3: " << point << std::endl;
|
||||
|
||||
//std::cout << "index: " << j << std::endl;
|
||||
|
||||
getline(file, s);
|
||||
//file.ignore();
|
||||
} else if(s == "f") {
|
||||
|
||||
file >> idx;
|
||||
indicies.push_back(--idx);
|
||||
file.ignore(5, ' ');
|
||||
|
||||
file >> idx;
|
||||
indicies.push_back(--idx);
|
||||
file.ignore(5, ' ');
|
||||
|
||||
file >> idx;
|
||||
indicies.push_back(--idx);
|
||||
getline(file, s);
|
||||
|
||||
} else {
|
||||
getline(file, s);
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
return Archimedes::Body(
|
||||
Archimedes::VertexBuffer(verticies),
|
||||
Archimedes::IndexArray(indicies),
|
||||
Archimedes::VertexLayout(),
|
||||
shader
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#ifdef SANDBOX_DYNAMIC
|
||||
typedef Sandbox mtype;
|
||||
#include "endModule.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
glm
|
||||
curl
|
||||
nlohmann_json
|
||||
|
||||
stb
|
||||
];
|
||||
|
||||
buildPhase = ''
|
||||
|
||||
Reference in New Issue
Block a user