I'm making a thread software with VTK, where I need to change the model itself in real time, while I need to change his method of rendering. Everything is working fine, but, the problem start with the interactor->start(); , the model data gets updated just fine, but it's only showed on screen when I move The camera. Also I have selected some methods for generating a 3D data from a imagedata file, for that I need to close the vtk window (interactor window) and then the code will reopen it and send the new data generated to it...
I would need something like these:
int force close_window = false; int refresh_interactor = false;
I managed to make the Window close, but only with vtkcommand::Keypressed command, but idk how do I do with a new command :S, I tried the vtkcommand::UserEvent but I didn't found a good information about how to deal with that data (like some way to call it)
the way I'm dealing with VTK is with two threads, the first one, is just about the vtk iren loop, and the second one would manage the models and check if iren requires to be updated.
In my dream code it should be something like this:
=======================================================
bool VTKWindow()
{
...
vtkSmartPointer ator = vtkSmartPointer::New();
iren = vtkSmartPointer::New();
RenWindow = vtkSmartPointer::New();
render->SetBackground(.1, .2, .3);
RenWindow->AddRenderer(renderer);
iren->SetRenderWindow(RenWindow);
if(data_type == voxel_type)
{
Render->AddViewProp(VoxelData);
}
else
{
actor->SetMapper(PolyData);
Render->AddActor(Actor);
}
RenWindow->Render();
iren->Start();
}
void ManageVTK()
{
while true loop...
if(force close_window == true)
do some command to exit the iren loop
if(refresh_interactor == true)
do some command to refresh iren
}
Sorry for the english, it's not my native language, and also sorry about the question format, it's the first time I'm using stackoverflow
It may sounds stupid, but, I found a kind of solution for the problem.
I saw on related links this guy vtkRenderWindowInteractor event loop and threading and, it's almost the same problem...
class VTKNewEvent : public vtkCommand{
public:
vtkTypeMacro(VTKNewEvent , vtkCommand);
static VTKNewEvent * New(){
return new VTKNewEvent ;
}
void Execute(vtkObject * caller, unsigned long vtkNotUsed(eventId), void * vtkNotUsed(callData)){
vtkRenderWindowInteractor *iren = static_cast<vtkRenderWindowInteractor*>(caller);
if (iren_close == true){
iren->GetRenderWindow()->Finalize // Stop the interactor
iren->TerminateApp();
iren_close = false;
}
if (iren_update== true){
renderJanela->Render();
iren_update= false;
}
}
};
bool VTKWindow(){
vtkSmartPointer<VTKNewEvent > IrenRefresh= vtkSmartPointer<VTKNewEvent>::New();
...
iren->CreateRepeatingTimer(1);//this makes that IrenRefresh will be called at every 1ms
iren->AddObserver(vtkCommand::TimerEvent, IrenRefresh);
iren->Start();
...
}
it's simple, but, maybe not the best, but it did Th job, I hope this link will help people that are starting into the VTK world, since threads + rendering loop wasn't a simple job to understand what was going on
Related
Using Cocos2d-x and C++, I'm trying to play and pause an animation for a sprite.
I'm using version 3.15.1 of Cocos2dx.
I have a class called PlayerSprite which is derrived from the cocos2d::Sprite class. Inside PlayerSprite initialization, I've setup my animation with the following code:
SpriteBatchNode* playerSpriteBatch = SpriteBatchNode::create("player.png");
SpriteFrameCache* spriteFrameCache = SpriteFrameCache::getInstance();
spriteFrameCache->addSpriteFramesWithFile("player.plist");
Vector<SpriteFrame*> animFrames(2);
char str[18] = { 0 };
for (int i = 1; i < 3; i++) {
sprintf(str, "player_idle_%d.png", i);
SpriteFrame* frame = spriteFrameCache->getSpriteFrameByName(str);
animFrames.pushBack(frame);
}
Animation* idleAnim = Animation::createWithSpriteFrames(animFrames, 0.8f);
self->idleAction = self->runAction(RepeatForever::create(Animate::create(idleAnim)));
self->idleAction->setTag(0);
When I run the code, it works fine and the animation loops correctly.
In my void update() method, I am trying to pause/play the action/animation based of weather the player is moving or idle.
I do this with the following code:
const bool isIdleActionRunning = this->getNumberOfRunningActionsByTag(0) > 0 ? true : false;
const bool isMoving = !vel.isZero();
if (!isMoving && !isIdleActionRunning) {
// Player is idle AND animation is not running
// Run animation
this->runAction(idleAction);
} else if (isMoving && isIdleActionRunning) {
// Player is moving but animation is running
// Pause animation
this->stopActionByTag(0);
}
When I run this code now, my character falls, and as soon as he hits the gound, I get an error at this->runAction(idleAction); saying:
Access violation reading location 0xDDDDDDE5
I believe this is caused due to this->stopActionByTag(0) deleting the action pointer. I've tried to clone the action to avoid this but have had no success.
I know this is a bit late and you might already have solved this but here goes...
Your problem is that you cannot use one instance of Action (idleAction) multiple times. So, once you have run it and removed it, it is released and cannot be used. So, you have 2 options now,
Either create a new idleAction Action every time before running the action.
Or, have an idleAction retained and don't run it ever. Instead, create a clone of this idleAction and run a new clone each time. i.e.
idleAction->retain();
const bool isIdleActionRunning = this->getNumberOfRunningActionsByTag(0) > 0 ? true : false;
const bool isMoving = !vel.isZero();
if (!isMoving && !isIdleActionRunning) {
// Player is idle AND animation is not running
// Run animation
Action idleActionClone = idleAction->clone();
this->runAction(idleActionClone);
} else if (isMoving && isIdleActionRunning) {
// Player is moving but animation is running
// Pause animation
this->stopActionByTag(0);
}
Solution: call retain() to keep your action.
It's a matter of memory management of cocos2d-x.
In create() function of your RepeatForever class (derived from Ref), the reference count is set to 1 and there is a line of code ret->autorelease() before returning the object, which means this object will be released automatically at the end of this frame.
You called runAction() function the same frame you created it, the action is retained by ActionManager, it's reference count set to 2, and then 1 at the end of the frame (autorelease).
After your stopping it, it's released by ActionManager, reference count set to 0 and it's deleted. After this you use your action, it will be an access violation method.
*Edit: don't forget to release the action manually when PlayerSprite is deleted, or it's a leak.
When you stop action it's being recycled from memory. In order to play action once more, you have to recreate it. So you may just make a creator function, which returns your animation. The downside is you're recreating animation each time and it'll also play from the beginning (technically you can rewind it).
But I've developed a simpler technique to pause/resume animations:
Let's say you have an action:
action = MoveBy::create(5.0f, Vec2(50, 100));
Now, you can embed this action into Speed action like this:
action = Speed::create(MoveBy::create(5.0f, Vec2(50, 100)), 1.0f);
1.0f - is speed, so it's normal action rate. Now to pause just call:
action->setSpeed(0.0f);
and to resume:
action->setSpeed(1.0f);
you can also use different speed if you need it for some reason or another ;)
first post here, I also need it to help others.
I'm just new at QT/c++, but with years of hobby making programming things, I'm progressing relatively fast.
I'm trying to learn it by making a game, so on, I made, besides other things, a custom sprite class that inherits from QWidget.
I reimplemented, as a common practice, the paintEvent function, using some tricks, qpixmap/qpainter, json files, spritesheets, codehelpers made by my self, to succefully play an animation with stances like idle/walking/attacking.
All went perfect until I tried to move it while walking by the function move(int x, int y) from QWidget.
The problem, I think, is that every time I call "move" function it updates/refresh/repaint the QWidget by calling paintEvent function again, chopping my animation, generating several issues, etc. etc.
I can't to figure out how to move it without repainting or waiting the animation to finish, or what I'm missing. It seems there are no other ways to move a QWidget.
I belive the problem is in another event function that's being called by a emitted signal, probably moveEvent, but I reimplemented it keeping it empty and the result was the same.
Do you have any idea? Should I remake it all in another way to skip this trouble? Or is it as simple as I can't see the coin opposite to me?
Ask for code if needed.
Thank you so much, Luna.
EDIT 1:
customsprite::customsprite(QWidget *parent, QString spriteName) : QWidget(parent)
{
// qpm is a QPixmap
qpm_idle.load(":/Assets/sprites/" + spriteName + ".png");
qpm_walk.load(":/Assets/sprites/" + spriteName + "_walk.png");
...
// here goes a custom class to load json files for each sprite sheet
// the json contains x,y,h,w info to draw the animation
...
//some int,bools,qstrings
...
// fps is QTimer
fps.setInterval(33);
connect(&fps,SIGNAL(timeout()),this,SLOT(update()));
fps.start();
}
//the paintEvent:
void customsprite::paintEvent(QPaintEvent *){
//
QPainter qp(this);
QRect targetR(xMove,0,spriteW,spriteH);
QRect sourceR(jhV[status].getFrameX(jhV[status].namesV[spriteFg]),0,spriteW*sizeDivisor,spriteH*sizeDivisor);
// things abouts consulting jsonhelper info
switch (status){ // status is to know if should draw idle or walk animation
case 0:
qp.drawPixmap(targetR,qpm_idle,sourceR);
break;
case 1:
xMove = xMove + 1;
targetR = QRect(xMove,0,spriteW,spriteH);
qp.drawPixmap(targetR,qpm_walk,sourceR);
break;
default:
break;
}
// all this works fine
if(!reversingAnimation && shouldAnimate){ // simple bool options
spriteFg++; // an int counter refering to which frame should be drawed
if(spriteFg == jhV[status].getSSSize()){ // this consults the json files by a custom jsonhelper, it works fine
if(reversible){
reversingAnimation = true;
spriteFg = jhV[status].getSSSize() - 1;
}else if(!reversible){
spriteFg = 0;
emitSignals();
if(animateOnce == true){
shouldAnimate = false;
}
}
}
}
//here goes a similar the above code to to handle the animation playing in reverse, nothing important
}
Then in my generic QMainWindow I add an instance of my customsprite class, set its parent as QMainWindow, it appears, play the animation.
The problem is when I try to use:
//cs is customsprite
cs->move(cs->x()+1,cs->Y());
It moves, but interrumping the animation several times.
I have tried also putting it with a "isWalking" bool filter inside the paintEvent, but it's the same.
EDIT 2:
The "xMove" thing there, is a trick used to succefully and smoothly move the animation, but it need to increase the width of the QWidget to being seen.
Not a good solution.
The code I've written displays the sf::Drawable objects only for the top state of the state stack. Rendering works fine for everything, except the sf::Text type, that does not change the color of the text when button.getText().setFillColor(sf::Color:Red) is called. However, when I construct a button with a red text, whenever I try to set another color to that button, I only get a white text, no matter what color I request.
Here's where I change the color of a button:
void GameState_MainMenu::handleRealTimeInput()
{
for each (TextButton button in mButtons)
{
if (button.isSpriteClicked())
{
button.getText().setFillColor(sf::Color::Red);
button.triggerAction();
sf::Clock wait;
sf::Time timer = sf::Time::Zero;
timer = sf::seconds(0.15f);
while (wait.getElapsedTime() < timer)
{
}
wait.restart();
}
}
}
and this is my Game::render() method:
void Game::render()
{
GameState *currentState = getActiveState();
if (currentState != nullptr)
{
mWindow.clear();
currentState->draw();
}
mWindow.display();
}
Lastly, this is the draw method of the MainMenu state:
void GameState_MainMenu::draw()
{
game->mWindow.draw(game->mBackground);
game->mWindow.draw(mSelector.mSprite);
for each (TextButton button in mButtons)
{
game->mWindow.draw(button.getText());
}
}
It's probably because you have a while loop in the GameState_MainMenu::handleRealTimeInput that the program is getting stuck in.
You can try to use threads, though that way could get pretty messy. I suggest revising your code.
Okay, so I figured out this had something to do with c++'s for each instruction. As soon as I switched to the classic array-like traversal, my buttons started changing colors. I'm not saying this is THE solution, just that it worked for me. If anyone has the same problem, you might want to check that.
I've got a button that I need to be a toggle button for the sound of a game. I'm using the MenuSpriteItem class.
auto menuSoundOn = Sprite::createWithSpriteFrameName("soundOn.png");
auto menuSoundOff = Sprite::createWithSpriteFrameName("soundOff.png");
auto menuSoundBtn = MenuItemSprite::create(menuSoundOn, menuSoundOff, CC_CALLBACK_1(LevelsLayer::shutSound, this));
menuSoundBtn->setTag(0);
_mainMenu = Menu::create(menuSoundBtn, nullptr);
this->addChild(_mainMenu);
//Then in my shutSound method
auto menuSoundBtn = _mainMenu->getChildByTag(0);
if (_ifSound){
_ifSound = false;
//Do some stuff to shut the sound
menuSoundBtn->setSelectedImage("noSound.png");
}
else{
_ifSound = true;
//Do some stuff to bring the sound back
menuSoundBtn->setSelectedImage("sound.png");
}
The problem is that getting the Btn from his parent with getChildByTag(0) method I receive a Node according with the documentation, but setSelectedImage is not part of the Node class and there is an error telling me so, so what is the right way to access MenuSpriteItems from their Parents and then manipulate them as in this case by changing the Normal Image?
Greetings.
I've got the answer and It's really powerful and simple.
auto menuSoundBtn = dynamic_cast<MenuItemSprite*>(_mainMenu->getChildByTag(0));
This is the explanation from the guy:
This code will get the child with tag 0 and turn it into a MenuItemSprite* object if it is a MenuItemSprite* object, or it returns null if the object was not a MenuItemSprite*.
Hope it helps someone. Greetings.
I am trying to make my basic loading screen transition over to game level screen. So what i wanted to do is, once the loading screen is active (or has appeared onscreen), I want at this point to start loading my game state. What it is doing at the moment is loading everything at the start, and this does take a while.
So currently my project starts off with a main menu. Then when i press enter, its starts the loading screen. I have my manual state change using keypresses like so:
void Game::update()
{
static bool enterPreviouslyPressed = false;
static bool escapePreviousPressed = false;
const Uint8 *keys = SDL_GetKeyboardState(NULL);
if (keys[::SDL_SCANCODE_ESCAPE] && !escapePreviousPressed && typeid(*fsm->getState()) == typeid(GameState))
{
fsm->setState(menuState);
}
else if (keys[::SDL_SCANCODE_RETURN] && !enterPreviouslyPressed && typeid(*fsm->getState()) == typeid(MainMenuState))
{
fsm->setState(loadingState);
}
else if ((keys[::SDL_SCANCODE_RETURN] && !enterPreviouslyPressed) && typeid(*fsm->getState()) == typeid(LoadScreenState))
{
fsm->setState(gameState);
}
else if (keys[::SDL_SCANCODE_ESCAPE] && !escapePreviousPressed && typeid(*fsm->getState()) == typeid(MainMenuState))
{
exit(0);
}
enterPreviouslyPressed = keys[::SDL_SCANCODE_RETURN] != 0;
escapePreviousPressed = keys[::SDL_SCANCODE_ESCAPE] != 0;
fsm->update();
}
I did this to initially does this so i could change states manually to check that everything works. I was wondering if there was an easy(ish) way, like boolean flags for example or another simpler way to do this. I wasn't able find any tutorials online so wondering if someone knows the best solution as to how to do this. I did see a question on here, kindda similar but I wasn't sure if it answered my question as the person did this in threads which I am not familiar with how to implement. Apologies if I dont seem to have the logic correct - so please advise otherwise.
Looks fairly standard, except I would simplify it by keeping two keyboard state variables declared as class variables, like:
const Uint8 *curKeys = SDL_GetKeyboardState(NULL), *prevKeys;
// ...
void Game::update() {
prevKeys = curKeys;
curKeys = = SDL_GetKeyboardState(NULL);
//and so then compare curKeys to prevkeys
//and ditch the booleans
// ...
}