So I am trying to create a mini-map/PIP. I have an existing program with scene that runs inside a Qt Widget. I have a class, NetworkViewer, which extends CompositeViewer. In NetworkViewer's constructor I call the following function. Notice the root is the scene which is populated elsewhere.
void NetworkViewer::init() {
root = new osg::Group() ;
viewer = new osgViewer::View( );
viewer->setSceneData( root ) ;
osg::Camera* camera ;
camera = createCamera(0,0,100,100) ;
viewer->setCamera( camera );
viewer->addEventHandler( new NetworkGUIHandler( (GUI*)view ) ) ;
viewer->setCameraManipulator(new osgGA::TrackballManipulator) ;
viewer->getCamera()->setClearColor(
osg::Vec4( LIGHT_CLOUD_BLUE_F,0.0f));
addView( viewer );
osgQt::GraphicsWindowQt* gw =
dynamic_cast( camera->getGraphicsContext() );
QWidget* widget = gw ? gw->getGLWidget() : NULL;
QGridLayout* grid = new QGridLayout( ) ;
grid->addWidget( widget );
grid->setSpacing(1);
grid->setMargin(1);
setLayout( grid );
initHUD( ) ;
}
The create camera function is as follows:
osg::Camera* createCamera( int x, int y, int w, int h ) {
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
osg::ref_ptr traits
= new osg::GraphicsContext::Traits;
traits->windowName = "" ;
traits->windowDecoration = false ;
traits->x = x;
traits->y = y;
traits->width = w;
traits->height = h;
traits->doubleBuffer = true;
traits->alpha = ds->getMinimumNumAlphaBits();
traits->stencil = ds->getMinimumNumStencilBits();
traits->sampleBuffers = ds->getMultiSamples();
traits->samples = ds->getNumMultiSamples();
osg::ref_ptr camera = new osg::Camera;
camera->setGraphicsContext( new osgQt::GraphicsWindowQt(traits.get()) );
camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );
camera->setViewMatrix(osg::Matrix::translate(-10.0f,-10.0f,-30.0f));
camera->setProjectionMatrixAsPerspective(
20.0f,
static_cast(traits->width)/static_cast(traits->height),
1.0f, 10000.0f );
return camera.release();
}
I have been looking at several camera examples and searching for a solution for a while to no avail. What I am really looking for is the background being my main camera which takes up most of the screen and displays the scene graph while my mini-map appears in the bottom right. It has the same scene as the main camera but is overlaid on top of it and has its own set of controls for selection etc since it will have different functionality.
I was thinking that perhaps by adding another camera as a slave I would be able to do this:
camera = createCamera(40,40,50,50) ;
viewer->addSlave(camera) ;
But this doesn't seem to work. If I disable the other camera I do see a clear area that it appears this camera was suppose to be rendering in (its viewport) but that doesn't help. I've played around with rendering order thinking it could be that to no avail.
Any ideas? What it the best way to do such a minimap is? What am I doing wrong? Also anyway to make the rendering of the minimap circular instead of rectangular?
I am not personnally using OpenSceneGraph, so I can't advise you on your code. I think the best is to ask in the official forums. But I have some ideas on the minimap:
First, you have to specify the basic features of your minimap. Do you want it to emphasize some elements of the scene, or just show the scene (ie, RTS-like minimap vs simple top-show of the scene) ?
I assume you do not want to emphasize some elements of the scene. I also assume your main camera is not really 'minimap-friendly'. So, the simplest is to create a camera with the following properties:
direction = (0,-1,0) (Y is the vertical axis)
mode = orthographic
position = controlled by what you want, for example your main camera
Now, for the integration of the image. You can:
set the viewport of the minimap camera to what you want, if your minimap is rectangular.
render the minimap to a texture (RTT) and then blend it through an extra rendering pass.
You can also search other engines forums (like Irrlicht and Ogre) to see how they're doing minimaps.
Related
I’m creating a particle system using Qt and c++. I want to blend colours of the particles that overlap each other – adding the RGB values on top of each other, so colours would get brighter, something like this:
My code looks like this:
In custom QGraphicsScene class:
QPixmap* pixmap2 = new QPixmap("E:\\Qt_workspace\\1\\smoke5.png");
pixmap2->setDevicePixelRatio(0.5);
QPointF origin2 = {250, 100};
QPainter pix2(pixmap2);
pix2.setCompositionMode(QPainter::CompositionMode_Plus);
pix2.drawPixmap(origin2, *pixmap2);
pix2.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, true);
particleSystem2 = new ParticleSystem(this, pixmap2, origin2);
v_particleSystem.push_back(particleSystem2);
And i create particles in a loop:
void Level1::advance()
{
for (int i = 0; i < v_particleSystem.size(); ++i) {
v_particleSystem\[i\]->applyForce(gravity);
QVector2D v = { (float)player->x(), (float)player->y() };
repeller->update(v);
v_particleSystem[i]->applyReppeler(repeller);
v_particleSystem[i]->addParticle();
v_particleSystem[i]->run();
}
update(sceneRect); ///so items dont leave any artifacts though works without it when
using m_view->viewport()->repaint();
m_view->viewport()->repaint();
And Particle class derives from QGraphicsPixmapItem
But im getting this result:
Any idea how to achieve additive blending?
As far as I've found out, cocos doesn't offer a simple filter handling like AS3 for example does.
My situation:
I want to add a realtime shadow to an cocos2d::Sprite.
For example I would like to do something like this (similar to AS3):
auto mySprite = Sprite::createWithSpriteFrameName("myCharacter.png");
DropShadowFilter* dropShadow = new DropShadowFilter();
dropShadow->distance = 0;
dropShadow->angle = 45;
dropShadow->color = 0x333333;
dropShadow->alpha = 1;
dropShadow->blurX = 10;
dropShadow->blurY = 10;
dropShadow->strength = 1;
dropShadow->quality = 15;
mySprite->addFilter(dropShadow);
This should add a shadow to my Sprite to achieve an result like this:
Adobe Drop Shadow Example
Could you help me please?
There isn't any built in support for shadows on Sprites in Cocos2D-X.
The best option, performance-wise, would be to place your shadows in your sprite images already, instead of calculating and drawing them in the code.
Another option is to sub-class Sprite and override the draw method so that you duplicate the sprite and apply your effects and draw it below the original.
One possible way to achieve that is with this snippet from this thread on the Cocos forum. I can't say that I completely follow what this code does with the GL transforms, but you can use this as a starting point to experiment.
void CMySprite::draw()
{
// is_shadow is true if this sprite is to be considered like a shadow sprite, false otherwise.#
if (is_shadow)
{
ccBlendFunc blend;
// Change the default blending factors to this one.
blend.src = GL_SRC_ALPHA;
blend.dst = GL_ONE;
setBlendFunc( blend );
// Change the blending equation to thi in order to subtract from the values already written in the frame buffer
// the ones of the sprite.
glBlendEquationOES(GL_FUNC_REVERSE_SUBTRACT_OES);
}
CCSprite::draw();
if (is_shadow)
{
// The default blending function of cocos2d-x is GL_FUNC_ADD.
glBlendEquationOES(GL_FUNC_ADD_OES);
}
}
I have been working on a Dark GDK project in which I make a sprite face the cursor or mouse's location. I picked up on some code and implemented it into my application but it seems to not be working correction. Here is a preview, http://gyazo.com/bf57df49071e3a684a7e03b8f0cf4527, as you can see, the sprite is not facing the right place where the cursor is and it does not move correctly. I believe this is because Dark GDK doesn't know where the center of my object is. Can anyone help me understand what I am doing wrong? I changed the values of the rotation and rotated the sprite but that didn't help at all.
// Dark GDK - The Game Creators - www.thegamecreators.com
// the wizard has created a very simple project that uses Dark GDK
// it contains the basic code for a GDK application
// whenever using Dark GDK you must ensure you include the header file
#include "DarkGDK.h"
// the main entry point for the application is this function
void DarkGDK ( void )
{
// turn on sync rate and set maximum rate to 60 fps
dbSyncOn ( );
dbSyncRate ( 60 );
dbLoadImage("hero.png", 1);
dbSprite(1,100,100,1);
// our main loop
while ( LoopGDK ( ) )
{
float dx = dbMouseX() - dbSpriteX(1);
float dy = dbMouseY() - dbSpriteY(1);
dbRotateSprite(1,dbAtanFull(dy,dx));
if(dbEscapeKey() == 1)
{
break;
}
dbSync ( );
}
dbDeleteImage(1);
dbDeleteSprite(1);
// return back to windows
return;
}
1) The Sprite' Axis of Rotation Is At The Point Where It Is Drawn From The Upper-Left Hand Corner. That Axis Can Be Changed Using:
dbOffsetSprite( iD , xOff , yOff );
From the picture the preferred offset point would be the center of the ball.
2) The side/edge of the image (top,left,right,bottom) that face the cursor will be the 0 degree side. On any sprite the axis is:............................................
90 ...............................................................................................
.........................................................................|
..................................................................................................................................................................180--o--0.............................................................................................
.........................................................................|..................................................................................................
.......................................................................270.......................................................................................
Using the setup above the 0 will always face the cursor.
3.) To get the corresponding angle to face the cursor, simply add(+) that angle inside the function:
dbRotateSprite( 1 , dbAtanFull(dy,dx) + 90.0 );
So I have program which is a Qt App. I have some basic Qt GUI on the outside but then I have a Qt widget that makes use of OpenSceneGraph to render a 3D scene. To make things more complicated inside that screen I have a HUD that toggles on and off. This HUD consists of some graphic elements and then a Qt Widget rendered to a texture.
I basically have that working however I am having some size issues within the HUD/Qt Widget. When I first toggle the HUD to visible the Qt Widget is there but way too big. I can change the size but regardless, the first time I press a key the Qt Widget is auto re-sized to fit in the textured area I give it (which is what I expect) but this auto re-sized widget doesn't fit the area correctly. Its impossible to read the table that the widget contains.
To help I have two screen shots. The first is before I type a key:
http://cerrnim.com/wp-content/uploads/2012/12/before.png
And the second is after I type a key:
http://cerrnim.com/wp-content/uploads/2012/12/after.png
Additionally here are some code fragments showing how I create the HUD. Its of course a part of a much larger program but hopefully this is enough information.
/* AUX function to create HUD geo. */
osg::Geode* HUDGeometry( int x1, int y1, int x2, int y2,
std::string model, HUDEvents event, NetworkViewer* viewer ) {
osg::Geometry* quad = osg::createTexturedQuadGeometry(osg::Vec3(x1,y1,0),
osg::Vec3(x2-x1,0,0), osg::Vec3(0,y2-y1,0), 1, 1);
osg::Geode* geode = new osg::Geode( ) ;
geode->setName( model ) ;
geode->setUserData( new HUDEvent( event, viewer ) ) ;
osg::Texture2D* HUDTexture = new osg::Texture2D();
HUDTexture->setDataVariance(osg::Object::DYNAMIC);
osg::Image* hudImage = osgDB::readImageFile(model);
HUDTexture->setImage(hudImage);
geode->getOrCreateStateSet()->setTextureAttributeAndModes(
0, HUDTexture, osg::StateAttribute::ON);
geode->addDrawable( quad ) ;
return geode ;
}
/* Creates the HUD but does not display it yet. */
void NetworkViewer::initHUD( ) {
osg::MatrixTransform* mt = new osg::MatrixTransform;
osg::Camera* hudCamera = new osg::Camera;
hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
hudCamera->setViewMatrix(osg::Matrix::identity());
//hudCamera->setProjectionResizePolicy(osg::Camera::FIXED);
hudCamera->setProjectionMatrixAsOrtho2D(0,100,0,100);
hudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
hudCamera->setRenderOrder(osg::Camera::POST_RENDER);
hudCamera->setAllowEventFocus(true);
QWidget* widget = new QWidget;
layout = new QVBoxLayout( ) ;
widget->setLayout(layout);
widget->layout()->addWidget(((GUI*)view)->getTabs( ));
//widget->setGeometry(0, 0, 500, 400);
osg::ref_ptr<osgQt::QWidgetImage> widgetImage = new osgQt::QWidgetImage(widget);
osg::Geometry* quad = osg::createTexturedQuadGeometry(osg::Vec3(30,32,0),
osg::Vec3(40,0,0), osg::Vec3(0,35,0), 1, 1);
osg::Geode* geode = new osg::Geode;
geode->addDrawable(quad);
osg::Texture2D* texture = new osg::Texture2D(widgetImage.get());
texture->setResizeNonPowerOfTwoHint(false);
texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
mt->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
mt->addChild(hudCamera);
osgViewer::InteractiveImageHandler* handler =
new osgViewer::InteractiveImageHandler(widgetImage.get(), texture, hudCamera);
mt->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
mt->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
mt->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
mt->getOrCreateStateSet()->setAttribute(new osg::Program);
quad->setEventCallback(handler);
quad->setCullCallback(handler);
hudCamera->addChild( geode ) ;
hudCamera->addChild( HUDGeometry(73,73,75,75,
"models/quit.png", EXIT_OBJ, this ));
hudCamera->addChild( HUDGeometry(25,25,75,75,
"models/hud.png", NO_EVENT, this ));
osg::Group* overlay = new osg::Group;
overlay->addChild(mt);
root->addChild(overlay);
HUD = hudCamera ;
disableHUD( ) ;
}
I think the main problem is that you do not adapt the dimensions of the widget to the dimensions of the quad you render it on.
I'm not sure what QWidgetImage is doing internally, but I guess it's just rendering the widget onto a canvas of appropriate size and convert the result into an image. In your code you map the complete image (regardless of its dimension or aspect ration) onto that quad. If you want the widget to fit the quad you need to resize the widget before creating an image of it.
I have a bunch of QGraphicsSvgItem's in a QGraphicsScene that are drawn connected by QGraphicsLineItem's. This show's a graph of a tree-structure.
What I want to do is provide a feature where everything but a selected sub-tree becomes transparent. A kind of "highlight this sub-tree" feature. That part was easy, but the results are ugly because now the lines can be seen through the semi-transparent svg's.
I am looking for some way to still clip other QGraphicsItem's in the scene to the svg item's, giving the effect that the svg's are semi-transparent windows to the background.
I know this code does not use svg's but I figure you can replace that yourself if you are so inclined.
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QGraphicsScene scene;
for( int i = 0; i < 10; ++i ) {
QGraphicsLineItem* line = new QGraphicsLineItem;
line->setLine( i * 25.0 + 1.0, 0, i * 25.0 + 23.0, 0 );
scene.addItem( line );
}
for( int i = 0; i < 11; ++i ) {
QGraphicsEllipseItem* ellipse = new QGraphicsEllipseItem;
ellipse->setRect( (i * 25.0) - 9.0, -9.0, 18.0, 18.0f );
ellipse->setBrush( QBrush( Qt::green, Qt::SolidPattern ) );
ellipse->setOpacity( 0.5 );
scene.addItem( ellipse );
}
QGraphicsView view( &scene );
view.show();
return app.exec();
}
I would like the line's to not be seen behind the circle's. I have tried fiddling with the depth-buffer and the stencil buffer using opengl rendering to no avail.
How do I get the QGraphicsSvgItem's (or QGraphicsEllipseItem's in the example code) to still clip the lines even though they are semi-transparent?
The best solution here is to subclass QGraphicsScene and your graphics items.
Create other class for scene and several classes for different graphics items.
Then, you will have "paint" method for each item, where you can draw with the opacity you require.
In that case you will be able to solve clipping problem also because you will have control over the shape and bounding rectangle for each item.
Another nice feature would be ability to link items together in your implementation so that when you click somewhere, you can set the visibility settings for several items at once.
In other words, you will have more control over your entire scene and thus learning and writing these subclasses is a good time investment.
For example, you can see Colliding Mice Example where custom graphics items are painted.