void PolygonAdapter::createNewPolygon(WFMath::Polygon<2>* existingPoly) { delete mPolygon; mPolygon = 0; Ogre::SceneNode* entitySceneNode = getEntitySceneNode(); if (entitySceneNode) { mPolygon = new Authoring::Polygon(entitySceneNode, mPositionProvider); WFMath::Polygon<2> poly; if (existingPoly) { poly = *existingPoly; } else { poly.addCorner(0, WFMath::Point<2>(-1, -1)); poly.addCorner(1, WFMath::Point<2>(-1, 1)); poly.addCorner(2, WFMath::Point<2>(1, 1)); poly.addCorner(3, WFMath::Point<2>(1, -1)); } mPolygon->loadFromShape(poly); if (!mPickListener) { mPickListener = new Authoring::PolygonPointPickListener(*mPolygon); mPickListener->EventPickedPoint.connect(sigc::mem_fun(*this, &PolygonAdapter::pickListener_PickedPoint)); EmberOgre::getSingleton().getWorld()->getMainCamera().pushWorldPickListener(mPickListener); } } }
WFMath::Polygon<2> Polygon::getShape() const { WFMath::Polygon<2> poly; unsigned int i = 0; for (auto& point : mPoints) { poly.addCorner(i++, point->getLocalPosition()); } return poly; }
WFMath::Polygon<2> AreaAdapter::getDefaultPolygon() const { WFMath::Polygon<2> poly; poly.addCorner(0, WFMath::Point<2>(-1, -1)); poly.addCorner(1, WFMath::Point<2>(-1, 1)); poly.addCorner(2, WFMath::Point<2>(1, 1)); poly.addCorner(3, WFMath::Point<2>(1, -1)); return poly; }
void AreaShader::shadeArea(Surface& s, const Area* ar) const { WFMath::Polygon<2> clipped = ar->clipToSegment(s.m_segment); assert(clipped.isValid()); if (clipped.numCorners() == 0) return; Point2 segOrigin = s.m_segment.getRect().lowCorner(); clipped.shift(Point2(0,0) - segOrigin); scanConvert(clipped, s); }
static void scanConvert(const WFMath::Polygon<2>& inPoly, Surface& sf) { if (!inPoly.isValid()) return; std::list<Edge> pending; std::vector<Edge> active; Point2 lastPt = inPoly.getCorner(inPoly.numCorners() - 1); for (std::size_t p=0; p < inPoly.numCorners(); ++p) { Point2 curPt = inPoly.getCorner(p); // skip horizontal edges if (curPt.y() != lastPt.y()) pending.emplace_back(lastPt, curPt); lastPt = curPt; } if (pending.empty()) return; // sort edges by starting (lowest) z value pending.sort(); active.push_back(pending.front()); pending.pop_front(); // advance to the row of the first z value, and ensure z sits in the // middle of sample rows - we do this by offseting by 1/2 a row height // if you don't do this, you'll find alternating rows are over/under // sampled, producing a charming striped effect. WFMath::CoordType z = std::floor(active.front().start().y()) + ROW_HEIGHT * 0.5f; for (; !pending.empty() || !active.empty(); z += ROW_HEIGHT) { while (!pending.empty() && (pending.front().start().y() <= z)) { active.push_back(pending.front()); pending.pop_front(); } // sort by x value - note active will be close to sorted anyway std::sort(active.begin(), active.end(), EdgeAtZ(z)); // delete finished edges for (unsigned int i=0; i< active.size(); ) { if (active[i].end().y() <= z) active.erase(active.begin() + i); else ++i; } // draw pairs of active edges for (unsigned int i=1; i < active.size(); i += 2) span(sf, z, active[i - 1].xValueAtZ(z), active[i].xValueAtZ(z)); } // of active edges loop }
bool TerrainArea::parseArea() { if (!mEntity.hasAttr("area")) { S_LOG_FAILURE("TerrainArea created for entity with no area attribute"); return false; } const Atlas::Message::Element areaElem(mEntity.valueOfAttr("area")); if (!areaElem.isMap()) { S_LOG_FAILURE("TerrainArea element ('area') must be of map type."); return false; } const Atlas::Message::MapType& areaData(areaElem.asMap()); int layer = 0; WFMath::Polygon<2> poly; TerrainAreaParser parser; if (parser.parseArea(areaData, poly, layer)) { if (!mArea) { mArea = new Mercator::Area(layer, false); } else { //A bit of an ugly hack here since the Mercator system doesn't support changing the layer. We need to swap the old area for a new one if the layer has changed. if (mArea->getLayer() != layer) { mOldArea = mArea; mArea = new Mercator::Area(layer, false); } } // transform polygon into terrain coords WFMath::Vector<3> xVec = WFMath::Vector<3>(1.0, 0.0, 0.0).rotate(mEntity.getOrientation()); double theta = atan2(xVec.y(), xVec.x()); // rotation about Z WFMath::RotMatrix<2> rm; poly.rotatePoint(rm.rotation(theta), WFMath::Point<2>(0, 0)); poly.shift(WFMath::Vector<2>(mEntity.getPosition().x(), mEntity.getPosition().y())); mArea->setShape(poly); return true; } else { return false; } }
void Polygon::loadFromShape(const WFMath::Polygon<2>& shape) { clear(); for (size_t i = 0; i < shape.numCorners(); ++i) { const WFMath::Point<2>& position = shape[i]; PolygonPoint* point = new PolygonPoint(*getBaseNode(), getPositionProvider(), 0.25, position); point->makeInteractive(mBulletWorld); mPoints.push_back(point); } mRenderer.update(); }
bool TerrainArea::placeArea(WFMath::Polygon<2>& poly) { //If the position if invalid we can't do anything with the area yet. if (!mEntity.getPosition().isValid()) { return false; } // transform polygon into terrain coords if (mEntity.getOrientation().isValid()) { WFMath::Vector<3> xVec = WFMath::Vector<3>(1.0, 0.0, 0.0).rotate(mEntity.getOrientation()); double theta = atan2(xVec.y(), xVec.x()); // rotation about Z WFMath::RotMatrix<2> rm; poly.rotatePoint(rm.rotation(theta), WFMath::Point<2>(0, 0)); } poly.shift(WFMath::Vector<2>(mEntity.getPosition().x(), mEntity.getPosition().y())); return true; }
void testAddToSegment() { Mercator::Area* a1 = new Mercator::Area(1, false); WFMath::Polygon<2> p; p.addCorner(p.numCorners(), Point2(1, 1)); p.addCorner(p.numCorners(), Point2(6, 1)); p.addCorner(p.numCorners(), Point2(6, 6)); p.addCorner(p.numCorners(), Point2(1, 6)); a1->setShape(p); Mercator::Segment * seg1 = new Mercator::Segment(0,0,seg_size); int success = a1->addToSegment(*seg1); assert(success == 0); Mercator::Segment * seg2 = new Mercator::Segment(1 * seg_size,0,seg_size); success = a1->addToSegment(*seg2); assert(success != 0); }
int main() { Mercator::Terrain t; // Add a null test shader to the terrain Mercator::Shader * shader = new TestShader; t.addShader(shader, 0); // Create a test area with a shape which intersects // the Segment at 0,0 Mercator::Area* a1 = new Mercator::Area(0, false); WFMath::Polygon<2> p; p.addCorner(p.numCorners(), WFMath::Point<2>(3, 4)); p.addCorner(p.numCorners(), WFMath::Point<2>(10, 10)); p.addCorner(p.numCorners(), WFMath::Point<2>(14, 6)); p.addCorner(p.numCorners(), WFMath::Point<2>(18, 4)); p.addCorner(p.numCorners(), WFMath::Point<2>(17, 19)); p.addCorner(p.numCorners(), WFMath::Point<2>(6, 20)); p.addCorner(p.numCorners(), WFMath::Point<2>(-1, 18)); p.addCorner(p.numCorners(), WFMath::Point<2>(-8, 11)); a1->setShape(p); // Add enough base points to force the creation of the Segment at 0,0 t.setBasePoint(0, 0, -1); t.setBasePoint(0, 1, 8); t.setBasePoint(1, 0, 2); t.setBasePoint(1, 1, 11); // Get the Segment at 0,0 Mercator::Segment * seg = t.getSegmentAtIndex(0,0); assert(seg != 0); // Get the surfaces, and add one corresponding to the shader we added. // We need to do this as the functions that would normally make it happen // have been stubbed out. Mercator::Segment::Surfacestore & sss = seg->getSurfaces(); Mercator::Surface * sfce = new Mercator::Surface(*seg, *shader); // Force allocation of the surface buffer so we can check later that it // gets destroyed when the area is added to the terrain. sfce->allocate(); assert(sfce->isValid()); // Add the surface to the store for this segment sss[0] = sfce; // Add the area which should cause relevant surface date to be invalidated t.addArea(a1); // We assert this to ensure that the buffer has been de-allocated // by a call to Surface::invalidate caused by adding the Area. assert(!sfce->isValid()); // force the surface to re-allocate sfce->allocate(); assert(sfce->isValid()); // Modify the areas shape p.addCorner(p.numCorners(), WFMath::Point<2>(-9, 12)); a1->setShape(p); // and cause an area update t.updateArea(a1); // Check the surface has been invalidated again assert(!sfce->isValid()); // force the surface to re-allocate sfce->allocate(); assert(sfce->isValid()); t.removeArea(a1); // Check the surface has been invalidated again assert(!sfce->isValid()); }
void Area::setShape(const WFMath::Polygon<2>& p) { assert(p.isValid()); m_shape = p; m_box = p.boundingBox(); }
WFMath::Polygon<2> sutherlandHodgmanKernel(const WFMath::Polygon<2>& inpoly, Clip clipper) { WFMath::Polygon<2> outpoly; if (!inpoly.isValid()) return inpoly; std::size_t points = inpoly.numCorners(); if (points < 3) return outpoly; // i.e an invalid result Point2 lastPt = inpoly.getCorner(points - 1); bool lastInside = clipper.inside(lastPt); for (std::size_t p = 0; p < points; ++p) { Point2 curPt = inpoly.getCorner(p); bool inside = clipper.inside(curPt); if (lastInside) { if (inside) { // emit curPt outpoly.addCorner(outpoly.numCorners(), curPt); } else { // emit intersection of edge with clip line outpoly.addCorner(outpoly.numCorners(), clipper.clip(lastPt, curPt)); } } else { if (inside) { // emit both outpoly.addCorner(outpoly.numCorners(), clipper.clip(lastPt, curPt)); outpoly.addCorner(outpoly.numCorners(), curPt); } else { // don't emit anything } } // last was outside lastPt = curPt; lastInside = inside; } return outpoly; }
void testAreaShader() { Mercator::Area* a1 = new Mercator::Area(1, false); WFMath::Polygon<2> p; p.addCorner(p.numCorners(), Point2(3, 4)); p.addCorner(p.numCorners(), Point2(10, 10)); p.addCorner(p.numCorners(), Point2(14, 6)); p.addCorner(p.numCorners(), Point2(18, 4)); p.addCorner(p.numCorners(), Point2(17, 19)); p.addCorner(p.numCorners(), Point2(6, 20)); p.addCorner(p.numCorners(), Point2(-1, 18)); p.addCorner(p.numCorners(), Point2(-8, 11)); a1->setShape(p); Mercator::Terrain terrain(Mercator::Terrain::SHADED, 16); Mercator::AreaShader* ashade = new Mercator::AreaShader(1); terrain.addShader(ashade, 0); terrain.setBasePoint(0, 0, -1); terrain.setBasePoint(0, 1, 8); terrain.setBasePoint(1, 0, 2); terrain.setBasePoint(1, 1, 11); terrain.addArea(a1); Mercator::Segment* seg = terrain.getSegment(0,0); assert(a1->checkIntersects(*seg)); seg->populateSurfaces(); }
void testAreaShader() { Mercator::Area* a1 = new Mercator::Area(1, false); WFMath::Polygon<2> p; p.addCorner(p.numCorners(), Point2(3, 4)); p.addCorner(p.numCorners(), Point2(10, 10)); p.addCorner(p.numCorners(), Point2(14, 6)); p.addCorner(p.numCorners(), Point2(18, 4)); p.addCorner(p.numCorners(), Point2(17, 19)); p.addCorner(p.numCorners(), Point2(6, 20)); p.addCorner(p.numCorners(), Point2(-1, 18)); p.addCorner(p.numCorners(), Point2(-8, 11)); a1->setShape(p); Mercator::Area* a2 = new Mercator::Area(1, false); WFMath::Polygon<2> p2; p2.addCorner(p2.numCorners(), Point2(25, 18)); p2.addCorner(p2.numCorners(), Point2(72, 22)); p2.addCorner(p2.numCorners(), Point2(60, 30)); p2.addCorner(p2.numCorners(), Point2(27, 28)); p2.addCorner(p2.numCorners(), Point2(25, 45)); p2.addCorner(p2.numCorners(), Point2(3, 41)); p2.addCorner(p2.numCorners(), Point2(-2, 20)); a2->setShape(p2); Mercator::Terrain terrain(Mercator::Terrain::SHADED, 16); Mercator::Shader * base_shader = new Mercator::FillShader(Mercator::Shader::Parameters()); terrain.addShader(base_shader, 0); Mercator::AreaShader* ashade = new Mercator::AreaShader(1); terrain.addShader(ashade, 1); terrain.setBasePoint(0, 0, -1); terrain.setBasePoint(0, 1, 8); terrain.setBasePoint(1, 0, 2); terrain.setBasePoint(1, 1, 11); terrain.setBasePoint(2, 0, 2); terrain.setBasePoint(2, 1, 11); terrain.addArea(a1); // terrain.addArea(a2); Mercator::Segment* seg = terrain.getSegment(0,0); assert(a1->checkIntersects(*seg)); seg->populateSurfaces(); writePGMForSurface("test1.pgm", seg->getSize(), seg->getSurfaces()[1]); seg = terrain.getSegment(1,0); seg->populateSurfaces(); writePGMForSurface("test2.pgm", seg->getSize(), seg->getSurfaces()[1]); }
int main(int argc, char* argv[]) { Mercator::Area* a1 = new Mercator::Area(1, false); WFMath::Polygon<2> p; p.addCorner(p.numCorners(), Point2(3, 4)); p.addCorner(p.numCorners(), Point2(10, 10)); p.addCorner(p.numCorners(), Point2(-1, 18)); p.addCorner(p.numCorners(), Point2(-8, 11)); a1->setShape(p); Mercator::Terrain terrain(Mercator::Terrain::SHADED, seg_size); Mercator::AreaShader* ashade = new Mercator::AreaShader(1); terrain.addShader(ashade, 0); terrain.setBasePoint(-2, -1, 5); terrain.setBasePoint(-2, 0, 2); terrain.setBasePoint(-2, 1, 19); terrain.setBasePoint(-1, -1, 4); terrain.setBasePoint(-1, 0, 6); terrain.setBasePoint(-1, 1, 10); terrain.setBasePoint(0, -1, 2); terrain.setBasePoint(0, 0, -1); terrain.setBasePoint(0, 1, 8); terrain.setBasePoint(0, 2, 11); terrain.setBasePoint(1, -1, 7); terrain.setBasePoint(1, 0, 2); terrain.setBasePoint(1, 1, 11); terrain.setBasePoint(1, 2, 9); terrain.setBasePoint(2, -1, 3); terrain.setBasePoint(2, 0, 8); terrain.setBasePoint(2, 1, 2); terrain.setBasePoint(3, -1, 6); terrain.setBasePoint(3, 0, 7); terrain.setBasePoint(3, 1, 9); terrain.addArea(a1); Mercator::Segment* seg = terrain.getSegment(0,0); assert(seg->getAreas().size() == 1); assert(seg->getAreas().count(1) == 1); assert(a1->checkIntersects(*seg)); seg = terrain.getSegment(1,0); assert(seg->getAreas().size() == 0); assert(seg->getAreas().count(1) == 0); assert(a1->checkIntersects(*seg) == false); WFMath::Polygon<2> clipped = a1->clipToSegment(*seg); assert(clipped.isValid()); seg = terrain.getSegment(-1,0); assert(seg->getAreas().size() == 1); assert(seg->getAreas().count(1) == 1); assert(a1->checkIntersects(*seg)); clipped = a1->clipToSegment(*seg); assert(clipped.isValid()); seg = terrain.getSegment(0,1); assert(seg->getAreas().size() == 1); assert(seg->getAreas().count(1) == 1); assert(a1->checkIntersects(*seg)); clipped = a1->clipToSegment(*seg); assert(clipped.isValid()); seg = terrain.getSegment(2,0); assert(seg->getAreas().size() == 0); assert(seg->getAreas().count(1) == 0); assert(a1->checkIntersects(*seg) == false); p.clear(); p.addCorner(p.numCorners(), Point2(3 + seg_size, 4)); p.addCorner(p.numCorners(), Point2(10 + seg_size, 10)); p.addCorner(p.numCorners(), Point2(-1 + seg_size, 18)); p.addCorner(p.numCorners(), Point2(-8 + seg_size, 11)); a1->setShape(p); terrain.updateArea(a1); seg = terrain.getSegment(0,0); assert(seg->getAreas().size() == 1); assert(seg->getAreas().count(1) == 1); assert(a1->checkIntersects(*seg)); seg = terrain.getSegment(1,0); assert(seg->getAreas().size() == 1); assert(seg->getAreas().count(1) == 1); assert(a1->checkIntersects(*seg)); clipped = a1->clipToSegment(*seg); assert(clipped.isValid()); seg = terrain.getSegment(-1,0); assert(seg->getAreas().size() == 0); assert(seg->getAreas().count(1) == 0); assert(a1->checkIntersects(*seg) == false); seg = terrain.getSegment(0,1); assert(seg->getAreas().size() == 1); assert(seg->getAreas().count(1) == 1); assert(a1->checkIntersects(*seg)); clipped = a1->clipToSegment(*seg); assert(clipped.isValid()); seg = terrain.getSegment(2,0); assert(seg->getAreas().size() == 0); assert(seg->getAreas().count(1) == 0); assert(a1->checkIntersects(*seg) == false); clipped = a1->clipToSegment(*seg); assert(clipped.isValid()); terrain.removeArea(a1); seg = terrain.getSegment(0,0); assert(seg->getAreas().size() == 0); assert(seg->getAreas().count(1) == 0); seg = terrain.getSegment(1,0); assert(seg->getAreas().size() == 0); assert(seg->getAreas().count(1) == 0); seg = terrain.getSegment(-1,0); assert(seg->getAreas().size() == 0); assert(seg->getAreas().count(1) == 0); seg = terrain.getSegment(0,1); assert(seg->getAreas().size() == 0); assert(seg->getAreas().count(1) == 0); testAreaShader(); testAddToSegment(); return EXIT_SUCCESS; }
int main() { // Test constructor { Mercator::Forest mf; } // Test constructor { Mercator::Forest mf(23); } // Test getArea() { Mercator::Forest mf; Mercator::Area * a = mf.getArea(); assert(a == 0); } // Test species() { Mercator::Forest mf; Mercator::Forest::PlantSpecies & mps = mf.species(); assert(mps.empty()); } { Mercator::Forest forest(4249162ul); Mercator::Forest::PlantSpecies & species = forest.species(); const Mercator::Forest::PlantStore & plants = forest.getPlants(); // Forest is not yet populated assert(plants.empty()); assert(species.empty()); forest.populate(); // Forest has zero area, so even when populated it is empty assert(plants.empty()); assert(species.empty()); Mercator::Area* ar = new Mercator::Area(1, false); WFMath::Polygon<2> p; p.addCorner(p.numCorners(), Point2(5, 8)); p.addCorner(p.numCorners(), Point2(40, -1)); p.addCorner(p.numCorners(), Point2(45, 16)); p.addCorner(p.numCorners(), Point2(30, 28)); p.addCorner(p.numCorners(), Point2(-2, 26)); p.addCorner(p.numCorners(), Point2(1, 5)); ar->setShape(p); forest.setArea(ar); forest.populate(); // Forest has no species, so even when populated it is empty assert(plants.empty()); assert(species.empty()); { Mercator::Species pine; pine.m_probability = 0.04; pine.m_deviation = 1.f; species.push_back(pine); } forest.populate(); // Forest should now contain some plants assert(!plants.empty()); dumpPlants(plants); int plant_count = countPlants(plants); { Mercator::Species oak; oak.m_probability = 0.02; oak.m_deviation = 1.f; species.push_back(oak); } forest.populate(); // Forest should now contain some plants assert(!plants.empty()); assert(countPlants(plants) > plant_count); dumpPlants(plants); std::cout << countPlants(plants) << "," << plant_count << std::endl << std::flush; } }