• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1548
  • Last Modified:

C++ & DirectX 9: Quickest way to draw triangles/circles/etc.. How to optimize this coding?

I will attach the coding below. Basically, what it does is  Draws an object depending on where it is, and what it is.

The main concern where it draws and partially the dx drawing. But this part is the larger blow to framerate:

            if(isPlanet)
                  map->buffer->drawFilledCircle(x0 + addx,y0 + addy,cy/2,color);
            else if(isShip)
                  map->buffer->drawTriangle(x0-5+addx,y0+5+addy,x0+5+addx,y0+5+addy,x0+addx,y0-5+addy,scolor);
            else if(isColony && !colonizedPlanet)
                  map->buffer->drawRect(x0-3+addx,y0-3+addy,x0+4+addx,y0+4+addy,color);




The coding for the drawing is:

void DxCanvas::drawCircle(int x, int y, int rad, D3DCOLOR color, int numSegments){
      if (numSegments <= 0){
            numSegments = rad*2;
            if (numSegments < 2)
                  numSegments = 4;
            if (numSegments > 2000)
                  numSegments = 2000;
      }

      GLDraw::setColor(color);
      Render::setTexture(0);
      GLDraw::beginPrimitive(D3DPT_LINESTRIP);
      float xCenter = (float)x, yCenter = (float)y, radius = (float)rad;
      GLDraw::vertex2f(xCenter + radius, yCenter);
      float add = pi*2.0f/(float)numSegments;
      float angle = add;
      for (int i = 1; i < numSegments; i++, angle+= add)
            GLDraw::vertex2f(xCenter + cos(angle)*radius, yCenter + sin(angle)*radius);
      GLDraw::vertex2f(xCenter + radius, yCenter);
      GLDraw::endPrimitive();
}

void DxCanvas::drawFilledCircle(int x, int y, int rad, D3DCOLOR color, int numSegments){
      if (numSegments <= 0){
            numSegments = rad*2;
            if (numSegments < 2)
                  numSegments = 4;
            if (numSegments > 2000)
                  numSegments = 2000;
      }

      GLDraw::setColor(color);
      Render::setTexture(0);
      GLDraw::beginPrimitive(D3DPT_TRIANGLEFAN);
      float xCenter = (float)x - 0.5f, yCenter = (float)y - 0.5f, radius = (float)rad;
      GLDraw::vertex2f(xCenter, yCenter);
      GLDraw::vertex2f(xCenter + radius, yCenter);
      float add = pi*2.0f/(float)numSegments;
      float angle = add;
      for (int i = 1; i < numSegments; i++, angle+= add)
            GLDraw::vertex2f(xCenter + cos(angle)*radius, yCenter + sin(angle)*radius);
      GLDraw::vertex2f(xCenter + radius, yCenter);      
      GLDraw::endPrimitive();
}

void DxCanvas::drawTriangle(int x0,int y0,int x1,int y1,int x2,int y2, D3DCOLOR color){
      GLDraw::setColor(color);
      Render::setTexture(0);
      //GLDraw::beginPrimitive(D3DPT_TRIANGLELIST);
      GLDraw::beginPrimitive(D3DPT_LINESTRIP);
      GLDraw::vertex2f((float)x0, (float)y0);
      GLDraw::vertex2f((float)x1, (float)y1);
      GLDraw::vertex2f((float)x2, (float)y2);
      GLDraw::vertex2f((float)x0, (float)y0);
      GLDraw::endPrimitive();
}

Which I would guess is basic DX9 rendering. But it sems to be taking a heavy blow on FPS like stated. Does anyone have any ideas how to optimize this above coding with DX or the below coding (printText/DrawString etc is basic DX output as well for text can attach if needed). Any suggestions to make the coding a bit more happy.

Right now there are several objects in one area, so it can take a very large hit to draw these! I was thinking of trying to split rendering each frame, but thats a last option (Aka if I give 8 frames to loop, and theres 200 objects, I want it too render 25 each frame and keep looping etc. Kinda to 'even' the load).
int SF_DisplayEngine::DrawMapConsoleObject(int i){
	if(!map)
		return 0;

	if(!isShip && !isPlanet && !isColony)
		return 0;

	if(!visible /*&& !isAWarpingShip*/)
		return 0;

	int zoom = strategicZoom;
	int scale = strategicScale;

	int addx = map->buffer->x;
	int addy = map->buffer->y;

	int cx = sprite->cx/scale;
	int cy = sprite->cy/scale;

	if(cx < 1) cx = 1;
	if(cy < 1) cy = 1;

	if(isPlanet){
		cx *= 2;
		cy *= 2;
	}

	if(isShip){
		cx = 9;
		cy = 9;
	}

	if(isColony){
		cx = 7;
		cy = 7;
	}

	long x = map->buffer->width/2 +(gx - x0)/zoom - cx/2;
	long y = map->buffer->height/2 -(gy - y0)/zoom - cy/2;

	long x0 = x + cx/2;
	long y0 = y + cy/2;

	long nx = map->buffer->width/2 +(ngx - x0)/zoom - cx/2;
	long ny = map->buffer->height/2 -(ngy - y0)/zoom - cy/2;

	int onScr =(x > -cx) &&(x < map->buffer->width) &&
		(y > -cy) &&(y < map->buffer->height);

	bool dontDrawObject = false;
	if(zoom >= 64 &&(isShip || isColony) && i != ge->localSlot)
		dontDrawObject = true;

	dxbb->setClipRect(map->buffer->x + 10, map->buffer->y + 10, map->buffer->x + map->buffer->width - 10, map->buffer->y + map->buffer->height - 10);

	char *text = 0;
	if(onScr && !dontDrawObject){
		ulong scolor = color|0xFF000000;
		if(i == ge->localSlot)
			scolor = 0xFFFFFFFF;

		if(isPlanet)
			map->buffer->drawFilledCircle(x0 + addx,y0 + addy,cy/2,color);
		else if(isShip)
			map->buffer->drawTriangle(x0-5+addx,y0+5+addy,x0+5+addx,y0+5+addy,x0+addx,y0-5+addy,scolor);
		else if(isColony && !colonizedPlanet)
			map->buffer->drawRect(x0-3+addx,y0-3+addy,x0+4+addx,y0+4+addy,color);

		if(isSun)
			text =((PlanetClass *)(game->objectList[i]))->name;
		if(isPlanet && !isMinor && zoom < 128)
			text =((PlanetClass *)(game->objectList[i]))->name;
		if(isMinor && zoom < 32)
			text =((PlanetClass *)(game->objectList[i]))->name;
		if(isShip && zoom < 32)
			text = game->player[game->ship[i].playerIndex].shipName;

		if(visible && isTargetted && ge->itime % (10*SF_MULTIPLIER) < (5*SF_MULTIPLIER))
			map->buffer->drawRect(x-2+addx,y-2+addy,x+cx+2+addx,y+cy+2+addy,0xFFFF0000);

		if(mainFont && mainFont->spr){
			if(text)
				mainFont->DrawString(map->buffer,text,x+addx,y+cy+mainFont->cy+addy,race);
		}
		else{
			if(text)
				map->font->printText(text,x+addx,y+cy+addy,color);
		}
	}/* onScreen */

	dxbb->resetClipRect();

	return 0;
}

Open in new window

0
Valleriani
Asked:
Valleriani
2 Solutions
 
ambienceCommented:
I think the main issue could be the creation of a vertex buffer per every primitive drawn. I'm not familiar with what GLDraw::vertex2f does, but apparently it looks like adding vertex to the vertex buffer started by GLDraw::beginPrimitive?
An index buffer is an obvious improvement then.Moreover, if your world is just 2D, using bitmaps for even triangles and circles would reduce the computation because those would just be blit to the screen.
0
 
George TokasCommented:
For as far as I can see this is 2D application...
3D uses other ways...
Also GLDraw does that mean OpenGL draw??
If yes then this is a mix I never saw before....
Zooming and clipping is using at 2D drawing and in this case ambience is right...
3D drawing requires a rendering of the objects and setting a "point of view" (a camera if you like) to finally display the objects based on the view frustum...
There is a set of wrapper classes about all of those at http://www.gtokas.com for use with C++ Builder.
You can get some idea from there...

George Tokas.
0
 
VallerianiAuthor Commented:
Ended up using a basic bitmap for it and it sped up almost 6x :)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now