the objective is to draw lines with vtkLineSource from a xml file.
so,I retrieve values from a xml file into vectors, then I loop through the vectors in nested loops to retrieve the values and pass them as arguments to the function of drawing.
here is my code
for ( std::vector<double>::iterator i = tab_recupere_X1.begin();
i != tab_recupere_X1.end();
i++)
{
p0[0]= *i;
std::cout << "p0[0]"<<p0[0]<<std::endl;
for (std::vector<double>::iterator j = tab_recupere_Y1.begin();
j != tab_recupere_Y1.end();
j++)
{
p0[1] = *j;
std::cout << "p0[1]"<<p0[1]<<std::endl;
// break;
for (std::vector<double>::iterator k = tab_recupere_X2.begin();
k != tab_recupere_X2.end();
k++)
{
p1[0] = *k;
std::cout << "p1[0]"<<p1[0]<<std::endl;
for (std::vector<double>::iterator p = tab_recupere_Y2.begin();
p != tab_recupere_Y2.end();
p++)
{
p1[1] = *p;
std::cout << "p1[1]"<<p1[1]<<std::endl;
vtkSmartPointer<vtkLineSource> lineSource =
vtkSmartPointer<vtkLineSource>::New();
lineSource->SetPoint1(p0);
lineSource->SetPoint2(p1);
lineSource->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(lineSource->GetOutputPort());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetLineWidth(4);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(actor);
renderWindow->Render();
renderWindowInteractor->Start();
}
}
}
}
but the last loop runs indefinitely without stopping, and nothing has been drawn.
I used the (break) but nothing has been improved.
My purpose is for each iteration, retrieve the values of x and y and draw lines.
Can you help me please!
thank you in advance.
Alright, I think it is a bit hard to understand what is wrong in your code. I can't see anything obvious (maybe someone else will) but here are a couple points to help you find out what is going on:
Have you tried to comment out all your functions in your last loop (with iterator p)? Is it working when you do so?
You probably don't want to do any display in this big loop, you should build or draw everything then display only when finished.
Refactoring this code would be a good idea, you may know what you're doing now but how about in 6 months? I'm not even mentioning the fact that someone else seeing this code will probably either give up understanding it or rewrite the whole thing himself even if the bug fix would have been one character.
Related
Hello I'm making a game using SFML, but I ran into some problems.
I want to complete this function:
if a human character collide with items, one garbage draw on screen. (5 textures)
So multiple textures of garbages stack up from the bottom of the window.
I tried to use vector and Sprite array, but my codes can't add garbages. It just draw one garbage, and then change another textures.
What should I do to keep garbages drawn until window closes?
I should add many Sprites to solve this problem, but I have no ideas... I've done everything I can.
My code is here:
// out of main loop
Texture GarbagesTexture[5];
GarbagesTexture[0] = garbageTex1;
GarbagesTexture[1] = garbageTex2;
GarbagesTexture[2] = garbageTex3;
GarbagesTexture[3] = garbageTex4;
GarbagesTexture[4] = garbageTex5;
int SelectedGarbage = 0;
vector<Sprite> Garbages;
Position GarbagesPosition;
GarbagesPosition.x = 890.f;
GarbagesPosition.y = 590.f;
// main loop
//collision
for (size_t i = 0; i < items.size(); i++)
{
if (humanArr[index].getGlobalBounds().intersects(item[i].getGlobalBounds()))
{
...
...
CollisionTime++;
SelectedGarbage++;
if (SelectedGarbage > 5) SelectedGarbage = 0;
GarbagesPosition.x = GarbagesPosition.x - 10.f;
GarbagesPosition.y = GarbagesPosition.y - 5.f;
Sprite GarbageInputSprite;
Garbages.push_back(GarbageInputSprite);
Garbages[i].setTexture(GarbagesTexture[SelectedGarbage];
Garbages[i].setPosition(GarbagesPosition.x, GarbagesPosition.y);
}
}
//draw
window.clear();
...
...
for (int i = 0; i < CollisionTime; i++)
window.draw(Garbages[i]);
window.display();
I am a poor beginner in SFML, but I'll try to do my best.
I would really appreciate it if you could help me solve this problem.
I have some crazy issues in my code, and these issue is:
1) As you see in code below, if I execute it I will got a 3D preview model without sliderWidget. (Fixed)
2) If I change this line from mapper->SetInputConnection(surface->GetOutputPort()); to mapper->SetInputConnection(reader->GetOutputPort()); I will got a sliderWidget but I will not see a 3D model. (Fixed)
3) If I try to set custom key event, its will be work and change value but every change I need to wait until its reload or build 3d dicom (its work like you run and create a 3D model every time not like a slider).
class vtkSliderCallback : public vtkCommand
{
public:
int counter = 1;
static vtkSliderCallback *New()
{
return new vtkSliderCallback;
}
virtual void Execute(vtkObject *caller, unsigned long, void*)
{
vtkSliderWidget *sliderWidget =
reinterpret_cast<vtkSliderWidget*>(caller);
cout << this->counter << endl;
this->SphereSource->SetValue(this->counter++, static_cast<vtkSliderRepresentation *>(sliderWidget->GetRepresentation())->GetValue());
}
vtkSliderCallback():SphereSource(0) {}
vtkMarchingCubes *SphereSource;
};
int main(int argc, char* argv[])
{
// Verify input arguments
if ( argc < 4 )
{
std::cout << "Usage: " << argv[0]
<< " DicomSiresFolder" << " isoValueStep" << " OutputDirectory" << std::endl;
return EXIT_FAILURE;
}
std::string folder = argv[1];
// A sphere
vtkSmartPointer<vtkImageData> volume =
vtkSmartPointer<vtkImageData>::New();
vtkSmartPointer<vtkDICOMImageReader> reader =
vtkSmartPointer<vtkDICOMImageReader>::New();
reader->SetDirectoryName(folder.c_str());
reader->Update();
volume->DeepCopy(reader->GetOutput());
vtkSmartPointer<vtkMarchingCubes> surface =
vtkSmartPointer<vtkMarchingCubes>::New();
surface->SetInputData(volume);
surface->ComputeNormalsOn();
surface->SetValue(0, 400);
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(surface->GetOutputPort());
mapper->ScalarVisibilityOff();
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->SetInterpolationToFlat();
// A renderer and render window
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
// An interactor
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
// Add the actors to the scene
renderer->AddActor(actor);
// Render an image (lights and cameras are created automatically)
renderWindow->Render();
vtkSmartPointer<vtkSliderRepresentation3D> sliderRep =
vtkSmartPointer<vtkSliderRepresentation3D>::New();
sliderRep->SetMinimumValue(-800.0);
sliderRep->SetMaximumValue(800.0);
sliderRep->SetTitleText("Iso Resolution");
sliderRep->GetPoint1Coordinate()->SetCoordinateSystemToWorld();
sliderRep->GetPoint1Coordinate()->SetValue(-4,6,0);
sliderRep->GetPoint2Coordinate()->SetCoordinateSystemToWorld();
sliderRep->GetPoint2Coordinate()->SetValue(4,6,0);
sliderRep->SetSliderLength(0.075);
sliderRep->SetSliderWidth(0.05);
sliderRep->SetEndCapLength(0.05);
vtkSmartPointer<vtkSliderWidget> sliderWidget =
vtkSmartPointer<vtkSliderWidget>::New();
sliderWidget->SetInteractor(renderWindowInteractor);
sliderWidget->SetRepresentation(sliderRep);
sliderWidget->SetAnimationModeToAnimate();
sliderWidget->EnabledOn();
vtkSmartPointer<vtkSliderCallback> callback =
vtkSmartPointer<vtkSliderCallback>::New();
callback->SphereSource = surface;
sliderWidget->AddObserver(vtkCommand::InteractionEvent,callback);
renderWindowInteractor->Initialize();
renderWindow->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
UPDATE:
I Fixed issue on point 1 and 2, but still Issue 3 needed to fix.
Your callback is changing the value for vtkMarchingCube, so you're running a marching cubes every time, so yes, it's rebuilding a mesh every time. As far as I understand what you need to do, one solution can be to precompute vtkMarchingCubes output for all possible values: not elegant (but it could work if you have enough memory).
In any case, use vtkFlyingEdges3D instead of vtkMarchingCubes, it's much faster (it could be fast enough to solve your problem without any other modification).
I am currently experiencing some heavy slowdowns with my game. I have narrowed it down to something related with texture animations.
In my game there are characters that walk in 1 of 4 possible directions, they will walk up to a point, then change direction and continue walking (sort of like a tower defense game).
First i am loading the sprite frame cache like this
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("characters.plist");
This code is only run once during the life time of my application.
When the characters get loaded to the screen their animation is being set using the following code:
int direction = 0;
int number = 0;
if (this->to_x < 0) // Left
{
direction = 1;
number = 1;
}
else if(this->to_x > 0) // Right
{
direction = 2;
number = 1;
}
if (this->to_y < 0) // Down
{
direction = 0;
number = 0;
}
else if(this->to_y > 0) // Up
{
direction = 3;
number = 2;
}
int s = 0; //skin
// Set the animation
Animation *animation = Animation::create();
for (int i = 0; i < INT16_MAX; i++)
{
string frame_sprite_name = StringUtils::format("%s_%d_%d_%d.png",parameters[name].image_name.c_str(),s,number,i);
auto frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(frame_sprite_name);
if (frame) {
animation->addSpriteFrame(frame);
} else {
break;
}
}
// Invert the sprite when they go right
if (direction == 2) {
setFlippedX(true);
}else{
setFlippedX(false);
}
// Set the pace of the animation based on the type
if (name=="runner") {
animation->setDelayPerUnit(0.15f);
} else{
animation->setDelayPerUnit(0.3f);
}
Animate *animate = Animate::create(animation);
this->stopAllActions();
this->runAction(RepeatForever::create(animate));
What this code does is:
Check the direction
Get the sprite frame from the cache based on the direction
Run the action with repeat forever.
However this code is ran every time they change direction to set the new animation of the active characters. Also, at one time I can have around 40-50 of these characters going around.
I've noticed that after a few minutes in the game the slowdown starts to happen as soon as a new "character" is created, (since they are created in rapid succession in waves). And the slowdown also happens when the characters change in direction. So this makes me believe I am using the textures wrong.
If anyone knows how to fix this please let me know.
PD: I was thinking about the possibility of pre-loading all the animations and then just having each of the sprites that represent the characters run the corresponding animation.
You should definitely cache the animation in the AnimationCache with addAnimation and getAnimation methods.
I'm having a small issue with VTK. When I launch my program, it starts to render and then automatically stops while it should actually keep on rendering.
I cannot see where that error may come from. I wrote an other piece of code for the exact same rendering which works just fine.
So here is the constructor of my class:
Drawing::Drawing(void)
{
translation = vtkSmartPointer<vtkTransform>::New();
ctxView = vtkContextView::New();
win = ctxView->GetRenderWindow();
ren = ctxView->GetRenderer();
cam = ren->GetActiveCamera();
ren->SetBackground(.0,.0,.0);
}
Here is the piece of code not working:
void Drawing::read(){
std::string filename = BUNNY;
// Read all the data from the file
vtkSmartPointer<vtkXMLPolyDataReader> reader =vtkSmartPointer<vtkXMLPolyDataReader>::New();
reader->SetFileName(filename.c_str());
reader->Update();
cout << "File Found and Loaded : " << filename << endl ;
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(reader->GetOutputPort());
mainActor = vtkSmartPointer<vtkActor>::New();
mainActor->SetMapper(mapper);
ren->AddActor(mainActor);
win->PolygonSmoothingOn();
win->Render();
win->Start();
}
And here is the piece of code working:
void otherRead(){
std::string filename = BUNNY;
// Read all the data from the file
vtkSmartPointer<vtkXMLPolyDataReader> reader =vtkSmartPointer<vtkXMLPolyDataReader>::New();
reader->SetFileName(filename.c_str());
reader->Update();
cout << "File Found and Loaded : " << filename << endl ;
// Visualize
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(reader->GetOutputPort());
mainActor = vtkSmartPointer<vtkActor>::New();
mainActor->SetMapper(mapper);
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renderWindow);
vtkInteractorStyleMultiTouchCamera *style =
vtkInteractorStyleMultiTouchCamera::New();
iren->SetInteractorStyle(style);
renderer->AddActor(mainActor);
renderer->SetBackground(0,0,0); // Background color green
renderWindow->PolygonSmoothingOn();
renderWindow->Render();
renderWindowInteractor->Start();
}
I don't know if it's a vtk or a c++ problem actually. The output of the not-working piece of code is just a few milliseconds window and then the program exists while the otherRead() gives a normal rendering without exiting the program.
Thanks in advance for the help
So it was indeed a vtk problem. One very basic some might say but still not that easy to figure out when you're starting with vtk.
I'm posting the answer, the documentation is not big on vtk so it might help other newbies. So in fact, the event loop for the window has to be started. It can be done thanks to the following lines:
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(win);
vtkInteractorStyleMultiTouchCamera *style =
vtkInteractorStyleMultiTouchCamera::New();
iren->SetInteractorStyle(style);
//Start the event loop
iren->Initialize();
iren->Start();
Hope this helps :)
Im aware this code just looks like a massive block of mess so iv'e done my best to comment what i can... If anyone regularly does skeletal animation im hoping youl see whats going on here.
The problem im having is that float interp = (next-current)/(next-start); is not returning whats expected, e.g. values greater than 1 and minus values... Im guessing this is the whole reason the animations arent being shown and theres no other underlying mistakes.. If there is anything obvious sticking out please let me know.
m_animations stores all the keyframe information for a joint.
void Animation::getRotation(Joint& J) {
int i=0,j=0; //i for bone to animation j for which keyframe in animation
float start, next, current = m_time.elapsed(); //storing time elapsed to keep it the same thoughout method to avoid errors
for (i=0; i<m_animations.size(); i++) {
if(m_animations[i].m_bname == J.name) //finds which bone is being animated
break;
} //retrieve the correct 'anim' for Joint
if (current > m_animations[i].rx_time[m_animations[i].rx_time.size()-1]) { //checks to see if end of animation
m_time.restart();
current = m_time.elapsed(); //resets the animation at its end
}
for (j=0; j<m_animations[i].rx_time.size()-1; j++) {
if(m_animations[i].rx_time[j] >= next && next < m_animations[i].rx_time[j+1]) { //finds the keyframe
start = m_animations[i].rx_time[j]; //start time of current frame
next = m_animations[i].rx_time[j+1]; //end time of current frame
break;
}
}
cout << start <<" "<< current <<" "<< m_time.elapsed() <<" "<< next << endl;
//Get start and end quaternions for slerp
Rotation3 Rj(m_animations[i].rx_angle[j], m_animations[i].ry_angle[j], m_animations[i].rz_angle[j], J.translation);
J.quat = Rj.GetQuat(); //rotating to
Rotation3 R = Rotation3(m_animations[i].rx_angle[j+1], m_animations[i].ry_angle[j+1], m_animations[i].rz_angle[j+1], J.translation);
Quat4 q = R.GetQuat(); //rotating from
float interp = (next-current)/(next-start); //find interpolation point
Quat4 slerp = Slerp(J.quat, q, interp); //sphereical linear interpolation
R = Rotation3(slerp,J.translation);
J.rotation.PasteRotation(R.GetRotationMatrix());
}
Also if it helps heres the update skeleton function that calls getRotation
void Animation::update_skeleton(Joint& J) {
getRotation(J);
J.world.PasteTranslation(J.translation); //world becomes translation matrix
J.world *= J.rotation;
if(J.pName != "") {
J.world = Mat4(J.parent->world) *= J.world; //as not to overwrite the parents world matrix
}
J.translation = J.world.ExtractTranslation();
for(int i=0; i<J.children.size(); i++) {
update_skeleton(*J.children[i]);
}
}
Also when i run my program, it seems to be as if there is only one joint... So im guessing something might be going wrong with the J.translation value during getRotation, but im hoping that fixing my interpolation problem might solve this...
Any help will be VERY appreciated.
You seem to be resetting current before using the original values of start and next, if I've read the code properly that will be causing current to be greater than next, leading to yor negative interpolations.
Turns out there were quite a few mistakes... But the main error was to do with pointers, I fixed it by giving the bones ids for parents, children and itself. Then I changed the functions to take bone id instead of reference to a joint. Problem = fixed :D