gluPartialDisk in osg/osgEarth

236 views Asked by At

I've been trying to create an openGL gluDisk like object in osgEarth. So far I've attempted to do the following (Edited, this is the correct answer):

void ViewDriver::drawCircZone(double lat, double lon, double innerRadius, double outerRadius, QColor color, double beginAngle, double endAngle){
    GeometryFactory g;
    osg::ref_ptr<osgEarth::Geometry> outerCircleGeom = g.createArc(osg::Vec3d(lat, lon, 0), convertFromMetersToMercDeg(outerRadius), beginAngle, endAngle);
    osg::ref_ptr<osgEarth::Geometry> innerCircleGeom = g.createArc(osg::Vec3d(lat, lon, 0), convertFromMetersToMercDeg(innerRadius), beginAngle, endAngle);

    osg::Vec3dArray* outerCircArray = outerCircleGeom->createVec3dArray();
    osg::Vec3dArray* innerCircArray = innerCircleGeom->createVec3dArray();

    Vec3dVector* diskVec = new Vec3dVector;

    for(int i = 0; i < outerCircArray->size() - 1; i++){
        diskVec->push_back((*outerCircArray)[i]);
    }
    //This is important for closing the shape and not giving it a Pac-Man-like mouth
    diskVec->push_back((*outerCircArray)[0]);

    //This is how you make a "hole", by iterating backwards 
    for(int i = innerCircArray->size() - 1; i >= 0; i--){
        diskVec->push_back((*innerCircArray)[i]);
    }

    osg::ref_ptr<osgEarth::Symbology::Ring> diskRing = new Ring(diskVec);
    diskRing->close();

    osg::ref_ptr<Feature> circFeature = new Feature(diskRing, view->getMapViewer()->geoSRS);

    Style circStyle;
    circStyle.getOrCreate<PolygonSymbol>()->outline() = true;
    circStyle.getOrCreate<PolygonSymbol>()->fill()->color() = Color(color.red()/255.0, color.green()/255.0, color.blue()/255.0, 1.0);
    circStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN;
    circStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_DRAPE;

    osg::ref_ptr<FeatureNode> circNode = new FeatureNode(circFeature, circStyle);
    circNode->setDynamic(true);

    view->getMapNode()->addChild(circNode);
}

What stumped me originally was that I don't have a lot of graphics knowledge. Somewhere I read that when drawing outlines, do it in clockwise direction. When drawing outlines in counter clockwise direction they will "cut-out" or create a "hole" when combined with clockwise-drawn points. I was filling the "hole" outline with the smaller circle's point in a clockwise direction originally when testing that method which was why it didn't work.

1

There are 1 answers

0
Blanky On BEST ANSWER
void ViewDriver::drawCircZone(double lat, double lon, double innerRadius, double outerRadius, QColor color, double beginAngle, double endAngle){
        GeometryFactory g;
        osg::ref_ptr<osgEarth::Geometry> outerCircleGeom = g.createArc(osg::Vec3d(lat, lon, 0), convertFromMetersToMercDeg(outerRadius), beginAngle, endAngle);
        osg::ref_ptr<osgEarth::Geometry> innerCircleGeom = g.createArc(osg::Vec3d(lat, lon, 0), convertFromMetersToMercDeg(innerRadius), beginAngle, endAngle);

        osg::Vec3dArray* outerCircArray = outerCircleGeom->createVec3dArray();
        osg::Vec3dArray* innerCircArray = innerCircleGeom->createVec3dArray();

        Vec3dVector* diskVec = new Vec3dVector;

        for(int i = 0; i < outerCircArray->size() - 1; i++){
            diskVec->push_back((*outerCircArray)[i]);
        }
        //This is important for closing the shape and not giving it a Pac-Man-like mouth
        diskVec->push_back((*outerCircArray)[0]);

        for(int i = innerCircArray->size() - 1; i >= 0; i--){
            diskVec->push_back((*innerCircArray)[i]);
        }

        osg::ref_ptr<osgEarth::Symbology::Ring> diskRing = new Ring(diskVec);
        diskRing->close();

        osg::ref_ptr<Feature> circFeature = new Feature(diskRing, view->getMapViewer()->geoSRS);

        Style circStyle;
        circStyle.getOrCreate<PolygonSymbol>()->outline() = true;
        circStyle.getOrCreate<PolygonSymbol>()->fill()->color() = Color(color.red()/255.0, color.green()/255.0, color.blue()/255.0, 1.0);
        circStyle.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_RELATIVE_TO_TERRAIN;
        circStyle.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_DRAPE;

        osg::ref_ptr<FeatureNode> circNode = new FeatureNode(circFeature, circStyle);
        circNode->setDynamic(true);

        view->getMapNode()->addChild(circNode);
}