/* * © Copyright 2014 – Urheberrechtshinweis * Alle Rechte vorbehalten / All Rights Reserved * * Programmcode ist urheberrechtlich geschuetzt. * Das Urheberrecht liegt, soweit nicht ausdruecklich anders gekennzeichnet, bei Frank Ebner. * Keine Verwendung ohne explizite Genehmigung. * (vgl. § 106 ff UrhG / § 97 UrhG) */ #ifndef FLOORPLAN_3D_OUTLINE_H #define FLOORPLAN_3D_OUTLINE_H #include "Obstacle3.h" #include "misc.h" #include #include "../../geo/GPCPolygon2.h" namespace Floorplan3D { class Outline { public: /** convert a floor (floor/ceiling) into triangles */ std::vector get(const Floorplan::Floor* f) { FloorPos fpos(f); std::vector res; if (!f->enabled) {return res;} if (!f->outline.enabled) {return res;} // floor uses an outline based on "add" and "remove" areas // we need to create the apropriate triangles to model the polygon // including all holes (remove-areas) // process all "add" regions by type // [this allows for overlaps of the same type] std::unordered_map types; for (Floorplan::FloorOutlinePolygon* fop : f->outline) { if (fop->method == Floorplan::OutlineMethod::ADD) { if (fop->outdoor) { types["outdoor"].add(fop->poly); } else { types["indoor"].add(fop->poly); } } } // remove the "remove" regions from EVERY "add" region added within the previous step for (Floorplan::FloorOutlinePolygon* fop : f->outline) { if (fop->method == Floorplan::OutlineMethod::REMOVE) { for (auto& it : types) { it.second.remove(fop->poly); } } // allow for overlapping outdoor/indoor regions -> outdoor wins [remove outdoor part from indoor parts] if (fop->outdoor) { types["indoor"].remove(fop->poly); } } // create an obstacle for each type (indoor, outdoor) for (auto& it : types) { // TODO: variable type? Obstacle3D::Type type = (it.first == "indoor") ? (Obstacle3D::Type::GROUND_INDOOR) : (Obstacle3D::Type::GROUND_OUTDOOR); Obstacle3D obs(type, Floorplan::Material::CONCRETE); // convert them into polygons std::vector> polys = it.second.get(fpos.z1); // convert polygons (GL_TRIANGLE_STRIP) to triangles for (const std::vector& pts : polys) { for (int i = 0; i < (int)pts.size() - 2; ++i) { // floor must be double-sided Triangle3 tria1 (pts[i+0], pts[i+1], pts[i+2]); Triangle3 tria2 (pts[i+2], pts[i+1], pts[i+0]); // ensure the triangle with the normal pointing downwards (towards bulding's cellar) // is below the triangle that points upwards (towards the sky) if (tria1.getNormal().z < 0) {std::swap(tria1, tria2);} // tria2 = ceiling of previous floor tria2 -= Point3(0,0,fpos.fh); // add both obs.triangles.push_back(tria1); obs.triangles.push_back(tria2); } } res.push_back(obs); } return res; } }; } #endif // FLOORPLAN_3D_OUTLINE_H