// // Created by Иван Ильин on 13.01.2021. // #include #include "Mesh.h" #include "ResourceManager.h" #include "Screen.h" using namespace std; Mesh &Mesh::operator*=(const Matrix4x4 &matrix4X4) { std::vector newTriangles; newTriangles.reserve(_tris.size()); for (auto &t : _tris) { newTriangles.emplace_back(t * matrix4X4); } setTriangles(std::move(newTriangles)); return *this; } void Mesh::loadObj(const std::string &filename, const Vec3D &scale) { _tris.clear(); auto objects = ResourceManager::loadObjects(filename); for (auto &obj : objects) { for (auto &tri : obj->triangles()) { _tris.push_back(tri); } } this->scale(scale); } Mesh::Mesh(ObjectNameTag nameTag, const std::string &filename, const Vec3D &scale) : Object(std::move(nameTag)) { loadObj(filename, scale); } Mesh::Mesh(ObjectNameTag nameTag, const vector &tries) : Object(std::move(nameTag)), _tris(tries) {} void Mesh::setColor(const sf::Color &c) { _color = c; for (auto &t : _tris) { t.setColor(c); } // because we change the color of mesh we should update geometry with a new color glFreeFloatArray(); } Mesh Mesh::LineTo(ObjectNameTag nameTag, const Vec3D &from, const Vec3D &to, double line_width, const sf::Color &color) { Mesh line(std::move(nameTag)); Vec3D v1 = (to - from).normalized(); Vec3D v2 = from.cross(from + Vec3D{1, 0, 0}).normalized(); Vec3D v3 = v1.cross(v2).normalized(); // from plane Vec4D p1 = (- v2 * line_width / 2.0 - v3 * line_width / 2.0).makePoint4D(); Vec4D p2 = (- v2 * line_width / 2.0 + v3 * line_width / 2.0).makePoint4D(); Vec4D p3 = ( v2 * line_width / 2.0 + v3 * line_width / 2.0).makePoint4D(); Vec4D p4 = ( v2 * line_width / 2.0 - v3 * line_width / 2.0).makePoint4D(); // to plane Vec4D p5 = (to - from - v2 * line_width / 2.0 - v3 * line_width / 2.0).makePoint4D(); Vec4D p6 = (to - from - v2 * line_width / 2.0 + v3 * line_width / 2.0).makePoint4D(); Vec4D p7 = (to - from + v2 * line_width / 2.0 + v3 * line_width / 2.0).makePoint4D(); Vec4D p8 = (to - from + v2 * line_width / 2.0 - v3 * line_width / 2.0).makePoint4D(); line._tris = std::move(std::vector{ {p2, p4, p1}, {p2, p3, p4}, {p1, p6, p2}, {p1, p5, p6}, {p2, p6, p7}, {p2, p7, p3}, {p6, p5, p8}, {p6, p8, p7}, {p4, p3, p7}, {p4, p7, p8}, {p1, p8, p5}, {p1, p4, p8} }); line.setColor(color); line.translateToPoint(from); return line; } Mesh Mesh::ArrowTo(ObjectNameTag nameTag, const Vec3D &from, const Vec3D &to, double line_width, sf::Color color) { Mesh arrow(std::move(nameTag)); Vec3D v1 = (to - from).normalized(); Vec3D v2 = from.cross(from + Vec3D{1, 0, 0}).normalized(); Vec3D v3 = v1.cross(v2).normalized(); Vec3D to_line = to - v1*0.4; // from plane Vec4D p1 = (- v2 * line_width / 2.0 - v3 * line_width / 2.0).makePoint4D(); Vec4D p2 = (- v2 * line_width / 2.0 + v3 * line_width / 2.0).makePoint4D(); Vec4D p3 = ( v2 * line_width / 2.0 + v3 * line_width / 2.0).makePoint4D(); Vec4D p4 = ( v2 * line_width / 2.0 - v3 * line_width / 2.0).makePoint4D(); // to plane Vec4D p5 = (to_line - from - v2 * line_width / 2.0 - v3 * line_width / 2.0).makePoint4D(); Vec4D p6 = (to_line - from - v2 * line_width / 2.0 + v3 * line_width / 2.0).makePoint4D(); Vec4D p7 = (to_line - from + v2 * line_width / 2.0 + v3 * line_width / 2.0).makePoint4D(); Vec4D p8 = (to_line - from + v2 * line_width / 2.0 - v3 * line_width / 2.0).makePoint4D(); // arrow Vec4D p9 = (to_line - from - v2 * line_width*2 - v3 * line_width*2).makePoint4D(); Vec4D p10 = (to_line - from - v2 * line_width*2 + v3 * line_width*2).makePoint4D(); Vec4D p11 = (to_line - from + v2 * line_width*2 + v3 * line_width*2).makePoint4D(); Vec4D p12 = (to_line - from + v2 * line_width*2 - v3 * line_width*2).makePoint4D(); Vec4D p13 = (to - from).makePoint4D(); arrow._tris = std::move(std::vector{ {p2, p4, p1}, {p2, p3, p4}, {p1, p6, p2}, {p1, p5, p6}, {p2, p6, p7}, {p2, p7, p3}, {p6, p5, p8}, {p6, p8, p7}, {p4, p3, p7}, {p4, p7, p8}, {p1, p8, p5}, {p1, p4, p8}, { p9, p10, p13 }, { p10, p11, p13 }, { p11, p12, p13 }, { p12, p9, p13 }, }); arrow.setColor(color); arrow.translateToPoint(from); return arrow; } void Mesh::setOpacity(double t) { setColor(sf::Color(_color.r, _color.g, _color.b, t*255)); } void Mesh::setTriangles(vector&& t) { _tris = std::move(t); } Mesh::~Mesh() { delete[] _geometry; _geometry = nullptr; } void Mesh::glFreeFloatArray() { delete[] _geometry; _geometry = nullptr; } GLfloat *Mesh::glFloatArray() const { if(_geometry != nullptr) { return _geometry; } _geometry = new GLfloat[7 * 3 * _tris.size()]; for (size_t i = 0; i < _tris.size(); i++) { unsigned stride = 21 * i; Triangle triangle = _tris[i]; Vec3D norm = (model()*triangle.norm()).normalized(); float dot = static_cast(norm.dot(Vec3D(0, 1, 2).normalized())); for (int k = 0; k < 3; k++) { sf::Color color = triangle.color(); GLfloat ambientColor[4] = { static_cast(color.r) * (0.3f * std::fabs(dot) + 0.7f) / 255.0f, static_cast(color.g) * (0.3f * std::fabs(dot) + 0.7f) / 255.0f, static_cast(color.b) * (0.3f * std::fabs(dot) + 0.7f) / 255.0f, static_cast(color.a) / 255.0f }; _geometry[stride + 7 * k + 0] = static_cast(triangle[k].x()); _geometry[stride + 7 * k + 1] = static_cast(triangle[k].y()); _geometry[stride + 7 * k + 2] = static_cast(triangle[k].z()); _geometry[stride + 7 * k + 3] = ambientColor[0]; _geometry[stride + 7 * k + 4] = ambientColor[1]; _geometry[stride + 7 * k + 5] = ambientColor[2]; _geometry[stride + 7 * k + 6] = ambientColor[3]; } } return _geometry; } Mesh Mesh::Cube(ObjectNameTag tag, double size, sf::Color color) { Mesh cube(std::move(tag)); cube._tris = { { Vec4D{0.0, 0.0, 0.0, 1.0}, Vec4D{0.0, 1.0, 0.0, 1.0}, Vec4D{1.0, 1.0, 0.0, 1.0} }, { Vec4D{0.0, 0.0, 0.0, 1.0}, Vec4D{1.0, 1.0, 0.0, 1.0}, Vec4D{1.0, 0.0, 0.0, 1.0} }, { Vec4D{1.0, 0.0, 0.0, 1.0}, Vec4D{1.0, 1.0, 0.0, 1.0}, Vec4D{1.0, 1.0, 1.0, 1.0} }, { Vec4D{1.0, 0.0, 0.0, 1.0}, Vec4D{1.0, 1.0, 1.0, 1.0}, Vec4D{1.0, 0.0, 1.0, 1.0} }, { Vec4D{1.0, 0.0, 1.0, 1.0}, Vec4D{1.0, 1.0, 1.0, 1.0}, Vec4D{0.0, 1.0, 1.0, 1.0} }, { Vec4D{1.0, 0.0, 1.0, 1.0}, Vec4D{0.0, 1.0, 1.0, 1.0}, Vec4D{0.0, 0.0, 1.0, 1.0} }, { Vec4D{0.0, 0.0, 1.0, 1.0}, Vec4D{0.0, 1.0, 1.0, 1.0}, Vec4D{0.0, 1.0, 0.0, 1.0} }, { Vec4D{0.0, 0.0, 1.0, 1.0}, Vec4D{0.0, 1.0, 0.0, 1.0}, Vec4D{0.0, 0.0, 0.0, 1.0} }, { Vec4D{0.0, 1.0, 0.0, 1.0}, Vec4D{0.0, 1.0, 1.0, 1.0}, Vec4D{1.0, 1.0, 1.0, 1.0} }, { Vec4D{0.0, 1.0, 0.0, 1.0}, Vec4D{1.0, 1.0, 1.0, 1.0}, Vec4D{1.0, 1.0, 0.0, 1.0} }, { Vec4D{1.0, 0.0, 1.0, 1.0}, Vec4D{0.0, 0.0, 1.0, 1.0}, Vec4D{0.0, 0.0, 0.0, 1.0} }, { Vec4D{1.0, 0.0, 1.0, 1.0}, Vec4D{0.0, 0.0, 0.0, 1.0}, Vec4D{1.0, 0.0, 0.0, 1.0} }, }; cube.setColor(color); return cube *= Matrix4x4::Scale(Vec3D(size, size, size))*Matrix4x4::Translation(Vec3D(-0.5, -0.5, -0.5)); }