Mouse control tips

I try to write the bump mapping program in C++.

Some Python codes are:


        self.focus = Vec3(55,-55,20)
        self.heading = 180
        self.pitch = 0
        #self.mousex = 0
        #self.mousey = 0
        self.last = 0
        self.mousebtn = [0,0,0]

        taskMgr.add(self.controlCamera, "camera-task")
        self.accept("escape", sys.exit, [0])
        self.accept("mouse1", self.setMouseBtn, [0, 1])
        self.accept("mouse1-up", self.setMouseBtn, [0, 0])
        self.accept("mouse2", self.setMouseBtn, [1, 1])
        self.accept("mouse2-up", self.setMouseBtn, [1, 0])
        self.accept("mouse3", self.setMouseBtn, [2, 1])
        self.accept("mouse3-up", self.setMouseBtn, [2, 0])
        self.accept("enter", self.toggleShader)
        self.accept("j", self.rotateLight, [-1])
        self.accept("k", self.rotateLight, [1])
        self.accept("arrow_left", self.rotateCam, [-1])
        self.accept("arrow_right", self.rotateCam, [1])

    ......
        
    def setMouseBtn(self, btn, value):
        self.mousebtn[btn] = value

    def rotateLight(self, offset):
        self.lightpivot.setH(self.lightpivot.getH()+offset*20)

    def rotateCam(self, offset):
        self.heading = self.heading - offset*10

    def toggleShader(self):
        self.inst5.destroy()
        if (self.shaderenable):
            self.inst5 = addInstructions(0.75, "Enter: Turn bump maps On")
            self.shaderenable = 0
            self.room.setShaderOff()
        else:
            self.inst5 = addInstructions(0.75, "Enter: Turn bump maps Off")
            self.shaderenable = 1
            self.room.setShaderAuto()

    def controlCamera(self, task):
        md = base.win.getPointer(0)
        x = md.getX()
        y = md.getY()
        if base.win.movePointer(0, 100, 100):
            self.heading = self.heading - (x - 100) * 0.2
            self.pitch = self.pitch - (y - 100) * 0.2
        if (self.pitch < -45): self.pitch = -45
        if (self.pitch >  45): self.pitch =  45
        base.camera.setHpr(self.heading,self.pitch,0)
        dir = base.camera.getMat().getRow3(1)
        elapsed = task.time - self.last
        if (self.last == 0): elapsed = 0
        if (self.mousebtn[0]):
            self.focus = self.focus + dir * elapsed*30
        if (self.mousebtn[1]) or (self.mousebtn[2]):
            self.focus = self.focus - dir * elapsed*30
        base.camera.setPos(self.focus - (dir*5))
        if (base.camera.getX() < -59.0): base.camera.setX(-59)
        if (base.camera.getX() >  59.0): base.camera.setX( 59)
        if (base.camera.getY() < -59.0): base.camera.setY(-59)
        if (base.camera.getY() >  59.0): base.camera.setY( 59)
        if (base.camera.getZ() <   5.0): base.camera.setZ(  5)
        if (base.camera.getZ() >  45.0): base.camera.setZ( 45)
        self.focus = base.camera.getPos() + (dir*5)
        self.last = task.time
        return Task.cont
...

Some C++ Codes I write are:

        //Define events
        int keys[12] ={0,1,0,0,1,1,1,0,2,1,2,0};
        framework.define_key("mouse1", "", setMouseBtn, &keys[0]);
        framework.define_key("mouse1-up", "", setMouseBtn, &keys[2]);
        framework.define_key("mouse2", "", setMouseBtn, &keys[4]);
        framework.define_key("mouse2-up", "", setMouseBtn, &keys[6]);
        framework.define_key("mouse3", "", setMouseBtn, &keys[8]);
        framework.define_key("mouse3-up", "", setMouseBtn, &keys[10]);
        framework.define_key("enter", "", toggleShader, NULL);
        int offset[2] ={-1,1};
        framework.define_key("j", "", rotateLight, &offset[0]);
        framework.define_key("k", "", rotateLight, &offset[1]);
        framework.define_key("arrow_left", "", rotateCam, &offset[0]);
        framework.define_key("arrow_right", "", rotateCam, &offset[1]);

        ....

//Define global variable and function
LVecBase3f focus = LVecBase3f(55,-55,20);
float heading = 180;
float pitch = 0;
float last = 0;
int mousebtn[3] = {0,0,0};
bool shaderenable = false;

void setMouseBtn(const Event * event, void *data){
	int * _data = (int *) data;
	mousebtn[_data[0]] = _data[1];
}
void toggleShader(const Event * event, void *data){
	if (shaderenable) {
		instruction[4]->set_text("Enter: Turn bump maps On");
		shaderenable = false;
		room.set_shader_off();
	}else {
		instruction[4]->set_text("Enter: Turn bump maps Off");
		shaderenable = true;
		room.set_shader_auto();
	}
}
void rotateLight(const Event * event, void *data){
	int * _data = (int *) data;
	lightpivot.set_h(lightpivot.get_h()+*_data*20);
}
void rotateCam(const Event * event, void *data){
	int * _data = (int *) data;
	heading -= *_data*10;
}
AsyncTask::DoneStatus controlCamera(GenericAsyncTask* task, void* data) {

	MouseData md = window->get_graphics_window()->get_pointer(0);
	int x = md.get_x();
	int y = md.get_y();
	if (window->get_graphics_window()->move_pointer(0, 100, 100)){
		heading -= (x - 100) * 0.2;
		pitch -= (y - 100) * 0.2;
	}
	if (pitch < -45) pitch = -45;
	if (pitch > 45) pitch = 45;
	camera.set_hpr(heading,pitch,0);
	LVecBase3f dir = camera.get_mat().get_row3(1);
	double elapsed = task->get_dt()-last;
	if (last==0) elapsed = 0;
	if (mousebtn[0]==1)
		focus += dir * elapsed*30;
    if (mousebtn[1]==1||mousebtn[2]==1)
    	focus -= dir * elapsed*30;
    camera.set_pos(focus - (dir*5));
    if (camera.get_x() < -59.0) camera.set_x(-59);
    if (camera.get_x() >  59.0) camera.set_x( 59);
    if (camera.get_y() < -59.0) camera.set_y(-59);
    if (camera.get_y() >  59.0) camera.set_y( 59);
    if (camera.get_z() <   5.0) camera.set_z(  5);
    if (camera.get_z() >  45.0) camera.set_z( 45);
    focus = camera.get_pos() + (dir*5);
    last = task->get_dt();

    return AsyncTask::DS_cont;
}

However, I can not control the mouse, how to do?

I don’t see you adding the task to the task manager anywhere.

Oh, other codes are very easy, and we have past them easily, so I ignore them.

The task is added to the list by the code:

 taskMgr->add(new GenericAsyncTask("camera-task", &controlCamera, (void*) NULL));

I had also seen the lightpivot spinning, I use CLerpNodePathInterval to do it.

The troubles we meet are:

1)When I move the mouse, I can not control it as I do in Python program, I can not locate the right position to watch the bump mapping effect.

2)When I click the left button, no response.

3)When I click the right button, no response.

4)When I click the middle button, no response.

It seems I can not control the mouse by the way of that in Python codes.

The mouse control works the same in C++ as in Python, once you get past the initial setup. Have you called
window->enable_keyboard()? That will be necessary to activate the mouse buttons as well as the keyboard buttons.

Other than that, you need to use standard debugging techniques. If nothing happens when you click the mouse button, is it calling the event callback? You can put a cerr statement in the callback function to prove it.

David

You’re defining “int keys” and “int offset” in the function itself, so it’s no longer in the stack when that function finished executing. You will need to put them on the heap or declare them someplace where you’re sure that they are still in memory when the task is run.

You could find out if this is the issue by just putting some cerr statements around your code to see if the functions are being called and that the values are correct.

Of course, I do.

I have some questions, I comment them in the codes below:

//Do I use the right global variable of camera?
camera = window->get_camera_group();

......

        MouseData md = window->get_graphics_window()->get_pointer(0);
	int x = md.get_x();
	int y = md.get_y();
        //what does this line do?
        //it seems that move_pointer() always return false!
	if (window->get_graphics_window()->move_pointer(0, 100, 100)){
		heading -= (x - 100) * 0.2;
		pitch -= (y - 100) * 0.2;
	}
	if (pitch < -45) pitch = -45;
	if (pitch > 45) pitch = 45;
        camera.set_hpr(heading,pitch,0);
        //Does the index of get_row3() range from 0~3?
        //Is it as same as that in python?
	LVecBase3f dir = camera.get_mat().get_row3(1);
	double elapsed = task->get_dt()-last;
	if (last==0) elapsed = 0;
	if (mousebtn[0]==1)
		focus += dir * elapsed*30;
    if (mousebtn[1]==1||mousebtn[2]==1)
    	focus -= dir * elapsed*30;
    //what does this line do?
    camera.set_pos(focus - (dir*5));
    if (camera.get_x() < -59.0) camera.set_x(-59);
    if (camera.get_x() >  59.0) camera.set_x( 59);
    if (camera.get_y() < -59.0) camera.set_y(-59);
    if (camera.get_y() >  59.0) camera.set_y( 59);
    if (camera.get_z() <   5.0) camera.set_z(  5);
    if (camera.get_z() >  45.0) camera.set_z( 45);
    //what does this line do?
    focus = camera.get_pos() + (dir*5);
    last = task->get_dt();

    ...

I will debug them now, I will post the runnable code skeleton soon.

The simple version of the codes are:

#include "pandaFramework.h"
#include "pandaSystem.h"
#include "textNode.h"
#include "cIntervalManager.h"
#include "mouseData.h"
#include "lmatrix.h"

PandaFramework framework;
PT(WindowFramework) window;
NodePath camera, render, room;
PT(TextNode) instruction[5];
string instructionText[5] = {"Press ESC to exit",
		                      "Move mouse to rotate camera",
		                      "Left mouse button: Move forwards",
		                      "Right mouse button: Move backwards",
		                      "Enter: Turn bump maps Off"};
PT(AsyncTaskManager) taskMgr = AsyncTaskManager::get_global_ptr();
LVecBase3f focus = LVecBase3f(55,-55,20);
float heading = 180;
float pitch = 0;
float last = 0;
int mousebtn[3] = {0,0,0};
bool shaderenable = false;

void setMouseBtn(const Event * event, void *data){
	int * _data = (int *) data;
	mousebtn[_data[0]] = _data[1];
}
void toggleShader(const Event * event, void *data){
	if (shaderenable) {
		instruction[4]->set_text("Enter: Turn bump maps On");
		shaderenable = false;
		room.set_shader_off();
	}else {
		instruction[4]->set_text("Enter: Turn bump maps Off");
		shaderenable = true;
		room.set_shader_auto();
	}
}
void rotateLight(const Event * event, void *data){
	//int * _data = (int *) data;
	//lightpivot.set_h(lightpivot.get_h()+(*_data)*20);
}
void rotateCam(const Event * event, void *data){
	int * _data = (int *) data;
	heading -= (*_data)*10;
}
AsyncTask::DoneStatus controlCamera(GenericAsyncTask* task, void* data) {
	MouseData md = window->get_graphics_window()->get_pointer(0);
	int x = md.get_x();
	int y = md.get_y();
	if (window->get_graphics_window()->move_pointer(0, 100, 100)){
		heading -= (x - 100) * 0.2;
		pitch -= (y - 100) * 0.2;
	}
	if (pitch < -45) pitch = -45;
	if (pitch > 45) pitch = 45;
	camera.set_hpr(heading,pitch,0);
	LVecBase3f dir = camera.get_mat().get_row3(1);
	double elapsed = task->get_dt()-last;
	if (last==0) elapsed = 0;
	if (mousebtn[0]==1)
		focus += dir * elapsed*30;
    if (mousebtn[1]==1||mousebtn[2]==1)
    	focus -= dir * elapsed*30;
    camera.set_pos(focus - (dir*5));
    if (camera.get_x() < -59.0) camera.set_x(-59);
    if (camera.get_x() >  59.0) camera.set_x( 59);
    if (camera.get_y() < -59.0) camera.set_y(-59);
    if (camera.get_y() >  59.0) camera.set_y( 59);
    if (camera.get_z() <   5.0) camera.set_z(  5);
    if (camera.get_z() >  45.0) camera.set_z( 45);
    focus = camera.get_pos() + (dir*5);
    last = task->get_dt();

    return AsyncTask::DS_cont;
}

int main(int argc, char *argv[]) {

    framework.open_framework(argc, argv);
    framework.set_window_title("Bump Mapping");
    window = framework.open_window();
    if (window != (WindowFramework *)NULL) {

        window->enable_keyboard();
        camera = window->get_camera_group();
        render = window->get_render();
        window->set_background_type(WindowFramework::BT_black);

        for (int i=0;i<5;i++){
        	instruction[i] = new TextNode("instruction" + i);
        	instruction[i]->set_text_color(1,1,1,1);
        	instruction[i]->set_text(instructionText[i]);
        	instruction[i]->set_align(TextNode::A_left);

        	NodePath instructionNP = window->get_aspect_2d().attach_new_node(instruction[i]);
        	instructionNP.set_scale(0.05);
        	instructionNP.set_pos(-1.30, 0.0, .95-.05*i);
        }

        room = window->load_model(framework.get_models(),"../models/abstractroom");
        room.reparent_to(render);

        room.set_shader_auto();
        shaderenable = true;

        framework.define_key("escape", "close window", framework.event_esc, &framework);
        int keys[12] ={0,1,0,0,1,1,1,0,2,1,2,0};
        framework.define_key("mouse1", "", setMouseBtn, &keys[0]);
        framework.define_key("mouse1-up", "", setMouseBtn, &keys[2]);
        framework.define_key("mouse2", "", setMouseBtn, &keys[4]);
        framework.define_key("mouse2-up", "", setMouseBtn, &keys[6]);
        framework.define_key("mouse3", "", setMouseBtn, &keys[8]);
        framework.define_key("mouse3-up", "", setMouseBtn, &keys[10]);
        framework.define_key("enter", "", toggleShader, NULL);
        int offset[2] ={-1,1};
        framework.define_key("j", "", rotateLight, &offset[0]);
        framework.define_key("k", "", rotateLight, &offset[1]);
        framework.define_key("arrow_left", "", rotateCam, &offset[0]);
        framework.define_key("arrow_right", "", rotateCam, &offset[1]);

        taskMgr->add(new GenericAsyncTask("camera-task", &controlCamera, (void*) NULL));

        Thread *current_thread = Thread::get_current_thread();
        while(framework.do_frame(current_thread)) {
        	CIntervalManager::get_global_ptr()->step();
        }

    } else {
    	nout << "Could not load the window!\n";
    }
    framework.close_framework();
    return (0);
}

I am debugging! The trouble remains.

I had found the reason :smiley:

But I still not quite understand the codes commented. Pls help me :blush:

move_pointer moves the mouse pointer to the indicated location. It’s probably returning false because when you’re testing, the mouse is outside the window, so Panda has no control over it, or something along those lines.

To answer your other questions:

        //Does the index of get_row3() range from 0~3?
        //Is it as same as that in python?
   LVecBase3f dir = camera.get_mat().get_row3(1);

Yes, the range is 0…3, because a matrix has four rows. This returns the indicated row of the matrix, as a 3-component vector (ignoring the fourth column). This is the same as in Python (it’s the same function call, in fact).

In this case, this code relies on the understanding that the second row of the matrix contains the vector that corresponds to the Y axis, which is the same thing as the forward vector. There are clearer ways in Panda to get the forward vector.

    //what does this line do?
    camera.set_pos(focus - (dir*5));

This sets the position of the camera node to the indicated value. Specifically, it is moving the camera in the opposite direction of “dir”, which we’ve already established is the forward vector.

    //what does this line do? 
    focus = camera.get_pos() + (dir*5); 

Returns the camera’s current position and then adjusts it in the direction of “dir”.

David

Thank both of you very much.

The tips of mouse control is still sciolistic, I will ask you when needed.

Happy new year! Good luck to 2012!

Please see the below codes:


...
 window->setup_trackball();
 window->get_mouse().ls();//case 1

I have the mouse, it can move camera, so, the results are:

Then I want to detect the mouse, the codes used are:

...
window->setup_trackball();
if (DCAST(MouseWatcher, window->get_mouse().node())->has_mouse()==true){//case 2
        	window->get_mouse().ls();
        }else{
        	cout<<"no mouse"<<endl;
        }

I guess the result should be as same as case 1, however, the result is:

What a mess! what’s wrong with the mouse?

Perhaps the mouse is not inside the window at that moment? Panda3D has no control over the mouse and is not guaranteed to have knowledge of its position when it is outside the window, therefore has_mouse() will return false.

Yes, the mouse is not in the window.

When I want to control the ball in the maze by mouse, I find the ball is always “hiccup”, i.e, flying away from the maze.

I want to know the stand C++ way to use task.time. In Python, the dt is calculated by:

...
    dt = task.time - task.last
    task.last = task.time

    if dt > .2: return Task.cont 
...

I found methods below have the same value:

//method 1
dt = globalClock->get_dt();

//method 2
dt = task->get_elapsed_time() - last;
last = task->get_elapsed_time();

However, dt is too large![0.28 ~ 0.8]

I do not know what is task->get_dt(), [0.0001 ~ 0.0004]. When I control the mouse move in the maze, which one is the right way?

Python’s task.time is equivalent to C++'s task->get_elapsed_time(). If you are getting larger values in your C++ app, perhaps it is because your frame rate really is poorer there? You could use PStats to verify whether this is true.

David

Yes, the meter shows it’s only 2~3fps. Then how to do?

I let dt /= 6.5;

return condition is dt > 0.05. It seems work. However, still fly away some time.

What is your supposed fps?

Is there any way to handle this problem automatically?

If your fps is too low, it’s because something in the frame is taking too long. I don’t know what it is in your case, but you can use PStats to figure it out. Is there one particular color band that’s much bigger than the rest? Double-click on it and see what it is made of. Is one of its components much bigger than the rest? Keep going until you’ve isolated the culprit.

David

The reason may be the OS is hosted in VMWare.

After changing the parameters’ values, the speed become slower. However, the ball will stay in the maze and keep running.

I will use PStats to check them soon.

I had just finished coding for the FPS simulation.

I will go ahead for the last tutorial program, motion trails.

So, keep in touch.

As I said today morning, I try to finish the last remain tutorial: motion trails.

However, after coding and debugging all errors, I found there have no effects for PaintBrush, Wings of Blue and Whirlpool effect. I do not know the reason. Can you help us?

The Codes are:

#include "pandaFramework.h"
#include "pandaSystem.h"
#include "textNode.h"
#include <sstream>
#include "cIntervalManager.h"
#include "cLerpNodePathInterval.h"
#include "texturePool.h"
#include "graphicsEngine.h"
#include <stdio.h>
#include "genericAsyncTask.h"
#include "asyncTaskManager.h"
#include "ambientLight.h"
#include "directionalLight.h"
#include "orthographicLens.h"

PandaFramework framework;
PT(WindowFramework) window;
NodePath camera, render, bcard, fcard;
double clickrate, nextclick;
PT(TextNode) instruction[6];
string instructionText[6] = {"Press ESC to exit",
		             "Press 1: Ghost effect",
		             "Press 2: PaintBrush effect",
		             "Press 3: Double Vision effect",
		             "Press 4: Wings of Blue effect",
		             "Press 5: Whirlpool effect"};
PT(AsyncTaskManager) taskMgr = AsyncTaskManager::get_global_ptr();
AsyncTask::DoneStatus takeSnapShot(GenericAsyncTask* task, void* data) {
    if (task->get_elapsed_time() > nextclick){
        nextclick += 1.0 / clickrate;
        if (nextclick < task->get_elapsed_time())
        	nextclick = task->get_elapsed_time();
        window->get_graphics_output()->trigger_copy();
    }

    return AsyncTask::DS_cont;
}
void chooseEffectGhost(const Event * event, void *data){
    window->set_background_type(WindowFramework::BT_black);
    bcard.hide();
    fcard.show();
    fcard.set_color(1.0,1.0,1.0,0.99);
    fcard.set_scale(1.00);
    fcard.set_pos(0,0,0);
    fcard.set_r(0);
    clickrate = 30;
    nextclick = 0;
}
void chooseEffectPaintBrush(const Event * event, void *data){
    window->set_background_type(WindowFramework::BT_black);
    bcard.show();
    fcard.hide();
    bcard.set_color(1,1,1,1);
    bcard.set_scale(1.0);
    bcard.set_pos(0,0,0);
    bcard.set_r(0);
    clickrate = 10000;
    nextclick = 0;
}
void chooseEffectDoubleVision(const Event * event, void *data){
    window->set_background_type(WindowFramework::BT_black);
    bcard.show();
    bcard.set_color(1,1,1,1);
    bcard.set_scale(1.0);
    bcard.set_pos(-0.05,0,0);
    bcard.set_r(0);
    fcard.show();
    fcard.set_color(1,1,1,0.60);
    fcard.set_scale(1.0);
    fcard.set_pos(0.05,0,0);
    fcard.set_r(0);
    clickrate = 10000;
    nextclick = 0;
}
void chooseEffectWingsOfBlue(const Event * event, void *data){
    window->set_background_type(WindowFramework::BT_black);
    fcard.hide();
    bcard.show();
    bcard.set_color(1.0,0.90,1.0,254.0/255.0);
    bcard.set_scale(1.1,1,0.95);
    bcard.set_pos(0,0,0.05);
    bcard.set_r(0);
    clickrate = 30;
    nextclick = 0;
}
void chooseEffectWhirlpool(const Event * event, void *data){
    window->set_background_type(WindowFramework::BT_black);
    bcard.show();
    fcard.hide();
    bcard.set_color(1,1,1,1);
    bcard.set_scale(0.999);
    bcard.set_pos(0,0,0);
    bcard.set_r(1);
    clickrate = 10000;
    nextclick = 0;
}
int main(int argc, char *argv[]) {
    framework.open_framework(argc, argv);
    framework.set_window_title("Motion");
    window = framework.open_window();
    if (window != (WindowFramework *)NULL) {
    	window->enable_keyboard();
        camera = window->get_camera_group();
        render = window->get_render();

    
        PT(TextNode) title = new TextNode("title");
        title->set_text("Tutorial 25 - Motion Trails");
        title->set_text_color(1,1,1,1);
        title->set_align(TextNode::A_right);

        NodePath titleNP = window->get_aspect_2d().attach_new_node(title);
        titleNP.set_pos(1.3,0.0,-0.95);
        titleNP.set_scale(0.07);

        for (int i=0;i<6;i++){
        	instruction[i] = new TextNode("instruction" + i);
        	instruction[i]->set_text_color(1,1,1,1);
        	instruction[i]->set_text(instructionText[i]);
        	instruction[i]->set_align(TextNode::A_left);

        	NodePath instructionNP = window->get_aspect_2d().attach_new_node(instruction[i]);
        	instructionNP.set_scale(0.05);
        	instructionNP.set_pos(-1.30, 0.0, .95-.06*i);
        }

        camera.set_pos(0, -26, 4);

        NodePath character = window->load_model(render,"../models/dancer");
        window->loop_animations();

        PT(DirectionalLight) dlight = new DirectionalLight("dlight");
        PT(AmbientLight) alight = new AmbientLight("alight");
        NodePath dlnp = render.attach_new_node(dlight);
        NodePath alnp = render.attach_new_node(alight);
        dlight->set_color(Colorf(1.0, 0.9, 0.8, 1));
        alight->set_color(Colorf(0.2, 0.3, 0.4, 1));
        dlnp.set_hpr(0, -60, 0);
        render.set_light(dlnp);
        render.set_light(alnp);

        PT(Texture) tex = new Texture();
        tex->set_minfilter(Texture::FT_linear);
       window->get_graphics_output()->add_render_texture(tex, GraphicsOutput::RTM_triggered_copy_texture);


	PT(DisplayRegion) dr = window->get_graphics_output()->make_mono_display_region(0,1,0,1);
	dr->set_sort(-10);
	dr->set_clear_depth_active(true);
        dr->set_incomplete_render(false);

        float left=-1, right=1, bottom=-1, top=1;
        PT(Camera) cam2dNode = new Camera("cam2d");
        PT(OrthographicLens) lens = new OrthographicLens();
        lens->set_film_size(right - left, top - bottom);
        lens->set_film_offset((right + left) * 0.5, (top + bottom) * 0.5);
        lens->set_near_far(-1000, 1000);
        cam2dNode->set_lens(lens);
        NodePath backcam =  window->get_render_2d().get_child(0).attach_new_node(cam2dNode);
        dr->set_camera(backcam);
        NodePath background = NodePath("background");
        backcam.reparent_to(background);
        background.set_depth_test(false);
        background.set_depth_write(false);
        DCAST(DisplayRegion, DCAST(Camera, backcam.node())->get_display_region(0))->set_clear_depth_active(false);

        bcard = window->get_graphics_output()->get_texture_card();
        bcard.reparent_to(background);
        bcard.set_transparency(TransparencyAttrib::M_alpha);
        fcard = window->get_graphics_output()->get_texture_card();
        fcard.reparent_to(window->get_render_2d());
        fcard.set_transparency(TransparencyAttrib::M_alpha);

        chooseEffectGhost(NULL, NULL);

        if (window->get_graphics_output()->get_gsg()->get_copy_texture_inverted()){
              cout<<"Copy texture is inverted."<<endl;
              bcard.set_scale(1,1,-1);
              fcard.set_scale(1,1,-1);
        }

        taskMgr->add(new GenericAsyncTask("takeSnapShot", &takeSnapShot, (void*) NULL));

        framework.define_key("escape", "close window", framework.event_esc, &framework);
        framework.define_key("1", "", chooseEffectGhost, NULL);
        framework.define_key("2", "", chooseEffectPaintBrush, NULL);
        framework.define_key("3", "", chooseEffectDoubleVision, NULL);
        framework.define_key("4", "", chooseEffectWingsOfBlue, NULL);
        framework.define_key("5", "", chooseEffectWhirlpool, NULL);

        framework.main_loop();
    } else {
    	nout << "Could not load the window!\n";
    }
    framework.close_framework();
    return (0);
}

In my opinion, this example should be fairly simple, however, why effect 2, 4, 5 can not work?

I will post it to right place in future.