diff --git a/assetManager.h b/assetManager.h index d84e4f7..5223a5f 100644 --- a/assetManager.h +++ b/assetManager.h @@ -11,6 +11,7 @@ namespace vb01{ class AssetManager{ public: static AssetManager* getSingleton(); + void readDir(std::string, std::vector&, bool); void load(std::string, bool = false); void editAsset(std::string, Asset&); Asset* getAsset(std::string); @@ -19,7 +20,6 @@ namespace vb01{ inline int getNumAssets(){return assets.size();} private: AssetManager(){} - void readDir(std::string, std::vector&, bool); std::vector assets; }; diff --git a/box.cpp b/box.cpp index 671656b..8901662 100755 --- a/box.cpp +++ b/box.cpp @@ -3,7 +3,6 @@ namespace vb01{ Box::Box(Vector3 size){ setSize(size); - construct(); } void Box::setSize(Vector3 size){ diff --git a/button.cpp b/button.cpp index 503c835..40df1b0 100644 --- a/button.cpp +++ b/button.cpp @@ -35,11 +35,12 @@ namespace vb01Gui{ mat->addVec4Uniform(diffColUni, color); } else{ - mat->addBoolUniform(texUni, true); string frame[]{imagePath}; Texture *tex = new Texture(frame, 1, false); - mat->addTexUniform("diffuseMap", tex, false); textures.push_back(tex); + + mat->addTexUniform("diffuseMap", tex, false); + mat->addBoolUniform(texUni, true); } rect->setMaterial(mat); @@ -130,15 +131,13 @@ namespace vb01Gui{ if(textures[i]->getPath()[0] == image) texId = i; - /* if(texId == -1){ string p[]{image}; - textures.push_back(new Texture(p, 1)); - mat->setDiffuseMap(textures[textures.size() - 1], 0); + textures.push_back(new Texture(p, 1, false)); + mat->setTexUniform("diffuseMap", textures[textures.size() - 1], false); } else - mat->setDiffuseMap(textures[texId], 0); - */ + mat->setTexUniform("diffuseMap", textures[texId], false); this->imagePath = image; } diff --git a/fontAsset.h b/fontAsset.h index 6c6dbb8..19ae3b2 100644 --- a/fontAsset.h +++ b/fontAsset.h @@ -3,10 +3,18 @@ #include "asset.h" +#include +#include +#include +#include FT_FREETYPE_H + namespace vb01{ - struct FontAsset : public Asset{ - FT_Face face; - }; + class Texture; + + struct FontAsset : public Asset{ + FT_Face face; + std::vector> glyphTextures; + }; } #endif diff --git a/light.cpp b/light.cpp index 0f423e2..b7f02bd 100755 --- a/light.cpp +++ b/light.cpp @@ -184,6 +184,7 @@ namespace vb01{ } //TODO replace depth map id literals + //TODO implement logic to skip lighting if the material has lighting disabled void Light::updateShader(vector materials, int thisId, mat4 &proj, mat4 &view){ Vector3 position = node->localToGlobalPosition(Vector3::VEC_ZERO), direction = node->getGlobalAxis(2); diff --git a/listbox.h b/listbox.h index 33fb7aa..7c13d77 100644 --- a/listbox.h +++ b/listbox.h @@ -35,6 +35,8 @@ namespace vb01Gui{ void scrollToHeight(float); virtual void onOpen(){} virtual void onClose(){} + inline void setName(std::string n){this->name = n;} + inline std::string getName(){return name;} inline int getScrollOffset(){return scrollOffset;} inline float getLineHeight(){return lineHeight;} inline bool isOpen(){return open;} @@ -60,7 +62,7 @@ namespace vb01Gui{ float lineHeight; int maxDisplay, scrollOffset = 0; bool open = false, closeable = false; - std::string fontPath; + std::string fontPath, name; vb01::Vector3 pos, textOffset; vb01::Vector2 size; ListboxButton *listboxButton; diff --git a/mesh.cpp b/mesh.cpp index 64de30e..91cf395 100755 --- a/mesh.cpp +++ b/mesh.cpp @@ -30,51 +30,7 @@ namespace vb01{ for(Mesh *m : meshes) delete m; - if(material) - delete material; - - glDeleteVertexArrays(1, &VAO); - glDeleteBuffers(1, &EBO); - glDeleteBuffers(1, &VBO); - } - - //TODO allow to init meshes to be drawn statically or dynamically - void Mesh::construct(){ - glGenVertexArrays(1, &VAO); - glGenBuffers(1, &VBO); - glGenBuffers(1, &EBO); - - u32 size = sizeof(MeshData::GpuVertex); - - glBindVertexArray(VAO); - glBindBuffer(GL_ARRAY_BUFFER, VBO); - - MeshData::GpuVertex *glVertData = meshBase.toGpuVerts(); - glBufferData(GL_ARRAY_BUFFER, 3 * meshBase.numTris * size, glVertData, GL_DYNAMIC_DRAW); - delete glVertData; - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * meshBase.numTris * sizeof(u32), meshBase.indices, GL_STATIC_DRAW); - - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, size, (void*)0); - glEnableVertexAttribArray(0); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, norm))); - glEnableVertexAttribArray(1); - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, uv))); - glEnableVertexAttribArray(2); - glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, tan))); - glEnableVertexAttribArray(3); - glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, biTan))); - glEnableVertexAttribArray(4); - glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, weights))); - glEnableVertexAttribArray(5); - glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, boneIndices))); - glEnableVertexAttribArray(6); - - for(int i = 0; i < meshBase.numShapeKeys; i++){ - glVertexAttribPointer(7 + i, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, shapeKeyOffsets) + 3 * i * sizeof(float))); - glEnableVertexAttribArray(7 + i); - } + if(material) delete material; } void Mesh::initFramebuffer(u32 &framebuffer, u32 &renderbuffer, int width){ @@ -94,7 +50,7 @@ namespace vb01{ } void Mesh::updateVerts(MeshData meshData){ - glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBindBuffer(GL_ARRAY_BUFFER, meshData.VBO); MeshData::GpuVertex *glVertData = meshBase.toGpuVerts(); glBufferSubData(GL_ARRAY_BUFFER, 0, 3 * sizeof(MeshData::GpuVertex) * meshBase.numTris, glVertData); @@ -130,8 +86,15 @@ namespace vb01{ float fov = cam->getFov(), width = root->getWidth(), height = root->getHeight(), nearPlane = cam->getNearPlane(), farPlane = cam->getFarPlane(); mat4 proj = perspective(radians(fov), width / height, nearPlane, farPlane); - material->update(); Shader *shader = material->getShader(); + material->update(); + + shader->setBool(castShadow, "castShadow"); + shader->setBool(skeleton, "animated"); + shader->setMat4(view, "view"); + shader->setMat4(proj, "proj"); + shader->setVec3(camPos, "camPos"); + shader->setMat4(model, "model"); if(skeleton) updateSkeleton(shader); @@ -142,13 +105,6 @@ namespace vb01{ if(reflect) updateReflection(pos); - shader->setBool(castShadow, "castShadow"); - shader->setBool(skeleton, "animated"); - shader->setMat4(view, "view"); - shader->setMat4(proj, "proj"); - shader->setVec3(camPos, "camPos"); - shader->setMat4(model, "model"); - if(shader->getName() == "gui"){ shader->setVec2(Vector2((float)width, (float)height), "screen"); @@ -401,7 +357,7 @@ namespace vb01{ } void Mesh::render(){ - glBindVertexArray(VAO); + glBindVertexArray(meshBase.VAO); glPolygonMode(GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL); glDrawElements(GL_TRIANGLES, 3 * meshBase.numTris, GL_UNSIGNED_INT, 0); } diff --git a/mesh.h b/mesh.h index 6d69172..099f259 100755 --- a/mesh.h +++ b/mesh.h @@ -20,7 +20,6 @@ namespace vb01{ public: Mesh(MeshData); ~Mesh(); - void construct(); void updateVerts(MeshData); virtual void update(); void render(); @@ -67,7 +66,6 @@ namespace vb01{ int numShapeKeys = 0; MeshData::ShapeKey *shapeKeys = nullptr; bool castShadow = false, reflect = false, reflective = false, wireframe = false; - u32 VAO, VBO, EBO; }; } diff --git a/meshData.cpp b/meshData.cpp index ba7572b..4e384ce 100644 --- a/meshData.cpp +++ b/meshData.cpp @@ -1,8 +1,83 @@ #include "meshData.h" +#include "glad.h" +#include +#include +#include + using namespace std; namespace vb01{ + //TODO allow to init meshes to be drawn statically or dynamically + MeshData::MeshData( + Vector3 *pos, + float **w, + int **bi, + Vector3 **sko, + int np, + Vector3 *norm, + Vertex *vert, + u32 *ind, + int nt, + std::string an, + std::string *vg, + int nvg, + std::string fsn, + ShapeKey *sk, + int nsk + ) : + positions(pos), + weights(w), + boneIndices(bi), + shapeKeyOffsets(sko), + numPos(np), + normals(norm), + vertices(vert), + indices(ind), + numTris(nt), + vertexGroups(vg), + numVertexGroups(nvg), + fullSkeletonName(fsn), + shapeKeys(sk), + numShapeKeys(nsk) + { + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + glGenBuffers(1, &EBO); + + u32 size = sizeof(MeshData::GpuVertex); + + glBindVertexArray(VAO); + glBindBuffer(GL_ARRAY_BUFFER, VBO); + + MeshData::GpuVertex *glVertData = toGpuVerts(); + glBufferData(GL_ARRAY_BUFFER, 3 * numTris * size, glVertData, GL_DYNAMIC_DRAW); + delete glVertData; + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3 * numTris * sizeof(u32), indices, GL_STATIC_DRAW); + + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, size, (void*)0); + glEnableVertexAttribArray(0); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, norm))); + glEnableVertexAttribArray(1); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, uv))); + glEnableVertexAttribArray(2); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, tan))); + glEnableVertexAttribArray(3); + glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, biTan))); + glEnableVertexAttribArray(4); + glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, weights))); + glEnableVertexAttribArray(5); + glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, boneIndices))); + glEnableVertexAttribArray(6); + + for(int i = 0; i < numShapeKeys; i++){ + glVertexAttribPointer(7 + i, 3, GL_FLOAT, GL_FALSE, size, (void*)(offsetof(MeshData::GpuVertex, shapeKeyOffsets) + 3 * i * sizeof(float))); + glEnableVertexAttribArray(7 + i); + } + } + void MeshData::ShapeKey::animate(float value, KeyframeChannel keyframeChannel){ switch(keyframeChannel.type){ case KeyframeChannel::SHAPE_KEY_MIN: diff --git a/meshData.h b/meshData.h index 6ca0ced..add53c6 100644 --- a/meshData.h +++ b/meshData.h @@ -9,62 +9,47 @@ #include "animatable.h" namespace vb01{ - struct MeshData{ - struct ShapeKey : public Animatable{ - std::string name; - float minValue, value, maxValue; - - ShapeKey(std::string n, float v, float mnv, float mxv) : name(n), value(v), minValue(mnv), maxValue(mxv), Animatable(Animatable::SHAPE_KEY, n){} - ShapeKey() : Animatable(Animatable::SHAPE_KEY){} - void animate(float, KeyframeChannel); - }; - - struct GpuVertex{ - Vector3 pos, norm, tan, biTan; - Vector2 uv; - float weights[4]{0, 0, 0, 0}; - int boneIndices[4]{-1, -1, -1, -1}; - Vector3 shapeKeyOffsets[100]; - }; - - struct Vertex{ - Vector3 *pos = nullptr, *norm = nullptr, tan, biTan; - Vector2 uv; - float *weights = nullptr; - int *boneIndices = nullptr; - Vector3 *shapeKeyOffsets = nullptr; - }; - - GpuVertex* toGpuVerts(); - - Vector3 *positions = nullptr, *normals = nullptr, **shapeKeyOffsets = nullptr; - float **weights = nullptr; - int **boneIndices = nullptr; - Vertex *vertices; - std::string *vertexGroups = nullptr; - ShapeKey *shapeKeys = nullptr; - u32 *indices, VAO, VBO, EBO; - int numPos, numTris, numVertexGroups = 0, numShapeKeys = 0; - std::string attachableName = "", fullSkeletonName = ""; - - MeshData(){} - MeshData(Vector3 *pos, float **w, int **bi, Vector3 **sko, int np, Vector3 *norm, Vertex *vert, u32 *ind, int nt, std::string an = "", std::string *vg = nullptr, int nvg = 0, std::string fsn = "", ShapeKey *sk = nullptr, int nsk = 0) : - positions(pos), - weights(w), - boneIndices(bi), - shapeKeyOffsets(sko), - numPos(np), - normals(norm), - vertices(vert), - indices(ind), - numTris(nt), - vertexGroups(vg), - numVertexGroups(nvg), - fullSkeletonName(fsn), - shapeKeys(sk), - numShapeKeys(nsk) - {} + struct MeshData{ + struct ShapeKey : public Animatable{ + std::string name; + float minValue, value, maxValue; + + ShapeKey(std::string n, float v, float mnv, float mxv) : name(n), value(v), minValue(mnv), maxValue(mxv), Animatable(Animatable::SHAPE_KEY, n){} + ShapeKey() : Animatable(Animatable::SHAPE_KEY){} + void animate(float, KeyframeChannel); }; + + struct GpuVertex{ + Vector3 pos, norm, tan, biTan; + Vector2 uv; + float weights[4]{0, 0, 0, 0}; + int boneIndices[4]{-1, -1, -1, -1}; + Vector3 shapeKeyOffsets[100]; + }; + + struct Vertex{ + Vector3 *pos = nullptr, *norm = nullptr, tan, biTan; + Vector2 uv; + float *weights = nullptr; + int *boneIndices = nullptr; + Vector3 *shapeKeyOffsets = nullptr; + }; + + GpuVertex* toGpuVerts(); + + Vector3 *positions = nullptr, *normals = nullptr, **shapeKeyOffsets = nullptr; + float **weights = nullptr; + int **boneIndices = nullptr; + Vertex *vertices; + std::string *vertexGroups = nullptr; + ShapeKey *shapeKeys = nullptr; + u32 *indices, VAO, VBO, EBO; + int numPos, numTris, numVertexGroups = 0, numShapeKeys = 0; + std::string attachableName = "", fullSkeletonName = ""; + + MeshData(){} + MeshData(Vector3*, float**, int**, Vector3**, int, Vector3*, Vertex*, u32*, int, std::string = "", std::string *vg = nullptr, int = 0, std::string = "", ShapeKey *sk = nullptr, int = 0); + }; } #endif diff --git a/model.cpp b/model.cpp index 0684ba1..f8e3257 100755 --- a/model.cpp +++ b/model.cpp @@ -14,17 +14,13 @@ using namespace std; namespace vb01{ Model::Model(string path) : Node(){ - ModelAsset *asset = ((ModelAsset*)AssetManager::getSingleton()->getAsset(path)); - Node *clonedRoot = asset->rootNode->clone(); - vector descendants = vector{clonedRoot}; - clonedRoot->getDescendants(descendants); + ModelAsset *asset = ((ModelAsset*)AssetManager::getSingleton()->getAsset(path)); + Node *clonedRoot = asset->rootNode->clone(); + vector descendants = vector{clonedRoot}; + clonedRoot->getDescendants(descendants); - for(Node *desc : descendants) - for(Mesh *mesh : desc->getMeshes()) - mesh->construct(); - - for(Node *child : clonedRoot->getChildren()) - attachChild(child); + for(Node *child : clonedRoot->getChildren()) + attachChild(child); } Model::~Model(){ diff --git a/node.cpp b/node.cpp index 721820e..4b0fbac 100755 --- a/node.cpp +++ b/node.cpp @@ -393,51 +393,51 @@ namespace vb01{ return Vector3(local.x, local.y, local.z); } - Quaternion Node::adjustRot(vector ancestors, Quaternion adjustableRot, bool localToGlobal){ - Quaternion rOrigin = adjustableRot; + Quaternion Node::adjustRot(Quaternion adjustableRot, bool localToGlobal){ + vector ancestors = getAncestors(); + Quaternion rOrigin = (localToGlobal ? Quaternion::QUAT_W : adjustableRot); while(!ancestors.empty()){ - int id = localToGlobal ? 0 : ancestors.size() - 1; + int id = (localToGlobal ? ancestors.size() - 1 : 0); + Node *node = ancestors[id], *nodePar = node->getParent(); - float angle = ancestors[id]->getOrientation().getAngle(); - Vector3 axis = ancestors[id]->getOrientation().getAxis(); + Vector3 parAxis[]{ + nodePar ? nodePar->getGlobalAxis(0) : Vector3::VEC_I, + nodePar ? nodePar->getGlobalAxis(1) : Vector3::VEC_J, + nodePar ? nodePar->getGlobalAxis(2) : Vector3::VEC_K + }; + + Vector3 axis = node->getOrientation().getAxis(); + axis = (parAxis[0] * axis.x + parAxis[1] * axis.y + parAxis[2] * axis.z).norm(); + float angle = node->getOrientation().getAngle(); - Quaternion o; if(localToGlobal){ - Node *par = ancestors[id]->getParent(); - Vector3 parAxis[]{ - par ? par->getGlobalAxis(0) : Vector3::VEC_I, - par ? par->getGlobalAxis(1) : Vector3::VEC_J, - par ? par->getGlobalAxis(2) : Vector3::VEC_K - }; + rOrigin = Quaternion(angle, axis) * rOrigin; + ancestors.pop_back(); - axis = (parAxis[0] * axis.x + parAxis[1] * axis.y + parAxis[2] * axis.z).norm(); - - o = Quaternion(angle, axis); - rOrigin = rOrigin * o; - ancestors.erase(ancestors.begin()); + if(ancestors.empty()){ + Vector3 ax = adjustableRot.getAxis(); + ax = (globalAxis[0] * ax.x + globalAxis[1] * ax.y + globalAxis[2] * ax.z).norm(); + return Quaternion(adjustableRot.getAngle(), ax) * rOrigin; + } } else{ - o = Quaternion(angle, axis).conj(); - rOrigin = rOrigin * o; + rOrigin = rOrigin * Quaternion(angle, axis).conj(); ancestors.pop_back(); + + if(ancestors.empty()) + return rOrigin; } } - - return rOrigin; } Quaternion Node::localToGlobalOrientation(Quaternion localRot){ - vector ancestors = getAncestors(); - Quaternion origin = adjustRot(ancestors, Quaternion::QUAT_W, true); - return localRot * origin; + return adjustRot(localRot, true); } Quaternion Node::globalToLocalOrientation(Quaternion globalRot){ - vector ancestors = getAncestors(); - Quaternion origin = adjustRot(ancestors, globalRot, false); - return origin; + return adjustRot(globalRot, false); } Node* Node::findDescendant(string name, bool allDescendants){ diff --git a/node.h b/node.h index 46aec28..59924c7 100755 --- a/node.h +++ b/node.h @@ -81,7 +81,7 @@ namespace vb01{ void adjustDir(Vector3); void updateShaders(); - Quaternion adjustRot(std::vector, Quaternion, bool); + Quaternion adjustRot(Quaternion, bool); std::vector drivers; protected: virtual void animate(float, KeyframeChannel); diff --git a/quad.cpp b/quad.cpp index 076b313..57508df 100755 --- a/quad.cpp +++ b/quad.cpp @@ -11,7 +11,6 @@ namespace vb01{ this->numHorDiv = numHorDiv; setSize(size); - Mesh::construct(); } void Quad::setSize(Vector3 size){ @@ -86,4 +85,22 @@ namespace vb01{ meshBase = MeshData(faceVertPos, nullptr, nullptr, nullptr, 6, norm, vertices, indices, numTris); } + + //TODO improve functionality for GUI quads + Vector2 Quad::getSubquadIds(int numVertDiv, int numHorDiv, Vector3 pos, Vector3 size){ + const int numHorQuads = numVertDiv + 1, numVertQuads = numHorDiv + 1; + Vector2 subQuadSize = Vector2(size.x / numHorQuads, size.z / numVertQuads); + + return Vector2(int((.5 * size.x + pos.x) / subQuadSize.x), int((.5 * size.z + pos.z) / subQuadSize.y)); + } + + Vector3 Quad::getSubquadCorner(int xId, int yId, int numVertDiv, int numHorDiv, bool top, bool right){ + const int numHorQuads = numVertDiv + 1, numVertQuads = numHorDiv + 1; + int vertPosId = 6 * xId * numVertQuads + 6 * yId; + + if(top && !right) return meshBase.positions[vertPosId]; + else if(top && right) return meshBase.positions[vertPosId + 4]; + else if(!top && !right) return meshBase.positions[vertPosId + 1]; + else if(!top && right) return meshBase.positions[vertPosId + 3]; + } } diff --git a/quad.h b/quad.h index 7b9d683..6d93dda 100755 --- a/quad.h +++ b/quad.h @@ -9,7 +9,12 @@ namespace vb01{ public: Quad(Vector3, bool = true, int numVertDiv = 0, int numHorDiv = 0); void setSize(Vector3); + Vector3 getSubquadCorner(int, int, int, int, bool, bool); + Vector2 getSubquadIds(int, int, Vector3, Vector3); inline Vector3 getSize(){return size;} + inline Vector2 getSubquadSize(){return Vector2(size.x / (numHorDiv + 1), size.y / (numVertDiv + 1));} + inline int getNumHorSubquads(){return numHorDiv + 1;} + inline int getNumVertSubquads(){return numVertDiv + 1;} private: Vector3 size; bool spatial; diff --git a/root.cpp b/root.cpp index 0c0c1d5..f097bf5 100755 --- a/root.cpp +++ b/root.cpp @@ -56,14 +56,49 @@ namespace vb01{ brdfLutPlane = new Quad(Vector3(1, 1, 1) * 2); iblBox = new Box(Vector3::VEC_IJK); + blurShader = new Shader(libPath + "blur"); + shader = new Shader(Root::getSingleton()->getLibPath() + "line3D"); + + for(int i = 0; i < 2; i++) + pingPongTextures[i] = new Texture(width, height, false); + Texture *fragTexture = new Texture(width, height, false); Texture *brightTexture = new Texture(width, height, false); - initMainFramebuffer(fragTexture, brightTexture); - initBloomFramebuffer(); + initMainFramebuffer(fragTexture, nullptr); initGuiPlane(fragTexture, brightTexture); + } - shader = new Shader(Root::getSingleton()->getLibPath() + "line3D"); + void Root::toggleHDR(bool hdr){ + glDeleteFramebuffers((hdr ? 2 : 1), &FBO); + glDeleteRenderbuffers(1, &RBO); + + Texture *fragTexture = ((Material::TextureUniform*)guiPlane->getMaterial()->getUniform("frag"))->value; + Texture *brightTexture = ((Material::TextureUniform*)guiPlane->getMaterial()->getUniform("bright"))->value; + initMainFramebuffer(fragTexture, (hdr ? brightTexture : nullptr)); + + this->hdr = hdr; + } + + void Root::initBloomFramebuffer(){ + glGenFramebuffers(2, pingpongBuffers); + + for(int i = 0; i < 2; i++){ + glBindFramebuffer(GL_FRAMEBUFFER, pingpongBuffers[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *(pingPongTextures[i]->getTexture()), 0); + + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + cout << "Not complete\n"; + } + } + + void Root::toggleBloom(bool bloom){ + this->bloom = bloom; + + if(bloom) + initBloomFramebuffer(); + else + glDeleteFramebuffers(2, pingpongBuffers); } void Root::initWindow(string name){ @@ -101,11 +136,14 @@ namespace vb01{ glBindFramebuffer(GL_FRAMEBUFFER, FBO); u32 colorAttachments[]{GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1}; + glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[0], GL_TEXTURE_2D, *fragTexture->getTexture(), 0); - for(int i = 0; i < 2; i++) - glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[i], GL_TEXTURE_2D, *((i == 0 ? fragTexture : brightTexture)->getTexture()), 0); - - glDrawBuffers(2, colorAttachments); + if(brightTexture){ + glFramebufferTexture2D(GL_FRAMEBUFFER, colorAttachments[1], GL_TEXTURE_2D, *brightTexture->getTexture(), 0); + glDrawBuffers(2, colorAttachments); + } + else + glDrawBuffers(1, colorAttachments); glGenRenderbuffers(1, &RBO); glBindRenderbuffer(GL_RENDERBUFFER, RBO); @@ -118,20 +156,6 @@ namespace vb01{ glBindFramebuffer(GL_FRAMEBUFFER, 0); } - void Root::initBloomFramebuffer(){ - blurShader = new Shader(libPath + "blur"); - glGenFramebuffers(2, pingpongBuffers); - - for(int i = 0; i < 2; i++){ - glBindFramebuffer(GL_FRAMEBUFFER, pingpongBuffers[i]); - pingPongTextures[i] = new Texture(width, height, false); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *(pingPongTextures[i]->getTexture()), 0); - - if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - cout << "Not complete\n"; - } - } - void Root::initGuiPlane(Texture *fragTexture, Texture *brightTexture){ guiPlane = new Quad(Vector3(width, height, -1), false); Material *mat = new Material(libPath + "postProcess"); @@ -167,7 +191,8 @@ namespace vb01{ glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); - updateBloomFramebuffer(); + if(bloom) updateBloomFramebuffer(); + updateGuiPlane(); glEnable(GL_DEPTH_TEST); @@ -259,10 +284,14 @@ namespace vb01{ shader->setFloat(exposure, "exposure"); shader->setFloat(gamma, "gamma"); shader->setInt(0, "frag"); - shader->setInt(1, "bright"); ((Material::TextureUniform*)material->getUniform("frag"))->value->select(0); - ((Material::TextureUniform*)material->getUniform("bright"))->value->select(1); + + if(hdr){ + shader->setInt(1, "bright"); + ((Material::TextureUniform*)material->getUniform("bright"))->value->select(1); + } + guiPlane->render(); } diff --git a/root.h b/root.h index 3c87e7e..614a76c 100755 --- a/root.h +++ b/root.h @@ -23,6 +23,8 @@ namespace vb01{ public: void update(); void start(int, int, std::string, std::string); + void toggleHDR(bool); + void toggleBloom(bool); inline Camera* getCamera(){return camera;} inline Node* getRootNode(){return rootNode;} inline Node* getGuiNode(){return guiNode;} @@ -31,10 +33,8 @@ namespace vb01{ inline u32* getFBO(){return &FBO;} inline u32* getRBO(){return &RBO;} inline GLFWwindow* getWindow(){return window;} - inline void setHDREnabled(bool hdr){this->hdr = hdr;} inline void setExposure(float exposure){this->exposure = exposure;} inline void setGamma(float gamma){this->gamma = gamma;} - inline void setBloom(bool bloom){this->bloom = bloom;} inline void setBlurLevel(bool level){this->blurLevel = level;} inline Box* getSkybox(){return skybox;} inline Box* getIblBox(){return iblBox;} diff --git a/text.cpp b/text.cpp index b04db8d..6e12df8 100755 --- a/text.cpp +++ b/text.cpp @@ -4,7 +4,6 @@ #include "texture.h" #include "node.h" #include "material.h" -#include "fontAsset.h" #include "assetManager.h" #include "glad.h" @@ -23,17 +22,20 @@ namespace vb01{ } Text::~Text(){ - clearFont(); - glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); } + //TODO ensure destruction of textures when unloading the asset void Text::applyFont(string fontPath, u16 firstChar, u16 lastChar){ - clearFont(); + characters.clear(); - FontAsset *font = (FontAsset*)AssetManager::getSingleton()->getAsset(fontPath); + font = (FontAsset*)AssetManager::getSingleton()->getAsset(fontPath); FT_Face face = font->face; + vector keys; + + for (pair p : font->glyphTextures) + keys.push_back(p.first); for(u16 i = firstChar; i < lastChar; i++){ if(FT_Load_Char(face, i, FT_LOAD_RENDER)){ @@ -43,21 +45,18 @@ namespace vb01{ Glyph c; c.ch = i; - c.texture = new Texture(face); c.size = Vector2(face->glyph->bitmap.width, face->glyph->bitmap.rows); c.bearing = Vector2(face->glyph->bitmap_left, face->glyph->bitmap_top); c.advance = face->glyph->advance.x; + c.texId = i; + + if(find(keys.begin(), keys.end(), i) == keys.end()) + font->glyphTextures.push_back(make_pair(i, new Texture(face))); + characters.push_back(c); } } - void Text::clearFont(){ - while(!characters.empty()){ - delete characters[characters.size() - 1].texture; - characters.pop_back(); - } - } - void Text::update(){ Root *root = Root::getSingleton(); int width = root->getWidth(), height = root->getHeight(); @@ -72,11 +71,17 @@ namespace vb01{ for(int i = (leftToRight ? 0 : entry.length() - 1); (leftToRight ? (i < entry.length()) : (i >= 0)); (leftToRight ? i++ : i--)){ Glyph *glyphPtr = getGlyph(entry[i]); - if(!glyphPtr) - continue; + if(!glyphPtr) continue; + + int glyphTexId = -1; + for(int j = 0; j < font->glyphTextures.size(); j++) + if(font->glyphTextures[j].first == glyphPtr->texId){ + glyphTexId = j; + break; + } Glyph glyph = *glyphPtr; - prepareGlyphs(glyph, advanceOffset); + prepareGlyphs(glyph, glyphTexId, advanceOffset); Vector2 size = glyph.size, bearing = glyph.bearing; if(horizontal) @@ -86,7 +91,7 @@ namespace vb01{ } } - void Text::prepareGlyphs(Glyph glyph, Vector2 advanceOffset){ + void Text::prepareGlyphs(Glyph glyph, int glyphTexId, Vector2 advanceOffset){ Vector3 nodePos = node->getPosition(); Vector2 origin = Vector2(nodePos.x, nodePos.y) + (advanceOffset * scale); Vector3 scale = node->getScale(); @@ -104,17 +109,13 @@ namespace vb01{ origin.x + bearing.x, origin.y - bearing.y, 0, 0 }; - renderGlyphs(glyph, data, sizeof(data)); - } - - void Text::renderGlyphs(Glyph glyph, float data[], u32 dataSize){ glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); - glBufferSubData(GL_ARRAY_BUFFER, 0, dataSize, data); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(data), data); int id = 2; material->getShader()->setInt(id, "textures[1].pastTexture"); - glyph.texture->select(id); + font->glyphTextures[glyphTexId].second->select(id); glDrawArrays(GL_TRIANGLES, 0, 6); } diff --git a/text.h b/text.h index c48cc22..9d1780d 100755 --- a/text.h +++ b/text.h @@ -4,13 +4,13 @@ #include #include +#include "fontAsset.h" #include "attachable.h" #include "vector.h" #include "util.h" namespace vb01{ class Node; - class Texture; class Shader; class Material; @@ -18,7 +18,7 @@ namespace vb01{ public: struct Glyph{ u16 ch; - Texture *texture = nullptr; + int texId; u32 advance; Vector2 size, bearing; }; @@ -41,9 +41,9 @@ namespace vb01{ private: void applyFont(std::string, u16, u16 = 256); void clearFont(); - void prepareGlyphs(Glyph, Vector2); - void renderGlyphs(Glyph, float[], u32); + void prepareGlyphs(Glyph, int, Vector2); + FontAsset *font = nullptr; Material *material = nullptr; std::wstring entry; std::vector characters; diff --git a/texture.cpp b/texture.cpp index dd7c064..503e822 100755 --- a/texture.cpp +++ b/texture.cpp @@ -15,7 +15,7 @@ using namespace std; namespace vb01{ - Texture::Texture(int width, int height, bool shadowMap) : Animatable(Animatable::TEXTURE){ + Texture::Texture(int width, int height, bool shadowMap, bool hiRes) : Animatable(Animatable::TEXTURE){ this->width = width; this->height = height; texture = new u32; @@ -33,8 +33,7 @@ namespace vb01{ glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); } else{ - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, NULL); - //glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F,width,height,0,GL_RGB,GL_UNSIGNED_BYTE,NULL); + glTexImage2D(GL_TEXTURE_2D, 0, (hiRes ? GL_RGB16F : GL_RGB), width, height, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -60,7 +59,9 @@ namespace vb01{ } } - void Texture::loadImageData(ImageAsset *asset, int i){ + void Texture::loadImageData(ImageAsset *asset, bool creating, int i){ + if(!creating) glDeleteTextures(1, &texture[i]); + width = asset->width; height = asset->height; @@ -79,7 +80,7 @@ namespace vb01{ if(paths[i].substr(length - 4, string::npos) == ".png") png = true; - loadImageData((ImageAsset*)AssetManager::getSingleton()->getAsset(paths[i])); + loadImageData((ImageAsset*)AssetManager::getSingleton()->getAsset(paths[i]), true); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); diff --git a/texture.h b/texture.h index 55f073d..bb00acc 100755 --- a/texture.h +++ b/texture.h @@ -15,14 +15,14 @@ namespace vb01{ class Texture : public Animatable{ public: ~Texture(); - Texture(int, int, bool = true); + Texture(int, int, bool = true, bool = false); Texture(std::string[], int, bool, int = 0, bool = false, std::string = ""); Texture(int, bool = true, int = 0, std::string = ""); Texture(FT_Face); void select(int = 0, int = 0); void update(int = 0); void animate(float, KeyframeChannel); - void loadImageData(ImageAsset*, int = 0); + void loadImageData(ImageAsset*, bool, int = 0); inline u32* getTexture(int i = 0){return &(texture[i]);} inline std::string* getPath(){return paths;} inline int getNumFrames(){return numFrames;} diff --git a/util.cpp b/util.cpp index b60ab1e..298033d 100755 --- a/util.cpp +++ b/util.cpp @@ -7,20 +7,140 @@ using namespace std; namespace vb01{ - double *x = nullptr, *y = nullptr; + double *x = nullptr, *y = nullptr; - Vector2 getCursorPos() - { - if(!x) - x = new double; + Vector2 getCursorPos() { + if(!x) x = new double; - if(!y) - y = new double; - - glfwGetCursorPos(Root::getSingleton()->getWindow(), x, y); - return Vector2(*x, *y); + if(!y) y = new double; + + glfwGetCursorPos(Root::getSingleton()->getWindow(), x, y); + return Vector2(*x, *y); + } + + bool rectInter(Vector2 rp1, Vector2 rd1, Vector2 rps1, Vector2 p2[]){ + for(int i = 0; i < 4; i++){ + Vector2 pv = p2[i] - rp1; + float pd = pv.getLength(), angle = rd1.getAngleBetween(pv.norm()); + angle = (angle > PI / 2 ? PI - angle : angle); + + bool b1 = (pd * sin(angle) <= .5 * rps1.x); + bool b2 = (pd * cos(angle) <= .5 * rps1.y); + + if(b1 && b2) return true; } + return false; + } + + bool segmInter(Vector2 p1[], Vector2 p2[]){ + pair e1[]{ + make_pair(p1[0], p1[1]), + make_pair(p1[1], p1[2]), + make_pair(p1[2], p1[3]), + make_pair(p1[3], p1[0]) + }; + pair e2[]{ + make_pair(p2[0], p2[1]), + make_pair(p2[1], p2[2]), + make_pair(p2[2], p2[3]), + make_pair(p2[3], p2[0]) + }; + + for(int i = 0; i < 4; i++){ + //float a = hypVec.z / hypVec.x; + //float b = pos.z - a * pos.x; + + Vector2 e1Vec = e1[i].second - e1[i].first; + float a1, b1, x1; + bool vert1 = true; + + if(e1Vec.x != 0){ + vert1 = false; + a1 = e1Vec.y / e1Vec.x; + b1 = e1[i].second.y - a1 * e1[i].second.x; + } + else x1 = e1[i].first.x; + + for(int j = 0; j < 4; j++){ + Vector2 e2Vec = e2[j].second - e2[j].first; + float a2, b2, x2; + bool vert2 = true; + + if(e2Vec.x != 0){ + vert2 = false; + a2 = e2Vec.y / e2Vec.x; + b2 = e2[j].second.y - a2 * e2[j].second.x; + } + else x2 = e2[j].first.x; + + if(!vert1 && !vert2){ + if(a1 - a2 == 0) continue; + + float x = (b1 - b2) / (a1 - a2); + float y = a1 * x + b1; + + if( + (e1[i].first.x < x && x < e1[i].second.x) && + (e1[i].first.y < y && y < e1[i].second.y) + ){ + return true; + } + } + else if(!vert1 && vert2){ + float minX = e1[i].first.x, maxX = e1[i].second.x; + float minY = e2[i].first.y, maxY = e2[i].second.y; + + if(minX > maxX) swap(minY, maxY); + if(minY > maxY) swap(minY, maxY); + + float y = a1 * x2 + b1; + + if((minX < x2 && x2 < maxX) && (minY < y && y < maxY)){ + return true; + } + } + else if(vert1 && !vert2){ + float minX = e2[j].first.x, maxX = e2[j].second.x; + float minY = e1[j].first.y, maxY = e1[j].second.y; + + if(minX > maxX) swap(minY, maxY); + if(minY > maxY) swap(minY, maxY); + + float y = a2 * x1 + b2; + + if((minX < x1 && x1 < maxX) && (minY < y && y < maxY)){ + return true; + } + } + } + } + + return false; + } + + bool rectanglesIntersect(Vector2 rp1, Vector2 rd1, Vector2 rdl1, Vector2 rps1, Vector2 rp2, Vector2 rd2, Vector2 rdl2, Vector2 rps2){ + Vector2 p1[]{ + rp1 + .5 * (rdl1 * rps1.x + rd1 * rps1.y), + rp1 + .5 * (-rdl1 * rps1.x + rd1 * rps1.y), + rp1 + .5 * (-rdl1 * rps1.x - rd1 * rps1.y), + rp1 + .5 * (rdl1 * rps1.x - rd1 * rps1.y) + }; + Vector2 p2[]{ + rp2 + .5 * (rdl2 * rps2.x + rd2 * rps2.y), + rp2 + .5 * (-rdl2 * rps2.x + rd2 * rps2.y), + rp2 + .5 * (-rdl2 * rps2.x - rd2 * rps2.y), + rp2 + .5 * (rdl2 * rps2.x - rd2 * rps2.y) + }; + + if(rectInter(rp1, rd1, rps1, p2)) return true; + if(rectInter(rp2, rd2, rps2, p1)) return true; + + if(segmInter(p1, p2)) return true; + + return false; + } + void readFile(string path, vector &lines, int firstLine, int lastLine){ string l; std::ifstream inFile(path); diff --git a/util.h b/util.h index 05b70e3..5237c3c 100755 --- a/util.h +++ b/util.h @@ -21,6 +21,9 @@ namespace vb01{ static const float PI = 4 * atan(1); + bool rectInter(Vector2, Vector2, Vector2, Vector2[]); + bool segmInter(Vector2[], Vector2[]); + bool rectanglesIntersect(Vector2, Vector2, Vector2, Vector2, Vector2, Vector2, Vector2, Vector2); void readFile(std::string, std::vector&, int = 0, int = -1); void getLineData(std::string, std::string[], int, int = 0); int findNthOccurence(std::string&, std::string, int, bool = true); diff --git a/xmlModelReader.cpp b/xmlModelReader.cpp index f268ab7..1e77a36 100644 --- a/xmlModelReader.cpp +++ b/xmlModelReader.cpp @@ -190,7 +190,24 @@ namespace vb01{ const char *fullSkeletonName = meshEl->Attribute("skeleton"); string name = string(meshEl->Parent()->ToElement()->Attribute("name")) + string(meshEl->Attribute("name")); - Mesh *mesh = new Mesh(MeshData(vertPos, weights, boneIndices, shapeKeyOffsets, numVertPos, normals, vertices, indices, numVertices / 3, name, vertexGroups, numVertexGroups, (fullSkeletonName ? fullSkeletonName : ""), shapeKeys, numShapeKeys)); + MeshData meshData = MeshData( + vertPos, + weights, + boneIndices, + shapeKeyOffsets, + numVertPos, + normals, + vertices, + indices, + numVertices / 3, + name, + vertexGroups, + numVertexGroups, + (fullSkeletonName ? fullSkeletonName : ""), + shapeKeys, + numShapeKeys + ); + Mesh *mesh = new Mesh(meshData); return mesh; }