How to add osgEarth Features at runtime? - c++

I'm playing around with osgEarth and while it's crazy easy to add features in the .earth file, I'm struggling to do it at runtime via the API. I want to let the user draw polygons on the map/globe so I need to be able to dynamically define geometry and styles based on user input.
Right now I'm just going for a static implementation to figure out what I need to do, but for the life of me I can't get anything to show up. Here is my sample code. I've already loaded a .earth file that defines the MapNode which is what I'm using here.
// Style
osgEarth::Symbology::Style shapeStyle;
shapeStyle.getOrCreate<osgEarth::Symbology::PolygonSymbol>()->fill()->color() = osgEarth::Symbology::Color::Green;
// Geometry
osgEarth::Symbology::Polygon* polygon = new osgEarth::Symbology::Polygon();
polygon->push_back(0, 0);
polygon->push_back(0, 10);
polygon->push_back(10, 10);
// Feature
osgEarth::Features::Feature* feature = new osgEarth::Features::Feature(polygon, mapNode->getMapSRS(), shapeStyle);
// Node
osgEarth::Annotation::FeatureNode* featureNode = new osgEarth::Annotation::FeatureNode(mapNode, feature);
featureNode->setStyle(shapeStyle);
featureNode->init();
mapNode->addChild(featureNode);
This should draw a green triangle near the middle of the map, but I don't see anything. Am I wrong in assuming that my polygon points are geo coordinates (lon, lat)? Is it wrong to just create my Style and Geometry on the fly like this? What am I doing wrong?
Update: This seems to work fine on a 3D (geocentric) map, but not on a 2D (projected) map which is what I'm after.

After poking around a bit I stumbled upon the osgearth_features example that comes with the SDK which includes examples of creating features programatically. I followed the pattern from the sample and came up with something that works.
// Style
osgEarth::Symbology::Style shapeStyle;
osgEarth::Symbology::PolygonSymbol* fillStyle = shapeStyle.getOrCreate<osgEarth::Symbology::PolygonSymbol>();
fillStyle->fill()->color() = osgEarth::Symbology::Color::Green;
osgEarth::Symbology::LineSymbol* lineStyle = shapeStyle.getOrCreate<osgEarth::Symbology::LineSymbol>();
lineStyle->stroke()->color() = osgEarth::Symbology::Color::Black;
lineStyle->stroke()->width() = 2.0f;
// Geometry
osgEarth::Symbology::Polygon* polygon = new osgEarth::Symbology::Polygon();
polygon->push_back(0, 0, 10000);
polygon->push_back(0, 10, 10000);
polygon->push_back(10, 10, 10000);
// Feature Options (references the geometry)
osgEarth::Drivers::OGRFeatureOptions featureOptions;
featureOptions.geometry() = polygon;
// Model Options (references the feature options and style)
osgEarth::Drivers::FeatureGeomModelOptions geomOptions;
geomOptions.featureOptions() = featureOptions;
geomOptions.styles() = new osgEarth::StyleSheet();
geomOptions.styles()->addStyle( shapeStyle );
geomOptions.enableLighting() = false;
// Model Layer Options (created using the model options)
osgEarth::ModelLayerOptions layerOptions("test polygon", geomOptions);
mapNode->getMap()->addModelLayer(new osgEarth::ModelLayer(layerOptions));
Defining the style and geometry is more or less the same as what I was doing before (I added a line symbol this time), but in this case I'm adding a ModelLayer to the Map. That ModelLayer uses some model options that reference my style and geometry through the feature options.
I don't know if this is the best way to do it or how scalable it is (can I do this over and over thousands of times?), bit it's at least got me going,

Related

How to Move All Sprites At Once: Cocos2dx v3 C++

I'm attempting to make a Space Invaders clone. In doing so I'm having a difficult time grouping the invaders together so that they move at the same time.This is due to both CCLayer and CCNode being deprecated in v3.1 in cocos2dx. I saved my sprites to a vector that I can iterate over but when I attempt to move them only move one at a time. I need to group them together so I can move them all at once.
void Gameplay::moveInvaders(){
auto moveLeft = MoveBy::create(2, Vec2(-1, 0));
auto moveRight = MoveBy::create(2, Vec2(1, 0));
auto moveDown = MoveBy::create(2, Vec2(0, 1));
auto stay = MoveBy::create(20, Vec2(0,0));
// create a sequence with the actions and callbacks
auto seq = Sequence::create(moveLeft, stay, moveRight, stay, moveDown, stay, nullptr);
for (int i = 0; i < invaders.size(); i++) {
invaders.at(i)->runAction(seq);
}
Update: I ended up figuring out the issue. Instead of trying to use the sequence I ended up scripting the movements with some control logic and the system timer.
Add this to your init() function:
this->schedule(schedule_selector(Gameplay::moveInvaders), 1.0);
Of the form:
this->schedule(schedule_selector(<Class_Name>::<function_To_call>), <number_of_frames_to_run>);
Then decide what you want to do in your function that will be called that often. I used a couple of boolean and int values to keep a counter. That way I could control the direction the invaders would move.
Hopefully this helps somebody else! I couldn't find what I needed to know because most of the tutorials for cocos2dx were in Objective-C or Javascript.
How about adding all invaders into one sprite, say "InvaderGroup"? All transformations (and need to refer once, but most probably all Actions too) to a sprite are guaranteed to be calculated on children too, so no worries, I suppose.
So many invaders individually watching out for events sounds like overhead, especially the result movement is not supposed to be individually decided. You can use your own Sprite subclass if you prefer, but just to move them around it's not necessary.
P.S.
Your invaders will still be able to roam individually if you want them to, just the co-ordinates will be with reference to the parent Sprite.

cocos2d-x 3 batch drawing explained

I have read this page to understand batch drawing details, but I still have questions. I know that in order to reduce draw call number we need to use batch drawing. I use it like this:
auto spritebatch = SpriteBatchNode::create("ingame.png");
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("ingame.plist");
And now I need to create a Sprite I have to do this:
auto backgroundSprite = Sprite::createWithSpriteFrameName("back_gradient.png");
spritebatch->addChild(backgroundSprite);
But I don't understand the following things:
What if my game has several spritesheets. For example I have HUD spritesheet and ingame spritesheet. Now if I want to show ingame screen with HUD then I need to create 2 SpriteBatchNode? and add them into ingame layer?
What if the same spritesheet should be used in different Scenes. Should I do the following again?
auto spritebatch = SpriteBatchNode::create("ingame.png");
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("ingame.plist");
What if I use sprites with Button, TextEdit, Label and other UI elements.
First of all can I initialize Button state images from spritesheet?
As I know I cannot add UI element as a child to SpriteBatchNode. In this case how to combile UI elements and sprite in the same view/scene?
Sorry for lots of questions. But the fact is that I could not find any resource that contains the explanations to this questions. While they are all related. If you don't know answers to these questions, you don't know how to use SpriteBatchNode.
Don't use CCSpriteBatchNode in cocos2d-x v3. Batching is automatic and best left to the renderer to optimize draw calls through batch drawing. It says so right in the article you've linked:
The Render graph was decoupled from the Scene graph.That means that auto-batching is supported, finally :-) And the new renderer is so fast, that we no longer encourage the use of SpriteBatchNode.
I don't agree, depending not how fast new render is we want to get most of it as we can.
Narek, you are correct.
During rendering the geometry will be sorted to reduce the quantity of GL calls. But don't expect it will sort children of different parents in one line. Example: you have
Node A with children ab and ac
Node B with children bd and be.
if b and d uses textures of same atlas it is not guaranted you will get any perfomance boost of using atlases at all.
But I can confirm, currently it is really fast, and at my case the GL calls are not the bottleneck at all :)

How to make complex charts using Raphael

I supposed to make this type of charts, is it posssible to make through Raphael or any good Plug-in for Raphael. ( i prefer raphael, because already i using this), I am attaching the image that what i need to produce?
thanks for advance..
I'd genuinely advise just drawing the thing manually using the Raphael library. When we had a requirement for an uncommon graph type, I attempted to get existing graphing libraries to draw it, but it was awful. I mocked up a prototype in an evening to demonstrate how much cleaner it is to draw it manually with raphael, and we ended up using it. Best thing you can try to do is prototype what you are looking for: create a dummy set of Json for the graph and try to plot from this data. You should find that it's relatively straight forward to divide the content area up:
numberOfMonths = 6;
barsPerMonth = 2;
marginLeft = 40;
marginRight = 40;
graphArea = canvasWidth - marginLeft - marginRight;
monthWidth = graphArea / numberOfMonths;
barWidth = monthWidth / barsPerMonth;
Just define all of the margins and widths that you want. Define the range of your axes and define a tick scale/count. That should get you started.

Qt GUI Development - Displaying a 2D grid using QGraphicsView

I'm new to Qt development so I've being trying to research a solution to a user interface I need to design. My project is to simulate players in an online game moving around a global map. To represent the map I need to display a 2D grid, with each space in the grid representing a region of a map. I then need to display the location of each player in the game. The back-end is all fully working, with the map implemented as a 2D array. I'm just stuck on how to display the grid.
The research I have done has led me to believe a QGraphicsView is the best way to do this, but I can't seem to find a tutorial relevant to what I need. If anyone has any tips on how to implement this it would be much appreciated.
Thanks, Dan
A 2D Grid is nothing more than a set of horizontal and vertical lines. Suppose you have a 500x500 map and you want to draw a grid where the distance between the lines in both directions is 50. The sample code that follows shows you how you can achieve it.
// create a scene and add it your view
QGraphicsScene* scene = new QGraphicsScene;
ui->view->setScene(scene);
// Add the vertical lines first, paint them red
for (int x=0; x<=500; x+=50)
scene->addLine(x,0,x,500, QPen(Qt::red));
// Now add the horizontal lines, paint them green
for (int y=0; y<=500; y+=50)
scene->addLine(0,y,500,y, QPen(Qt::green));
// Fit the view in the scene's bounding rect
ui->view->fitInView(scene->itemsVBoundingRect());
You should check the QGraphicsView and the QGraphicsScene documentation as well as the corresponding examples. Also you can watch the graphics view training videos or some graphics view related videos from the Qt developer days.
Well if you have a constant grid size or even a limited number of grid sizes what i like to do is to draw a grid block in gimp or any other program and then set that as the background brush (draw only bottom and right side of the block) qt will repeat the image and will give you a full grid. I think this is good for performance too.
This is the grid image i used in one of my programs it's 10x10 pixels.
Then call QGraphicsScene setBackgroundBrush as the follwing:
scene->setBackgroundBrush(QBrush(QPixmap(":/grid/grid10.png")));
The more native way is this:
scene = self.getScene() # Your scene.
brush = QBrush()
brush.setColor(QColor('#999'))
brush.setStyle(Qt.CrossPattern) # Grid pattern.
scene.setBackgroundBrush(brush)
borderColor = Qt.black
fillColor = QColor('#DDD')
rect = QRectF(0.0, 0.0, 1280, 720) # Screen res or whatever.
scene.addRect(rect,borderColor,fillColor) # Rectangle for color.
scene.addRect(rect,borderColor,brush) # Rectangle for grid.
Sorry by PyQt...
Suppose a scene is set to the graphicsview then simply below one line will show the grid.
ui->graphicsView->scene()->setBackgroundBrush(Qt::CrossPattern);
There several other values can be passed for ex: Qt::Dense7Pattern
These are members of enum BrushStyle, just click on any used value in Qt creator and it will take you to the enum declaration where you can see all other possible values.
PS:
A scene can be set like this:
ui->graphicsView->setScene(new QGraphicsScene());

Manually drawing gradients for buttons, toolbars, tabs etc?

I would like to update some toolbar-like code we have to have a Vista/Win7 gradient roundedness to them.
Currently, the buttons have the Windows 2000 look & feel: blocky, single-tone.
I've played around with the XP themes, and using DrawThemeBackground, DrawThemeEdge, etc.; but I'm very dissatisfied with the theme drawing mechanics (the buttons are large, and the theme draws them as 2-tone, top half and bottom half, which looks okay when the buttons are small - it gives them a halfway decent appearance of being a gradient or having a rounded quality to them. But as large as these buttons are, they look stupid.
Experimenting by simply observing how many of the controls are drawn in various apps and controls, I can see that most of them seem to use gradients - where the top of the control appears a light color and fades to the bottom to a darker color - OR - where it is a lighter color than the background at the top, increases towards near-white at the middle, then fades back to a darker color towards the bottom.
I'm not really sure where to go from here. DrawThemeXXX seem to be inadequate. I don't really want to replace the entire control with a new one that has improved drawing but would require that I swap out some of the code for how the current custom control works, and risk various problems with some other library. I'd rather just have a way to draw arbitrary objects in the style of the current version of Windows that I'm running on. I would have thought that the theme drawing functions would have covered this. But they're fairly brain damaged, as I described.
Can someone point me towards 'How are modern C++ applications supposed to draw custom GUI elements so that they might reasonably expect a graceful appearance under XP, Vista, and Windows 7?'
We use MFC, Gdiplus, and raw Win32 APIs in our code, currently.
Here's to hoping someone knows a great deal about drawing modern GUIs under Windows from C++!
Just so that this isn't a wall of text, here's the current version of the paint handler, which draws the button with an etched border when 'hot-tracking' and both an etched border and the icon + text "depressed" (shifted by 1,1) when in a pressed state:
void CPlacesButton::PaintButton(CDC & dc, CRect & rcClient)
{
const int kLabelHeight = 8;
COLORREF clrHiLt = GetSysColor(COLOR_BTNHIGHLIGHT);
COLORREF clrShdo = GetSysColor(COLOR_BTNSHADOW);
COLORREF clrText = GetSysColor(COLOR_BTNTEXT);
COLORREF clrFace = GetSysColor(COLOR_BTNFACE);
// draw the button's background & border
if (m_bPressed || m_bDrawPressed || m_bMouseOnButton)
{
COLORREF clrDarkened = Darken(clrFace, -0.01f);
dc.FillRect(rcClient, &CBrush(clrDarkened));
//dc.Draw3dRect(rcClient, clrShdo, clrHiLt);
//dc.RoundRect(&rcClient, CPoint(10,10));
dc.DrawEdge(&rcClient, EDGE_ETCHED, BF_RECT|BF_FLAT);
//dc.DrawFrameControl(&rcClient, DFC_BUTTON, DFCS_BUTTONPUSH|DFCS_PUSHED);
}
// else if (m_bMouseOnButton) // hot draw
// //dc.Draw3dRect(rcClient, clrShdo, clrHiLt);
// dc.DrawEdge(&rcClient, EDGE_ETCHED, BF_RECT);
// //dc.RoundRect(&rcClient, CPoint(10,10));
else
dc.FillRect(rcClient, &CBrush(clrFace));
// use transparent mode for everything that follows
dc.SetBkMode(TRANSPARENT);
// center icon
CPoint ptIcon((rcClient.Width() - m_nIconSize) / 2, ((rcClient.Height() - m_nIconSize) / 2) - kLabelHeight);
if (m_bPressed || m_bDrawPressed)
ptIcon.Offset(1, 1);
// determine the state to draw ourselves in
const UINT nState = DST_ICON | (IsEnabled() ? DSS_NORMAL : DSS_DISABLED);
// draw our icon
dc.DrawState(ptIcon, CSize(m_nIconSize, m_nIconSize), m_hIcon, nState, (HBRUSH)NULL);
// create & select the font to use for the button's label
CFont guiFont;
VERIFY(guiFont.CreateStockObject(DEFAULT_GUI_FONT));
AutoSelectGDIObject select_font(dc, guiFont);
// determine clipping rect for label
CRect rcText(0, ptIcon.y+m_nIconSize+kLabelHeight, rcClient.Width(), ptIcon.y+m_nIconSize+kLabelHeight);
rcText.InflateRect(0,20);
if (m_bPressed || m_bDrawPressed)
rcText.OffsetRect(1, 1);
dc.SetTextColor(clrText);
if (IsEnabled())
dc.DrawText(m_strCaption, rcText, DT_VCENTER|DT_SINGLELINE|DT_CENTER);
else
dc.GrayString(NULL, NULL, (LPARAM)(LPCTSTR)m_strCaption, 0, rcText.TopLeft().x, rcText.TopLeft().y, rcText.Width(), rcText.Height());
}
I left some of the commented out variations in the code to indicate some hints as to what other possibilities I've tried. However, they're just a hint, as the complete alternate examples are not present.
Actually duplicating the look of the various flavors of Windows is ridiculously difficult, especially if your app can run on more than one version of windows.
I think that they intended to give you the api's to do this back in the Win2k/Win95 days, but then WinXP came along with shading and overlays, and the old API was completely inadequate.
So they came up with the theme stuff, which isn't really even an API so much as an API and a set of graphical primitives all jammed together. But they didn't follow through and allow the set of graphical primitives to be extended or replaced, so themes only works when your controls are a close match to the standard set.
So, for Win9x/Win2k. You use
DrawFrameControl
DrawEdge
For WinXP
DrawTheme
For WinVista/7
DrawTheme
DwmXXX functions
GradientFill ??
Now I suspect that Windows isn't actually using GradientDraw. I suspect it's actually using some DX10 shaders that are built in to the window manager code, but I don't know how to get at that, s I've been using GradientDraw instead. This code will give you a linear fade from the top of the control to the bottom.
INLINE void SetTrivertex(TRIVERTEX & vtx, int x, int y, COLORREF cr)
{
vtx.x = x;
vtx.y = y;
vtx.Red = (SHORT)(GetRValue(cr) * 256L);
vtx.Green = (SHORT)(GetGValue(cr) * 256L);
vtx.Blue = (SHORT)(GetBValue(cr) * 256L);
vtx.Alpha = (SHORT)(255 * 256L);
}
...
// fill the interior from the top down with a gradient that starts at crTop
// and ends with the crBottom
TRIVERTEX vtx[2];
SetTrivertex (vtx[0], prc->left+1, prc->top+1, crTop);
SetTrivertex (vtx[1], prc->right-1, prc->bottom-1, crBottom);
GRADIENT_RECT gRect = { 0, 1 };
GradientFill(hdc, vtx, 2, &gRect, 1, GRADIENT_FILL_RECT_V);
You never mentioned the MFC Feature Pack. Have you taken a look at it yet? Download for VS2008, included with VS2008 SP1. The CDrawingManager has lots of special effects. It has great support for application themes.
MFC alone isn't exactly skinning friendly. Apart from using another GUI (Qt is great for custom skinning) you can look at solutions like SkinCrafter.