diff --git a/CMakeLists.txt b/CMakeLists.txt index 5904ce5..86bde16 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ cmake_policy(SET CMP0015 NEW) set(GUI text.cpp) set(UTILS util.cpp) -set(MATH quaternion.cpp vector.cpp matrix.cpp ray.cpp) +set(MATH quaternion.cpp vector.cpp matrix.cpp rayCaster.cpp) set(RENDER lineRenderer.cpp particleEmitter.cpp camera.cpp light.cpp material.cpp mesh.cpp meshData.cpp model.cpp node.cpp quad.cpp box.cpp root.cpp shader.cpp texture.cpp) set(ANIM animationController.cpp animationChannel.cpp animation.cpp animatable.cpp keyframeChannel.cpp driver.cpp) set(ARMATURE skeleton.cpp bone.cpp ikSolver.cpp) @@ -121,8 +121,8 @@ if(BUILD_SAMPLES) add_executable(particleEmitterSample particleEmitterSample.cpp) target_link_libraries(particleEmitterSample ${LIB_NAME}) - add_executable(raySample raySample.cpp) - target_link_libraries(raySample ${LIB_NAME}) + add_executable(rayCasterSample rayCasterSample.cpp) + target_link_libraries(rayCasterSample ${LIB_NAME}) add_executable(pbrSample pbrSample.cpp) target_link_libraries(pbrSample ${LIB_NAME}) diff --git a/abstractGuiManager.cpp b/abstractGuiManager.cpp index 6a79207..f30f2c8 100644 --- a/abstractGuiManager.cpp +++ b/abstractGuiManager.cpp @@ -5,6 +5,8 @@ #include "slider.h" #include "checkbox.h" #include "listbox.h" +#include "node.h" +#include "text.h" #include "util.h" namespace vb01Gui{ @@ -120,10 +122,6 @@ namespace vb01Gui{ } } - void AbstractGuiManager::addButton(Button* b) { - buttons.push_back(b); - } - void AbstractGuiManager::addListbox(Listbox* l) { listboxes.push_back(l); buttons.push_back(l->getListboxButton()); @@ -205,11 +203,46 @@ namespace vb01Gui{ } } + void AbstractGuiManager::removeGuiRectangle(Node* r) { + for (int i = 0; i < guiRectangles.size(); i++) { + if (r == guiRectangles[i]) { + guiRectangles.erase(guiRectangles.begin() + i); + Root::getSingleton()->getGuiNode()->dettachChild(r); + delete r; + break; + } + } + } + + void AbstractGuiManager::removeText(Text* t) { + for (int i = 0; i < texts.size(); i++) { + if (t == texts[i]) { + texts.erase(texts.begin() + i); + Node *textNode = t->getNode(); + Root::getSingleton()->getGuiNode()->dettachChild(textNode); + delete textNode; + break; + } + } + } + + Text* AbstractGuiManager::getText(string name){ + Text *text = nullptr; + + for(Text *t : texts) + if(t->getNode()->getName() == name){ + text = t; + break; + } + + return text; + } + void AbstractGuiManager::removeAllButtons(vector exceptions){ int targetId = 0; while(targetId != buttons.size()){ - if(find(exceptions.begin(), exceptions.end(), buttons[targetId]) == exceptions.end()){ + if(buttons[targetId]->isSeparate() && find(exceptions.begin(), exceptions.end(), buttons[targetId]) == exceptions.end()){ delete buttons[targetId]; buttons.erase(buttons.begin() + targetId); } @@ -218,36 +251,90 @@ namespace vb01Gui{ } } - void AbstractGuiManager::removeAllListboxes() { - while (listboxes.size() > 0) { - removeButton(listboxes[listboxes.size() - 1]->getListboxButton()); - delete listboxes[listboxes.size() - 1]; - listboxes.pop_back(); + void AbstractGuiManager::removeAllListboxes(vector exceptions) { + int targetId = 0; + + while(targetId != listboxes.size()) { + if(find(exceptions.begin(), exceptions.end(), listboxes[targetId]) == exceptions.end()){ + removeButton(listboxes[listboxes.size() - 1]->getListboxButton()); + delete listboxes[listboxes.size() - 1]; + listboxes.pop_back(); + } + else + targetId++; } } - void AbstractGuiManager::removeAllCheckboxes() { - while (checkboxes.size() > 0) { - removeButton(checkboxes[checkboxes.size() - 1]->getCheckboxButton()); - delete checkboxes[checkboxes.size() - 1]; - checkboxes.pop_back(); + void AbstractGuiManager::removeAllCheckboxes(vector exceptions) { + int targetId = 0; + + while(targetId != checkboxes.size()) { + if(find(exceptions.begin(), exceptions.end(), checkboxes[targetId]) == exceptions.end()){ + removeButton(checkboxes[checkboxes.size() - 1]->getCheckboxButton()); + delete checkboxes[checkboxes.size() - 1]; + checkboxes.pop_back(); + } + else + targetId++; } } - void AbstractGuiManager::removeAllSliders() { - while (sliders.size() > 0) { - removeButton(sliders[sliders.size() - 1]->getMovableSliderButton()); - removeButton(sliders[sliders.size() - 1]->getStaticSliderButton()); - delete sliders[sliders.size() - 1]; - sliders.pop_back(); + void AbstractGuiManager::removeAllSliders(vector exceptions) { + int targetId = 0; + + while(targetId != sliders.size()) { + if(find(exceptions.begin(), exceptions.end(), sliders[targetId]) == exceptions.end()){ + removeButton(sliders[sliders.size() - 1]->getMovableSliderButton()); + removeButton(sliders[sliders.size() - 1]->getStaticSliderButton()); + delete sliders[sliders.size() - 1]; + sliders.pop_back(); + } + else + targetId++; } } - void AbstractGuiManager::removeAllTextboxes() { - while (textboxes.size() > 0) { - removeButton(textboxes[textboxes.size() - 1]->getTextboxButton()); - delete textboxes[textboxes.size() - 1]; - textboxes.pop_back(); + void AbstractGuiManager::removeAllTextboxes(vector exceptions) { + int targetId = 0; + + while(targetId != textboxes.size()) { + if(find(exceptions.begin(), exceptions.end(), textboxes[targetId]) == exceptions.end()){ + removeButton(textboxes[textboxes.size() - 1]->getTextboxButton()); + delete textboxes[textboxes.size() - 1]; + textboxes.pop_back(); + } + else + targetId++; + } + } + + void AbstractGuiManager::removeAllGuiRectangles(vector exceptions) { + int targetId = 0; + + while(targetId != guiRectangles.size()) { + if(find(exceptions.begin(), exceptions.end(), guiRectangles[targetId]) == exceptions.end()){ + Node *guiRect = guiRectangles[guiRectangles.size() - 1]; + guiRectangles.pop_back(); + Root::getSingleton()->getGuiNode()->dettachChild(guiRect); + delete guiRect; + } + else + targetId++; + } + } + + void AbstractGuiManager::removeAllTexts(vector exceptions) { + int targetId = 0; + + while(targetId != texts.size()) { + if(find(exceptions.begin(), exceptions.end(), texts[targetId]) == exceptions.end()){ + Node *textNode = texts[texts.size() - 1]->getNode(); + texts.pop_back(); + Root::getSingleton()->getGuiNode()->dettachChild(textNode); + delete textNode; + } + else + targetId++; } } @@ -256,11 +343,15 @@ namespace vb01Gui{ vector listboxExceptions, vector checkboxExceptions, vector sliderExceptions, - vector textboxExceptions){ + vector textboxExceptions, + vector guiRectExceptions, + vector textExceptions){ removeAllButtons(buttonExceptions); - removeAllListboxes(); - removeAllCheckboxes(); - removeAllSliders(); - removeAllTextboxes(); + removeAllListboxes(listboxExceptions); + removeAllCheckboxes(checkboxExceptions); + removeAllSliders(sliderExceptions); + removeAllTextboxes(textboxExceptions); + removeAllGuiRectangles(guiRectExceptions); + removeAllTexts(textExceptions); } } diff --git a/abstractGuiManager.h b/abstractGuiManager.h index bfa6b68..efcf824 100644 --- a/abstractGuiManager.h +++ b/abstractGuiManager.h @@ -4,6 +4,11 @@ #include #include +namespace vb01{ + class Node; + class Text; +} + namespace vb01Gui{ class Button; class Listbox; @@ -15,45 +20,56 @@ namespace vb01Gui{ public: void update(); void findClickedButton(); - void addButton(vb01Gui::Button*); - void removeButton(vb01Gui::Button*); + void addButton(Button *b){buttons.push_back(b);} + void removeButton(Button*); void removeButton(std::string); - void addListbox(vb01Gui::Listbox*); - void removeListbox(vb01Gui::Listbox*); - void addCheckbox(vb01Gui::Checkbox*); - void removeCheckbox(vb01Gui::Checkbox*); - void addTextbox(vb01Gui::Textbox*); - void removeTextbox(vb01Gui::Textbox*); - void addSlider(vb01Gui::Slider*); - void removeSlider(vb01Gui::Slider*); - void removeAllButtons(std::vector = std::vector{}); - void removeAllListboxes(); - void removeAllCheckboxes(); - void removeAllSliders(); - void removeAllTextboxes(); + void addListbox(Listbox*); + void removeListbox(Listbox*); + void addCheckbox(Checkbox*); + void removeCheckbox(Checkbox*); + void addTextbox(Textbox*); + void removeTextbox(Textbox*); + void addSlider(Slider*); + void addGuiRectangle(vb01::Node *r){guiRectangles.push_back(r);} + void removeGuiRectangle(vb01::Node*); + void addText(vb01::Text *t){texts.push_back(t);} + void removeText(vb01::Text*); + vb01::Text* getText(std::string); + void removeSlider(Slider*); + void removeAllButtons(std::vector = std::vector{}); + void removeAllListboxes(std::vector = std::vector{}); + void removeAllCheckboxes(std::vector = std::vector{}); + void removeAllSliders(std::vector = std::vector{}); + void removeAllTextboxes(std::vector = std::vector{}); + void removeAllGuiRectangles(std::vector = std::vector{}); + void removeAllTexts(std::vector = std::vector{}); void removeAllGuiElements( std::vector = std::vector{}, std::vector = std::vector{}, std::vector = std::vector{}, std::vector = std::vector{}, - std::vector = std::vector{} + std::vector = std::vector{}, + std::vector = std::vector{}, + std::vector = std::vector{} ); inline std::vector getButtons(){return buttons;} inline std::vector getListboxes(){return listboxes;} inline std::vector getTextboxes(){return textboxes;} private: - void updateCurrentListbox(vb01Gui::Button*, bool&); - void updateCurrentSlider(vb01Gui::Button*); - void updateCurrentTextbox(vb01Gui::Button*, bool&); + void updateCurrentListbox(Button*, bool&); + void updateCurrentSlider(Button*); + void updateCurrentTextbox(Button*, bool&); std::vector buttons; std::vector listboxes; std::vector checkboxes; std::vector sliders; std::vector textboxes; - vb01Gui::Slider *currentSlider = nullptr; - vb01Gui::Textbox *currentTextbox = nullptr; - vb01Gui::Listbox *currentListbox = nullptr; + std::vector guiRectangles; + std::vector texts; + Slider *currentSlider = nullptr; + Textbox *currentTextbox = nullptr; + Listbox *currentListbox = nullptr; protected: AbstractGuiManager(){} }; diff --git a/node.h b/node.h index d1978a3..1758e91 100755 --- a/node.h +++ b/node.h @@ -52,6 +52,7 @@ namespace vb01{ inline std::vector& getSkeletons(){return skeletons;} inline Mesh* getMesh(int i){return meshes[i];} inline int getNumMeshes(){return meshes.size();} + inline ParticleEmitter* getParticleEmitter(int i){return emitters[i];} inline Node* getParent(){return parent;} inline void setParent(Node *par){this->parent = par;} inline Node* getChild(int i){return children[i];} diff --git a/particleEmitter.h b/particleEmitter.h index b6523f8..b3a3236 100755 --- a/particleEmitter.h +++ b/particleEmitter.h @@ -19,6 +19,7 @@ namespace vb01{ ParticleEmitter() : Animatable(Animatable::NONE){} ~ParticleEmitter(); void update(); + inline Material* getMaterial(){return material;} inline void setMaterial(Material *mat){this->material = mat;} inline void setNode(Node *node){this->node = node;} inline void setSize(Vector2 size){this->size = size;} @@ -54,7 +55,6 @@ namespace vb01{ int numParticles; Particle **particles; Material *material = nullptr; - Node *node = nullptr; Vector2 size = Vector2::VEC_IJ; Vector3 gravity = Vector3::VEC_ZERO; Vector4 startColor = Vector4::VEC_IJKL, endColor = Vector4::VEC_IJKL; diff --git a/ray.h b/ray.h deleted file mode 100644 index 5c7d40b..0000000 --- a/ray.h +++ /dev/null @@ -1,22 +0,0 @@ -#include "vector.h" -#include "util.h" - -#include - -namespace vb01{ - class Node; - class Mesh; - - class Ray{ - public: - struct CollisionResult{ - Vector3 pos, norm; - float distance; - Mesh *mesh = nullptr; - }; - static void retrieveCollisions(Vector3, Vector3, Node*, std::vector&, const float = .0); - static void castRay(Vector3, Vector3, Node*, std::vector&, const float); - static void sortResults(std::vector&); - }; - -} diff --git a/ray.cpp b/rayCaster.cpp similarity index 66% rename from ray.cpp rename to rayCaster.cpp index 5030b5d..342dc1e 100644 --- a/ray.cpp +++ b/rayCaster.cpp @@ -1,22 +1,38 @@ #include -#include "ray.h" +#include "rayCaster.h" #include "mesh.h" #include "node.h" using namespace std; namespace vb01{ - void Ray::retrieveCollisions(Vector3 rayPos, Vector3 rayDir, Node *node, std::vector &results, const float rayLength){ - castRay(rayPos, rayDir, node, results, rayLength); - - for(Node *c : node->getChildren()) - retrieveCollisions(rayPos, rayDir, c, results, rayLength); + vector RayCaster::cast(Vector3 rayPos, Vector3 rayDir, Node *node, const float rayLength){ + return cast(rayPos, rayDir, vector{node}, rayLength); } - void Ray::castRay(Vector3 rayPos, Vector3 rayDir, Node *node, vector &results, float rayLength){ + vector RayCaster::cast(Vector3 rayPos, Vector3 rayDir, vector nodes, const float rayLength){ + vector results; + + for(Node *node : nodes){ + vector descendants = vector{node}; + node->getDescendants(descendants); + + for(Node *desc : descendants){ + vector res = retrieveCollisions(rayPos, rayDir, desc, rayLength); + results.insert(results.end(), res.begin(), res.end()); + } + } + + if(!results.empty()) sortResults(results); + + return results; + } + + vector RayCaster::retrieveCollisions(Vector3 rayPos, Vector3 rayDir, Node *node, float rayLength){ Vector3 pos = node->localToGlobalPosition(Vector3::VEC_ZERO); Quaternion rot = node->localToGlobalOrientation(Quaternion::QUAT_W); + vector results; for(Mesh *m : node->getMeshes()){ const int numVerts = m->getMeshBase().numTris * 3; @@ -64,14 +80,15 @@ namespace vb01{ } } } + + return results; } - void Ray::sortResults(std::vector &results){ - if(!results.empty()) - for(int i = 0; i < results.size(); i++){ - for(int i2 = i; i2 < results.size(); i2++) - if(results[i].distance > results[i2].distance) - swap(results[i], results[i2]); - } + void RayCaster::sortResults(std::vector &results){ + for(int i = 0; i < results.size(); i++){ + for(int j = i; j < results.size(); j++) + if(results[i].distance > results[j].distance) + swap(results[i], results[j]); + } } } diff --git a/rayCaster.h b/rayCaster.h new file mode 100644 index 0000000..2e8deb8 --- /dev/null +++ b/rayCaster.h @@ -0,0 +1,25 @@ +#include "vector.h" +#include "util.h" + +#include + +namespace vb01{ + class Node; + class Mesh; + + class RayCaster{ + public: + struct CollisionResult{ + Vector3 pos, norm; + float distance; + Mesh *mesh = nullptr; + }; + + static std::vector cast(Vector3, Vector3, Node*, const float = .0); + static std::vector cast(Vector3, Vector3, std::vector, const float = .0); + private: + static std::vector retrieveCollisions(Vector3, Vector3, Node*, const float); + static void sortResults(std::vector&); + }; + +} diff --git a/raySample.cpp b/rayCasterSample.cpp similarity index 93% rename from raySample.cpp rename to rayCasterSample.cpp index 536258e..5439610 100644 --- a/raySample.cpp +++ b/rayCasterSample.cpp @@ -3,7 +3,7 @@ #include "material.h" #include "assetManager.h" #include "lineRenderer.h" -#include "ray.h" +#include "rayCaster.h" using namespace std; using namespace vb01; @@ -76,11 +76,9 @@ int main(){ * Casts an infinite ray that checks for collision against meshes under * the icoshpere model node and paints it red upon collision */ - vector results; - Ray::retrieveCollisions(rayStart, rayEnd - rayStart, sphModel, results); - Ray::sortResults(results); mat->setVec4Uniform("diffuseColor", Vector4::VEC_L); + vector results = RayCaster::cast(rayStart, rayEnd - rayStart, sphModel); if(!results.empty()) mat->setVec4Uniform("diffuseColor", Vector4(1, 0, 0, 1)); diff --git a/samples/models/sphere.xml b/samples/models/sphere.xml index 7bb6797..f866172 100644 --- a/samples/models/sphere.xml +++ b/samples/models/sphere.xml @@ -1,288 +1,288 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - - - - - + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + - + - - - - + + + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - + + - - - - - - - + + + + + + + - - - - + + + + - + - - + + - - - + + + - + - - + + - - - - + + + + - - - - - + + + + + - - - - - - - - - - - - + + + + + + + + + + + + - + - - - - - - - - + + + + + + + + - - + + - - - - + + + + - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/script.py b/script.py index 9aeaca6..55a2147 100644 --- a/script.py +++ b/script.py @@ -151,6 +151,19 @@ def export(node, parentTag): nodeTag = ET.SubElement(parentTag, 'node') nodeTag.set('name', node.name) + nodeTag.set('px', str(node.location[0])) + nodeTag.set('py', str(node.location[2])) + nodeTag.set('pz', str(-node.location[1])) + + nodeTag.set('rw', str(node.rotation_quaternion[0])) + nodeTag.set('rx', str(node.rotation_quaternion[1])) + nodeTag.set('ry', str(node.rotation_quaternion[2])) + nodeTag.set('rz', str(node.rotation_quaternion[3])) + + nodeTag.set('sx', str(node.scale[0])) + nodeTag.set('sy', str(node.scale[1])) + nodeTag.set('sz', str(node.scale[2])) + if node.type == 'MESH': mesh = node.data numFaces = len(mesh.polygons) diff --git a/text.h b/text.h index 0177af9..c48cc22 100755 --- a/text.h +++ b/text.h @@ -28,6 +28,7 @@ namespace vb01{ void update(); void setText(std::wstring); inline void setScale(float s){this->scale = s;} + inline float getScale(){return scale;} inline int getLength(){return entry.length();} inline std::wstring getText(){return entry;} inline bool isHorizontal(){return horizontal;} diff --git a/xmlModelReader.cpp b/xmlModelReader.cpp index 2855925..011c6ca 100644 --- a/xmlModelReader.cpp +++ b/xmlModelReader.cpp @@ -276,8 +276,12 @@ namespace vb01{ ((Bone*)node)->setIkChainLength(ikChainLength); } } - else - node = new Node(Vector3::VEC_ZERO, Quaternion::QUAT_W, Vector3::VEC_IJK, name); + else{ + Vector3 pos = Vector3(atof(xmlEl->Attribute("px")), atof(xmlEl->Attribute("py")), atof(xmlEl->Attribute("pz"))); + Quaternion rot = Quaternion(atof(xmlEl->Attribute("rw")), atof(xmlEl->Attribute("rx")), atof(xmlEl->Attribute("ry")), atof(xmlEl->Attribute("rz"))); + Vector3 scale = Vector3(atof(xmlEl->Attribute("sx")), atof(xmlEl->Attribute("sy")), atof(xmlEl->Attribute("sz"))); + node = new Node(pos, rot, scale, name); + } XMLElement *skeletonTag = xmlEl->FirstChildElement("skeleton");