Drawing 2D Splines

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Post Reply
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Drawing 2D Splines

Post by slavik262 »

Would it be difficult to have drawing functions in IVideoDriver that draw 2D splines? I'm thinking something along the lines of GDI+. Spline support would really allow for scalable, vector-based GUI elements and would also be useful for HUD elements in games.
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

Well essentially you would just solve the given equation(s) at a given step rate and output a list of lines to draw. You could vary the step rate based on how detailed you want the line to look and everything. That's how most people handle drawing any arc-based objects.
TheQuestion = 2B || !2B
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

Halifax wrote:Well essentially you would just solve the given equation(s) at a given step rate and output a list of lines to draw. You could vary the step rate based on how detailed you want the line to look and everything. That's how most people handle drawing any arc-based objects.
I'll have to take this up as a project myself when I have the spare time. I just need to figure out a few things first:
  • How the implementations for IVideoDriver draw lines in the first place, and
  • What the "given equation(s)" are. I don't have much experience with the math behind splines, although I assume it involves a bit of calculus.
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

To draw lines you would use IVideoDriver::draw3DLine. Now when it comes to what equations you want to use there are a number of ways you can go about it. Have a look at Bezier curves and Cubic Hermite Splines. You can eventually venture into further areas, but those are the most widely used representation.
TheQuestion = 2B || !2B
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Better use a meshbuffer with EPT_LINES or even better LINE_STRIP, because that's by far faster than drawing each segment separately.
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

So you're suggesting I use a CMeshBuffer combined with drawVertexPrimitiveList()? If I were to do that, how would I transform the 3-d coordinates to the 2-d screen space?

I'm sorry if these are stupid questions; I'm relatively new to 3-d graphics programming. I understand the concepts, but I'm still working on grasping implementation in some areas.
zillion42
Posts: 324
Joined: Wed Aug 29, 2007 12:32 am
Location: Hamburg, Germany

Post by zillion42 »

hi,

there is this CIndexedPrimitiveNode, made by Pellaeon. I also use it. Check out this thread

http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=34481

and copy the cpp and header file to your project. I made a method that uses the node to draw lines, and all it needs is an array of core::vector3df for the points on the line. You can set colour and thickness aswell, hope it helps... ah I forgot I also added some code to segment the line, needed that because large lines wont draw because of the 16bit indices limitation, I noticed there is little gaps in the lines though. Hope it helps anyway:

Code: Select all

scene::ISceneNode* makeLine(core::array<core::vector3df> positions, video::SColor color, f32 thickness)
{
	scene::ISceneNode* returnNode = smgr->addEmptySceneNode();

	u32 originalSize = 2000;
	u32 SegmentsNeeded = core::ceil32( ((f32)positions.size()/(f32)originalSize) );

	u32 SegmentSize = 2000;
	u32 finishedSegments = 2000;

	if(SegmentsNeeded == 1)
	{
		SegmentSize = positions.size();
		finishedSegments = positions.size();
	}

	for(u32 i=0; i<SegmentsNeeded; i++)
	{
		scene::SMeshBuffer *segmentBuffer = new scene::SMeshBuffer();

		for(u32 j=0; j<SegmentSize; j++)
		{
			segmentBuffer->Indices.push_back(j);

			if(j !=0 && j != positions.size() - 1)
				segmentBuffer->Indices.push_back(j);

			segmentBuffer->Vertices.push_back(video::S3DVertex(
				positions[i*originalSize+j].X,
				positions[i*originalSize+j].Y,
				positions[i*originalSize+j].Z,
				1,1,1,
				color,
				1,1));
		}

		segmentBuffer->getMaterial().Thickness = thickness;

		CIndexedPrimitiveNode* segNode = new CIndexedPrimitiveNode(returnNode,smgr,-1,segmentBuffer,
			segmentBuffer->Indices.size()/2,
			scene::EPT_LINES);

		segNode->setMaterialFlag(video::EMF_LIGHTING, false);
		segNode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);

		if(finishedSegments + 2000 < positions.size())
		{
			finishedSegments += 2000;
		}
		else
		{
			u32 remainder = positions.size() - finishedSegments;
			SegmentSize = remainder;
		}
	}

	return returnNode;
}
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

I follow all of that, but say I'm making a function "draw2DSpline" that takes an array of screen-coordinate vectors of the form vector2d<s32> (in pixels just like all the other 2-d drawing code works). How would I convert those to 3-d coordinates so that my curve falls in the right place?
Post Reply