Page 1 of 1

drawing a bunch of 2D points on screen

Posted: Mon Sep 24, 2007 4:16 am
by yjlchina
hi, everybody.

I want to draw pixel point on irrlicht game screen using 2D APIs. the data source is a vector<Point> contains corrdinates which should be present on screen(800x600).So each time there is a event, i would scan the vector and draw the points.

However, I find in tutorial that APIs supporting 2D line and receangle like driver->draw2DRectangle() is called between beginScene() and endScene(). So when i using the code showing below, no effect...

Code: Select all

else if(event.EventType == EET_USER_EVENT) 
	{
		s32 a = event.UserEvent.UserData1;
		//s32 b = event.UserEvent.UserData2;
		f32 f = event.UserEvent.UserData3;

		// transform int handle into a vector pointer
		pactivePoints = static_cast<vector<Point>*>((void*)a);

vector<Point>::iterator i;
	
	if(pactivePoints != NULL)
		for(i = pactivePoints->begin(); i != pactivePoints->end(); i++)
		{
			int x = (*i).x;
			int y = (*i).y;

			position2d<int> start(x, y);
			position2d<int> end(x+1,y+1);
			SColor whitecolor(255,255,255,255);

			driver->draw2DLine(start, end, whitecolor);
			
		}


if i change the structure to:

Code: Select all

driver->beginScene(true, true, video::SColor(0,200,200,200));
for(...)
     driver->draw2DLine(start, end, whitecolor);
driver->endScene();
still no effects...

So, can I call 2D rendering APIs in other part of my program like OnEvent()? You know, if i add a mesh to smgr in other part of the program, it works since i call smgr->drawall() in the main loop.

Posted: Mon Sep 24, 2007 5:47 am
by hybrid
Maybe it's not a good idea to split up your render process into many different places. Render state confusions may likely occur.
anyway, you should probably change to ParticleSystems or simply use the Point drawing provided by the engine. For the latter you can either draw by using the drawVertexPrimitiveList with primitive EPT_POINTS or EPT_POINT_SPRITES, or you draw usual triangles with the material flag pointcloud being enabled. The latter can be used with normal scene nodes, but does not render much faster than the usual mesh, while EPT_POINTS uses far less indices and should render faster. You can use a custom scene node, though.

Posted: Mon Sep 24, 2007 5:57 am
by TomiZ
If you will use

driver->beginScene(true, true, video::SColor(0,200,200,200));
// render points/lines
driver->endScene();

and then you will draw everything else in main loop
driver->beginScene(true, true, video::SColor(0,200,200,200));
smgr->drawAll();
env->drawAll();
driver->endScene();

you will replace previous image (and screen will blinking).

So if you want to draw lines/points you have to do this in you main rendering loop after smgr and gui;

Posted: Mon Sep 24, 2007 8:58 am
by yjlchina
thank you two guys.

i did a little experiment, and find that if i call my drawpoints function in the main loop, it works just fine. codes are like this:

Code: Select all

while(device->run())
{
               driver->beginScene(true, true, video::SColor(0,200,200,200));
		now = device->getTimer()->getTime();
		if (now - sceneStartTime > 5000)
		{
			//do something here
			drawpoints();
			sceneStartTime = now;
		}

		//smgr->drawAll();
		driver->endScene();
}
so, in my simple conclusion, i can call 2D APIs actively in the main render loop and it work fine. but if i want to do some 2D animation passively, such as response to a event, i still can't find a proper place to draw them.

------------------------------------------------------------------------------------
another test. i didn't do a thing in main loop, the main loop look some what like this:

Code: Select all

while(device->run())
	if (device->isWindowActive())
	{}
and i put begine and end scene function into OnEvent() which is a callback. in this way render function appears once in my program. code segement is below:

Code: Select all

 // inside of  OnEvent function
vector<Point>::iterator i;
	
	// test codes
	static ti = 0;
	ti++;
	
	// render points
	driver->beginScene(true, true, video::SColor(0,200,200,200));
	if(pactivePoints != NULL)
		for(i = pactivePoints->begin(); i != pactivePoints->end(); i++)
		{
			int x = (*i).x;
			int y = (*i).y;

			position2d<int> start(x, y);
			position2d<int> end(x+ti,y+ti);
			SColor whitecolor(255,255,255,255);

			driver->draw2DLine(start, end, whitecolor);
		}
	driver->endScene();
as you can see, i put a counter inside. and in my test program, the counter increases ever time it is called. Still i see no points on screen...

I don't know why.

Posted: Mon Sep 24, 2007 9:21 am
by greenya
yjlchina wrote: so, in my simple conclusion, i can call 2D APIs actively in the main render loop and it work fine. but if i want to do some 2D animation passively, such as response to a event, i still can't find a proper place to draw them.
The proper place to drawing is between driver-beginScene() and driver->endScene().

In any other places you can call anytime something like smgr->addXXXNode(), gui->addXXX() and so on -- this all will be handled by smgr->drawAll(), gui->drawAll() and so on -- which is executed between driver->BeginScene() and driver->endScene().

OnEvent() and other your functions should be logical -- they should decide what to draw but don't draw it -- just set some data structures, which will be handled later between beginScene() and endScene() with proper code (also created by yourself).

This is how I see this (as simple as possible). The abstract example of some button animation:

somewhere in globals:

Code: Select all

int myExitButtonStateCount = 16;
int myExitButtonState = -1;
somewhere in OnEvent():

Code: Select all

if (-proper-event-checking-)
{
      myExitButtonState = myExitButtonStateCount-1;
}
somewhere between driver->beginScene() and endScene():

Code: Select all

if (myExitButtonState>=0)
{
      driver->draw2D... // <-- here some drawing of myExitButtonState
      myExitButtonState--;
}

Posted: Mon Sep 24, 2007 1:16 pm
by yjlchina
thanks, greenya.

you show me the right way to think about the problem. It seems my simple conclusion is a little bit 'straight-forward'.

Yes, i should refer to GUI->drawAll() mechanism.