Drawing 2D Splines
Drawing 2D Splines
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.
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: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.
- 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.
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
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.
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.
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:
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;
}