http://irrlicht.sourceforge.net/forum/v ... =9&t=33060
The graph element I've created has some different features than the promoted graph (although I imagine Sudi's trumps mine).
The thought in its design is to make it so you can easily embed it in other GUI elements (even stripping it of most features to the point where it doesn't even look like it exists! XD ) but offering conveniences. I tried to make it as easy as possible to use.
>> It possess a resizable graph window. i.e. I can set it to display points from x=-10 to x=23.45 and y=-6 to y=-3 and it will do that. I can also scale the graph's x or y axis by a percentage.
>> As for drawing the points: It does as you would expect: You simply give it an x and y value in its coordinate system (via drawOnGraph(vector2df,SColor=black)), and it draws the point on the graph in irrlicht's coordinate system. (And yes, the y-axis get's flipped.) I plan on adding the ability to add points based on polar-coordinates. The order of addition of points to the graph is irrelevant, as it should be. The graph can also be conveniently cleared, as it should be.
>> Optional x or y axis and x or y axis tick marks. Tick mark spacing is optional. It can also draw lines instead of ticks, effectively drawing a grid.
>> Custom colors for everything - axis and points.
>> Optional background.
>> Convenience of an instance of my incrementor class, Inc, posted here (http://irrlicht.sourceforge.net/forum/v ... 41#p277141) for traversing the graph (x or y direction). (I'll show you an example in a second.)
>> All of this is can be serialized and deserialized, btw. I also would have made a GUIElementFactory but I wasn't sure what way you guys wanted that implemented.
HEADS UP: The simple implementation requires my Incrementor class and my Range class (the latter for only some features, so you can scratch it if you want). Once again, both can be found here:
http://irrlicht.sourceforge.net/forum/v ... 41#p277141
I intend to put all of this stuff in a zip file and upload it onto my website for your convenience, but I'll do that when it's not so late at night.
My website: http://chronologicaldot.web44.net
IGraph2D.h
(abstract class)
Code: Select all
/*
Simple Graph
(c) Nicolaus Anderson
Created Jan 7, 2013
License: Same terms as irrlicht
*/
#include <irrlicht.h>
#ifndef _IGRAPH2D_
#define _IGRAPH2D_
namespace irr
{
namespace gui
{
//! Class Graph 2D
/*
Purpose: To plot 2D math functions.
*/
class IGraph2D : public IGUIElement
{
public:
IGraph2D( IGUIEnvironment* envir, IGUIElement* parent, irr::s32 id, irr::core::recti& rectangle )
: IGUIElement( EGUIET_ELEMENT, envir, parent, id, rectangle )
{
}
~IGraph2D()
{
}
//! Set graph size
/* NOT the same as scaling.
This function changes the ranges of values in the graph without changing
the size of the graph as a GUI element.
*/
virtual void setGraphSize( irr::core::rectf& size )=0;
//! Set graph size along one dimension
/* NOT the same as scaling.
This function changes the ranges of values of ONE AXIS in the graph without
changing the size of the graph as a GUI element.
\param size - New axis min or max
\param isMax - If the value given is for the maximum
*/
virtual void setGraphSizeX( irr::f32 size, bool isMax=true )=0;
virtual void setGraphSizeY( irr::f32 size, bool isMax=true )=0;
//! Set scale
/* Changes the scale of the ranges of values in the graph without changing
the size of the graph itself.
NOTE: Since this is a scaling, the rectangle being passed in should be the
percentage change (i.e. multiplier for the current values). */
virtual void setScale( irr::core::rectf& scale )=0;
//! Get graph size
/* Returns the size of the graph. */
virtual irr::core::rectf getGraphSize()=0;
//! Draw
/* Draws the GUI element. */
virtual void draw()=0;
//! Clear graph
/* Erases everything in the graph. */
virtual void clearGraph()=0;
//-------------------------------
// Drawing area functions / Spaz
//! Set point color
/* Sets the color of the points to be displayed. */
virtual void setPointColor( irr::video::SColor color )=0;
//! Set x-axis color
/* Sets the color that will be used in drawing the line representing
the x-axis. */
virtual void setXAxisColor( irr::video::SColor color )=0;
//! Set y-axis color
/* Sets the color that will be used in drawing the line representing
the y-axis. */
virtual void setYAxisColor( irr::video::SColor color )=0;
//-----------------------------
//! Serialize attributes
virtual void serializeAttributes(
irr::io::IAttributes* out,
irr::io::SAttributeReadWriteOptions* options=0
)=0;
//! Deserialize attributes
virtual void deserializeAttributes(
irr::io::IAttributes* in,
irr::io::SAttributeReadWriteOptions* options=0
)=0;
};
} // end namespace gui
} // end namespace irr
#endif // define _IGRAPH2D_
(header class of the simple implementation)
Code: Select all
/*
Simple Graph
(c) Nicolaus Anderson
Created Jan 7, 2013
License: Same terms as irrlicht
*/
#include "IGraph2D.h"
#include <Range.h>
#include <IncrementorT.h>
#ifndef __SIMPLEGRAPH2D_H__
#define __SIMPLEGRAPH2D_H__
namespace irr
{
namespace gui
{
//! Class Graph 2D
/*
Purpose: To plot 2D math functions.
*/
class SGraph2D : public IGraph2D
{
//! Graph Image
/* The actual graph itself: a chain of points that need to be
drawn. */
irr::core::array<irr::video::S3DVertex> graphImage;
//! Graph window
/* This is the range of values that the graphed values are forced
to fit into. It is a user-set range. */
irr::core::rectf window;
//! Markers (e.g. tick marks)
bool UseMarkers; // whether to use markers or not
bool UseTicks; // whether to use ticks or lines (if markers are in use)
irr::f32 markXgap; // spacing between markings on the x-axis
irr::f32 markYgap; // spacing between markings on the y-axis
bool showXaxisMarks; // whether the x-axis marks should be displayed
bool showYaxisMarks; // whether the y-axis marks should be displayed
//! Axis displaying flags
bool showXaxis;
bool showYaxis;
//! Colors
// Background color
irr::video::SColor background_color;
bool hasBackground;
// Axis colors
irr::video::SColor xaxis_color;
irr::video::SColor yaxis_color;
// Point color
irr::video::SColor point_color;
// Tick marks / lines perpendicular to the axis
irr::video::SColor xmark_color;
irr::video::SColor ymark_color;
// The video driver for drawing on screen
irr::video::IVideoDriver* viddriver;
public:
//! Constructor
SGraph2D(
// GUI element parameters
IGUIEnvironment* envir,
IGUIElement* parent,
irr::s32 id,
irr::core::recti& rectangle,
// Graph parameters
irr::core::rectf& graphWindow,
bool marks = false,
bool ticks = false
)
: IGraph2D( envir, parent, id, rectangle ),
window( graphWindow ),
UseMarkers( marks ),
showXaxisMarks( marks ),
showYaxisMarks( marks ),
UseTicks( ticks ),
markXgap(1.0f),
markYgap(1.0f),
showXaxis( true ),
showYaxis( true ),
background_color( irr::video::SColor( 255, 0, 0, 0 ) ),
hasBackground( true ),
xaxis_color( irr::video::SColor( 255, 0, 125, 0 ) ),
yaxis_color( irr::video::SColor( 255, 0, 125, 0 ) ),
point_color( irr::video::SColor( 255, 255, 0, 0 ) ),
xmark_color( irr::video::SColor( 255, 0, 125, 0 ) ),
ymark_color( irr::video::SColor( 255, 0, 125, 0 ) )
{
viddriver = Environment->getVideoDriver();
}
//! Destructor
~SGraph2D()
{
}
//! Set graph size
/* NOT the same as scaling.
This function changes the ranges of values in the graph without changing
the size of the graph as a GUI element.
*/
virtual void setGraphSize( irr::core::rectf& size );
//! Set graph size along one dimension
/* NOT the same as scaling.
This function changes the ranges of values of ONE AXIS in the graph without
changing the size of the graph as a GUI element.
\param size - New axis min or max
\param isMax - If the value given is for the maximum
*/
virtual void setGraphSizeX( irr::f32 size, bool isMax=true );
virtual void setGraphSizeY( irr::f32 size, bool isMax=true );
//! Set scale
/* Changes the scale of the ranges of values in the graph without changing
the size of the graph itself.
NOTE: Since this is a scaling, the rectangle being passed in should be the
percentage change (i.e. multiplier for the current values). */
virtual void setScale( irr::core::rectf& scale );
//! Reallocate Memory for Graph
/* In order to allow the graph to draw points quickly, this function is
available to reallocate storage space for the data points.
Old data points will not be destroyed and thus must be overwritten. */
void ReallocateGraphSpace();
//! Get graph size
/* Returns the size of the graph. */
virtual irr::core::rectf getGraphSize();
// Graphing region
//! Get Graph X-Axis Range
/* Returns the range of values that will be visible when the graph is
drawn. */
Range<irr::f32> getXAxisRange();
//! Get Graph Y-Axis Range
/* Returns the range of values that will be visible when the graph is
drawn. */
Range<irr::f32> getYAxisRange();
//! Get Iterable Range for X-Axis
/* Returns an incrementor whose range spans the visible x-axis of the
graph, whose step yields one point per pixel acroos the screen, and whose
starting position is the one necessary for all points drawn with this as
a guide to cross the entire graph window. */
Inc<irr::f32> getIterableXRange();
//! Get Iterable Range for Y-Axis
/* Returns an incrementor whose range spans the visible y-axis of the
graph, whose step yields one point per pixel acroos the screen, and whose
starting position is the one necessary for all points drawn with this as
a guide to cross the entire graph window. */
Inc<irr::f32> getIterableYRange();
// Other ----
//! Set step size
/* Sets the spacing between tick marks (if any). */
void markerSpacingX( irr::f32 gap=1.0f );
void markerSpacingY( irr::f32 gap=1.0f );
//! Draw
/* Draws the GUI element. */
virtual void draw();
//! Clear graph
/* Erases everything in the graph. */
virtual void clearGraph();
//-------------------------------
// Drawing area functions / Spaz
//! Set if there is a background
void useBackground( bool use=true );
//! Set background color
/* Sets the color to be displayed behind the graph. */
void setBackgroundColor( irr::video::SColor color );
//! Set point color
/* Sets the color of the points to be displayed. */
virtual void setPointColor( irr::video::SColor color );
//! Set x-axis color
/* Sets the color that will be used in drawing the line representing
the x-axis. */
virtual void setXAxisColor( irr::video::SColor color );
//! Set y-axis color
/* Sets the color that will be used in drawing the line representing
the y-axis. */
virtual void setYAxisColor( irr::video::SColor color );
//! Show x-axis
/* Shows the x-xais if desired. */
void setShowXAxis( bool show=true );
//! Show y-axis
/* Shows the y-axis if desired. */
void setShowYAxis( bool show=true );
//----- Tick marks vs lines
/* Either tick marks (three pixels crossing the line) or perpendicular
lines can be used to show the step size. */
//! Set to use tick marks instead of lines
void useTicks();
//! Set to use perpendicular lines instead of tick marks
void useLines();
//! Set to use no markers
void useNoMarkers();
//! Set to show the x-axis markers
void showXAxisMarkers( bool show=true );
//! Set to show the y-axis markers
void showYAxisMarkers( bool show=true );
//! Set x-axis tick color / perpendicular line color
void setXAxisMarkerColor( irr::video::SColor color );
//! Set y-axis tick color / perpendicular line color
void setYAxisMarkerColor( irr::video::SColor color );
//-----------------------------
//! Serialize attributes
virtual void serializeAttributes(
irr::io::IAttributes* out,
irr::io::SAttributeReadWriteOptions* options=0
);
//! Deserialize attributes
virtual void deserializeAttributes(
irr::io::IAttributes* in,
irr::io::SAttributeReadWriteOptions* options=0
);
// ------------ Drawing functions ------------
//! Draw to the graph
/* Draws on the graph a single point whose coordinates are preppared
according to the graph's coordinate system.
You should use this function for standard operations. */
void drawOnGraph(
irr::core::vector2df point,
irr::video::SColor color=irr::video::SColor(255,0,0,0)
);
//! Draw to the graph
/* Draws on the graph a single point whose coordinates are preppared for
the AbsoluteRect and need merely be shifted. */
void drawRawPoint(
irr::core::vector2df point,
irr::video::SColor color=irr::video::SColor(255,0,0,0)
);
protected:
//! Draw directly to the GUI element
/* Draws to the GUI element by handling the relative offset
of the GUI element from the upperleft corner of the screen. */
void drawToGUI( irr::core::vector2di point, irr::video::SColor color );
void drawToGUI( irr::core::line2df line, irr::video::SColor color );
};
} // end namespace gui
} // end namespace irr
#endif // define __SIMPLEGRAPH2D_H__
(cpp file of the simple implementation)
Code: Select all
/*
Simple Graph
(c) Nicolaus Anderson
Created Jan 7, 2013
License: Same terms as irrlicht
*/
#include "SGraph2D.h"
#ifndef __SIMPLEGRAPH2D_CPP__
#define __SIMPLEGRAPH2D_CPP__
void irr::gui::SGraph2D::setGraphSize( irr::core::rectf& size )
{
window = size;
ReallocateGraphSpace();
}
void irr::gui::SGraph2D::setGraphSizeX( irr::f32 size, bool isMax )
{
if ( isMax )
{
window.LowerRightCorner.X = size;
} else {
window.UpperLeftCorner.X = size;
}
ReallocateGraphSpace();
}
void irr::gui::SGraph2D::setGraphSizeY( irr::f32 size, bool isMax )
{
if ( isMax )
{
window.UpperLeftCorner.Y = size;
} else {
window.LowerRightCorner.Y = size;
}
ReallocateGraphSpace();
}
void irr::gui::SGraph2D::setScale( irr::core::rectf& scale )
{
window.UpperLeftCorner.X *= scale.UpperLeftCorner.X;
window.UpperLeftCorner.Y *= scale.UpperLeftCorner.Y;
window.LowerRightCorner.X *= scale.LowerRightCorner.X;
window.LowerRightCorner.Y *= scale.LowerRightCorner.Y;
window.repair();
ReallocateGraphSpace();
}
void irr::gui::SGraph2D::ReallocateGraphSpace()
{
graphImage.reallocate(
(irr::u32)AbsoluteRect.getWidth(),
false
);
}
irr::core::rectf irr::gui::SGraph2D::getGraphSize()
{
return window;
}
Range<irr::f32> irr::gui::SGraph2D::getXAxisRange()
{
return Range<irr::f32>(
window.UpperLeftCorner.X,
window.LowerRightCorner.X
);
}
Range<irr::f32> irr::gui::SGraph2D::getYAxisRange()
{
return Range<irr::f32>(
window.UpperLeftCorner.Y,
window.LowerRightCorner.Y
);
}
Inc<irr::f32> irr::gui::SGraph2D::getIterableXRange()
{
Inc<irr::f32> inc(CYC_REPEAT);
inc.setRange( getXAxisRange() );
inc.setStep( window.getWidth() / ((irr::f32)AbsoluteRect.getWidth()) );
inc.restart();
return inc;
}
Inc<irr::f32> irr::gui::SGraph2D::getIterableYRange()
{
Inc<irr::f32> inc(CYC_REPEAT);
inc.setRange( getYAxisRange() );
inc.setStep( window.getHeight() / ((irr::f32)AbsoluteRect.getHeight()) );
inc.restart();
return inc;
}
void irr::gui::SGraph2D::markerSpacingX( irr::f32 gap )
{
markXgap = gap;
}
void irr::gui::SGraph2D::markerSpacingY( irr::f32 gap )
{
markYgap = gap;
}
void irr::gui::SGraph2D::draw()
{
// Don't bother doing anything if this isn't visible
if ( !IsVisible || AbsoluteRect.getArea() == 0 || window.getArea() == 0.0f )
return;
// variables...
irr::core::vector2di point; /* point to be drawn on screen representing
a point from the MathFunc */
/* Marker offset
- used to ensure the markers are drawn from the center outward. */
Inc<irr::f32> markerIter; /* no wrapping because we want
out-of-bounds checking */
// Marker line - drawn on the GUI graph screen
irr::core::line2df marker;
// operations...
// Draw the background if there is one
if ( hasBackground )
{
viddriver->draw2DRectangle(
background_color,
AbsoluteRect,
&AbsoluteClippingRect
);
}
// Draw the axis if desired
if ( showXaxis )
{
drawToGUI(
irr::core::line2df(
window.UpperLeftCorner.X,
0.0f,
window.LowerRightCorner.X,
0.0f
),
xaxis_color
);
}
if ( showYaxis )
{
drawToGUI(
irr::core::line2df(
0.0f,
window.UpperLeftCorner.Y,
0.0f,
window.LowerRightCorner.Y
),
yaxis_color
);
}
// Draw the markers/lines if desired
if ( UseMarkers )
{
// Y-axis
if ( showYaxisMarks )
{
/* Set the offset for making the lines appear to be drawn
from the center outward */
markerIter.setMin( window.UpperLeftCorner.Y );
markerIter.setMax( window.LowerRightCorner.Y );
markerIter.setStep( markYgap );
markerIter.setVal( 0.0f ); // start in the center
// Set up the marker line
// Left side of the line
if ( UseTicks )
marker.start.X = -window.getWidth() / 20.0f; // for 10% window width
else
marker.start.X = window.UpperLeftCorner.X;
// Right side of the line
if ( UseTicks )
marker.end.X = window.getWidth() / 20.0f; // for 10% window width
else
marker.end.X = window.LowerRightCorner.X;
// Draw each marker
while ( !++markerIter ) // go until past the max
{
// Assign the position to the line to draw
marker.start.Y = marker.end.Y = markerIter.Val();
// Draw the marker to the GUI
drawToGUI( marker, ymark_color );
}
// Restart at the center
markerIter = 0.0f;
// Draw each marker
while ( !--markerIter ) // go until past the min
{
// Assign the position to the line to draw
marker.start.Y = markerIter.Val();
marker.end.Y = markerIter.Val();
// Draw the marker to the GUI
drawToGUI( marker, ymark_color );
}
}
// X-axis
if ( showXaxisMarks )
{
/* Set the offset for making the lines appear to be drawn
from the center outward */
markerIter.setMin( window.UpperLeftCorner.X );
markerIter.setMax( window.LowerRightCorner.X );
markerIter.setStep( markXgap );
markerIter.setVal( 0.0f ); // start in the center
// Set up the marker line
// Top of the line - Below the x-axis in terms of irrlicht drawing
if ( UseTicks )
marker.start.Y = window.getHeight() / 20.0f; // for 10% window height
else
marker.start.Y = window.UpperLeftCorner.Y;
// Bottom of the line - Above the x-axis in terms of irrlicht drawing
if ( UseTicks )
marker.end.Y = -window.getHeight() / 20.0f; // for 10% window height
else
marker.end.Y = window.LowerRightCorner.Y;
// Draw each marker
while ( !++markerIter ) // go until past the max
{
// Assign the position to the line to draw
marker.start.X = marker.end.X = markerIter.Val();
// Draw the marker to the GUI
drawToGUI( marker, xmark_color );
}
// Restart at the center
markerIter = 0.0f;
// Draw each marker
while ( !--markerIter ) // go until past the min
{
// Assign the position to the line to draw
marker.start.X = markerIter.Val();
marker.end.X = markerIter.Val();
// Draw the marker to the GUI
drawToGUI( marker, xmark_color );
}
}
}
// Display each points on screen
for (
irr::s32 pt = 0;
pt < (irr::s32)graphImage.size();
pt++
)
{
/* Note that when drawing the graph in the GUI element,
we need to shift their stored values because the bounds of the
graph window are independent of the actual GUI element size. */
/*
point.X = (irr::s32)(graphImage[pt].Pos.X - window.UpperLeftCorner.X)
* AbsoluteRect.getWidth();
*/
point.X = (irr::s32)graphImage[pt].Pos.X;
point.Y = (irr::s32)graphImage[pt].Pos.Y;
/* Note the y-axis value is negative in order have it drawn
in the orientation the GUI environment is drawn. */
drawToGUI( point, graphImage[pt].Color );
}
}
void irr::gui::SGraph2D::clearGraph()
{
graphImage.clear();
}
void irr::gui::SGraph2D::useBackground( bool use )
{
hasBackground = use;
}
void irr::gui::SGraph2D::setBackgroundColor( irr::video::SColor color )
{
background_color = color;
}
void irr::gui::SGraph2D::setPointColor( irr::video::SColor color )
{
point_color = color;
}
void irr::gui::SGraph2D::setXAxisColor( irr::video::SColor color )
{
xaxis_color = color;
}
void irr::gui::SGraph2D::setYAxisColor( irr::video::SColor color )
{
yaxis_color = color;
}
void irr::gui::SGraph2D::setShowXAxis( bool show )
{
showXaxis = show;
}
void irr::gui::SGraph2D::setShowYAxis( bool show )
{
showYaxis = show;
}
void irr::gui::SGraph2D::useTicks()
{
UseMarkers = true;
UseTicks = true;
showXaxisMarks = true;
showYaxisMarks = true;
}
void irr::gui::SGraph2D::useLines()
{
UseMarkers = true;
UseTicks = false;
showXaxisMarks = true;
showYaxisMarks = true;
}
void irr::gui::SGraph2D::useNoMarkers()
{
UseMarkers = false;
}
void irr::gui::SGraph2D::showXAxisMarkers( bool show )
{
showXaxisMarks = show;
if (show) UseMarkers = true;
}
void irr::gui::SGraph2D::showYAxisMarkers( bool show )
{
showYaxisMarks = show;
if (show) UseMarkers = true;
}
void irr::gui::SGraph2D::setXAxisMarkerColor( irr::video::SColor color )
{
xmark_color = color;
}
void irr::gui::SGraph2D::setYAxisMarkerColor( irr::video::SColor color )
{
ymark_color = color;
}
void irr::gui::SGraph2D::serializeAttributes(
irr::io::IAttributes *out,
irr::io::SAttributeReadWriteOptions *options
)
{
irr::core::recti win;
win.UpperLeftCorner.X = (irr::s32)(window.UpperLeftCorner.X);
win.UpperLeftCorner.Y = (irr::s32)(window.UpperLeftCorner.Y);
win.LowerRightCorner.X = (irr::s32)(window.LowerRightCorner.X);
win.LowerRightCorner.Y = (irr::s32)(window.LowerRightCorner.Y);
out->addRect( "Window", win );
out->addBool( "FillBackground", hasBackground );
out->addColor( "BGColor", background_color );
out->addColor( "XAxisColor", xaxis_color );
out->addColor( "YAxisColor", yaxis_color );
out->addColor( "PointColor", point_color );
out->addColor( "XAxisTickColor", xmark_color );
out->addColor( "YAxisTickColor", ymark_color );
out->addBool( "UseMarkers", UseMarkers );
out->addBool( "UseTicks", UseTicks );
out->addBool( "ShowXAxis", showXaxis );
out->addBool( "ShowYAxis", showYaxis );
}
void irr::gui::SGraph2D::deserializeAttributes(
irr::io::IAttributes *in,
irr::io::SAttributeReadWriteOptions *options
)
{
irr::core::recti win = in->getAttributeAsRect( "Window" );
window.UpperLeftCorner.X = (irr::f32)(win.UpperLeftCorner.X);
window.UpperLeftCorner.Y = (irr::f32)(win.UpperLeftCorner.Y);
window.LowerRightCorner.X = (irr::f32)(win.LowerRightCorner.X);
window.LowerRightCorner.Y = (irr::f32)(win.LowerRightCorner.Y);
hasBackground = in->getAttributeAsBool( "FillBackground" );
background_color = in->getAttributeAsColor( "BGColor" );
xaxis_color = in->getAttributeAsColor( "XAxisColor" );
yaxis_color = in->getAttributeAsColor( "YAxisColor" );
point_color = in->getAttributeAsColor( "PointColor" );
xmark_color = in->getAttributeAsColor( "XAxisTickColor" );
ymark_color = in->getAttributeAsColor( "YAxisTickColor" );
UseMarkers = in->getAttributeAsBool( "UseMarkers" );
UseTicks = in->getAttributeAsBool( "UseTicks" );
showXaxis = in->getAttributeAsBool( "ShowXAxis" );
showYaxis = in->getAttributeAsBool( "ShowYAxis" );
}
void irr::gui::SGraph2D::drawOnGraph(
irr::core::vector2df point, irr::video::SColor color
)
{
// Shift the origin to the corner
point.X -= window.UpperLeftCorner.X;
point.Y -= window.UpperLeftCorner.Y;
// Convert to the actual GUI window's coordinate system
point.X *= ((irr::f32)AbsoluteRect.getWidth()) / window.getWidth();
point.Y *= ((irr::f32)AbsoluteRect.getHeight()) / window.getHeight();
// Save
graphImage.push_back(
irr::video::S3DVertex( point.X, point.Y, 0,0,0,0, color, 0,0)
);
}
void irr::gui::SGraph2D::drawRawPoint(
irr::core::vector2df point,
irr::video::SColor color
)
{
// Shift the origin to the corner
point.X -= window.UpperLeftCorner.X
// conversion of shift to GUI element size
* ((irr::f32)AbsoluteRect.getWidth()) / window.getWidth();
point.Y -= window.UpperLeftCorner.Y
// conversion of shift to GUI element size
* ((irr::f32)AbsoluteRect.getHeight()) / window.getHeight();
// Save
graphImage.push_back(
irr::video::S3DVertex( point.X, point.Y, 0,0,0,0, color, 0,0)
);
}
void irr::gui::SGraph2D::drawToGUI(
irr::core::vector2di point,
irr::video::SColor color
)
{
// Flip for drawing on the GUI
point.Y = AbsoluteRect.getHeight() - point.Y;
/* This function has been passed a value that is already prepared to
be drawn to screen and simply needs to be offset. */
point.X += AbsoluteRect.UpperLeftCorner.X;
point.Y += AbsoluteRect.UpperLeftCorner.Y;
// Do nothing if the window isn't even visible
if ( window.getArea() == 0.0f )
return;
// Draw the point as a pixel - might be very small and hard to see
/* - Drawn faster than a polygon and may create a smooth line (if MathFunc
returns values of a smooth function) */
viddriver->drawPixel( point.X, point.Y, point_color );
// Attempt to draw the point as a polygon (to make it more visible)
/*
viddriver->draw2DPolygon(
point, // position
1.5f, // radius
point_color, // color
4 // roundness of the point
);
*/
}
void irr::gui::SGraph2D::drawToGUI(
irr::core::line2df line,
irr::video::SColor color
)
{
// Do nothing if the window isn't even visible
// - saves time and prevents divide-by-zero errors
if ( window.getArea() == 0.0f )
return;
/* This function has been passed a value that needs to be prepared
to fit in the window in addition to it being offset. */
// Line that will be drawn - initialized to begin within the GUI element
irr::core::line2di drawline(
AbsoluteRect.UpperLeftCorner.X,
AbsoluteRect.UpperLeftCorner.Y,
AbsoluteRect.UpperLeftCorner.X,
AbsoluteRect.UpperLeftCorner.Y
);
/* Tranform the line to graph coordinates. */
line.start.X -= window.UpperLeftCorner.X;
line.start.Y -= window.UpperLeftCorner.Y;
line.end.X -= window.UpperLeftCorner.X;
line.end.Y -= window.UpperLeftCorner.Y;
// starting x
drawline.start.X += (irr::s32) ( line.start.X
* AbsoluteRect.getWidth() / window.getWidth() // position conversion
);
// starting y
drawline.start.Y += (irr::s32) ( line.start.Y
* AbsoluteRect.getHeight() / window.getHeight() // position conversion
);
// ending x
drawline.end.X += (irr::s32) ( line.end.X
* AbsoluteRect.getWidth() / window.getWidth() // position conversion
);
// ending y
drawline.end.Y += (irr::s32) ( line.end.Y
* AbsoluteRect.getHeight() / window.getHeight() // position conversion
);
// Draw the line
viddriver->draw2DLine( drawline.start, drawline.end, color );
}
#endif // define __SIMPLEGRAPH2D_CPP__
Example usage:
Code: Select all
#include <irrlicht.h>
//... then include library
using namespace irr;
using namespace gui;
void plotsine( SGraph2D* );
void plotsine( SGraph2D* win )
{
Inc<f32> dis;
core::vector2df pt;
dis.copy( win->getIterableXRange() );
dis.setStep( 1.0f/1000.0f );
do {
pt.X = dis.Val();
pt.Y = 10 * sin( dis.Val() );
win->drawOnGraph( pt, video::SColor(255,255,0,0) );
} while ( !++dis );
}
void main()
{
IrrlichtDevice* device = createDevice();
video::IVideoDriver* vid = device->getVideoDriver();
IGUIEnvironment* envir = device->getGUIEnvironment();
SGraph2D* graph = new SGraph2D(
envir, // GUI environment
envir->getRootGUIElement(), // parent
0, // id
irr::core::recti(0,0,600,400), // GUI element boundaries
irr::core::rectf( -10.0f, -10.0f, 20.0f, 10.0f ), // graph window
true, // use marks or lines?
true // use tick marks?
);
graph->setBackgroundColor( video::SColor(255,150,150,150) );
plotsine( graph );
graph->drop();
graph = 0;
while( device->run() )
{
vid->beginScene();
envir->drawAll();
vid->endScene();
}
device->drop();
}