#ifndef GROUND_H #define GROUND_H #include #include "../gl/GLHelper.h" #include "../gl/GLTriangles.h" #include "../gl/GLLines.h" #include "../Renderable.h" #include "../../../../lib/gpc/Polygon.h" class Ground : public Renderable { private: Floorplan::Floor* floor; GLTriangles flooring; GLTriangles ceiling; GLLines outline; bool outlineOnly = false; bool transparent = false; public: /** ctor */ Ground(Floorplan::Floor* floor) : floor(floor) { setOutlineOnly(false); } void initGL() override { build(); flooring.setDiffuse(":/res/gl/tex/floor4.jpg"); flooring.setNormalMap(":/res/gl/tex/floor4_normal.jpg"); ceiling.setDiffuse(":/res/gl/tex/floor4.jpg"); ceiling.setNormalMap(":/res/gl/tex/floor4_normal.jpg"); flooring.build(); ceiling.build(); outline.build(); //loadShader(":/res/gl/vertex1.glsl", ":/res/gl/fragmentTex.glsl"); //program.setUniformValue("texDiffuse", 0); //program.setUniformValue("texNormalMap", 1); } /** render the floor */ void _render(const RenderParams& params) override { // skip me? if (params.clipAboveHeight_m < floor->atHeight) {return;} if (transparent) { program.setUniformValue("alpha", 0.5f); glEnable(GL_BLEND); } else { program.setUniformValue("alpha", 1.0f); glDisable(GL_BLEND); } if (outlineOnly) { glLineWidth(5); outline.render(&program); } else { flooring.render(&program); ceiling.render(&program); } glDisable(GL_BLEND); } /** render only the outline? */ void setOutlineOnly(const bool outline) override { (void) outline; // this->outlineOnly = outline; // if (outlineOnly) { // loadShader(":/res/gl/vertex1.glsl", ":/res/gl/fragmentLine.glsl"); // program.setUniformValue("color", QVector4D(0.0, 0.0, 0.4, 1.0)); // } else { loadShader(":/res/gl/vertex1.glsl", ":/res/gl/fragmentTex.glsl"); program.setUniformValue("texDiffuse", 0); program.setUniformValue("texNormalMap", 1); // } } void setTransparent(const bool transparent) override { this->transparent = transparent; } private: void build() { std::vector add; std::vector rem; const std::vector& polys = floor->outline; Polygon pol; for (Floorplan::FloorOutlinePolygon* poly : polys) { switch (poly->method) { case Floorplan::OutlineMethod::ADD: pol.add(poly->poly); break; case Floorplan::OutlineMethod::REMOVE: pol.remove(poly->poly); break; default: throw 1; } } std::vector> trias = pol.get(floor->atHeight); // is stored as TRIANGLE_STRIP // => triangle might have more than 3 points for (const std::vector& tria : trias) { const QVector3D normFloor(0, +1, 0); const QVector3D normCeil(0, -1, 0); const QVector3D t(1,0,0); const float s = 0.6; // add vertices for (int i = 2; i < (int) tria.size(); i+=1) { const Point3 p1 = tria[i-2]; const Point3 p2 = tria[i-1]; const Point3 p3 = tria[i-0]; const QVector3D vert1(p1.x, p1.z, p1.y); const QVector3D vert2(p2.x, p2.z, p2.y); const QVector3D vert3(p3.x, p3.z, p3.y); { const VertNormTexTan vnt1(vert1, normFloor, tex(vert1*s), t); const VertNormTexTan vnt2(vert2, normFloor, tex(vert2*s), t); const VertNormTexTan vnt3(vert3, normFloor, tex(vert3*s), t); flooring.addFaceCCW(vnt1, vnt2, vnt3); } { const VertNormTexTan vnt1(vert1, normCeil, tex(vert1*s), t); const VertNormTexTan vnt2(vert2, normCeil, tex(vert2*s), t); const VertNormTexTan vnt3(vert3, normCeil, tex(vert3*s), t); ceiling.addFaceCW(vnt1, vnt2, vnt3); } outline.addLine(vert1, vert2); outline.addLine(vert2, vert3); outline.addLine(vert3, vert1); } } } private: QVector2D tex(const QVector3D vert) { return QVector2D(vert.x(), vert.z()); } }; #endif // GROUND_H