bullet3/examples/RenderingExamples/TimeSeriesCanvas.cpp

346 lines
9.6 KiB
C++
Raw Normal View History

#include "TimeSeriesCanvas.h"
#include "../CommonInterfaces/Common2dCanvasInterface.h"
#include "LinearMath/btAlignedObjectArray.h"
#include "TimeSeriesFontData.h"
#include "LinearMath/btVector3.h"
#include <stdio.h>
struct DataSource
{
unsigned char m_red;
unsigned char m_green;
unsigned char m_blue;
float m_lastValue;
bool m_hasLastValue;
DataSource()
:m_hasLastValue(false)
{
}
};
struct TimeSeriesInternalData
{
btAlignedObjectArray<DataSource> m_dataSources;
struct Common2dCanvasInterface* m_canvasInterface;
int m_canvasIndex;
int m_width;
int m_height;
float m_pixelsPerUnit;
float m_zero;
int m_timeTicks;
int m_ticksPerSecond;
float m_yScale;
int m_bar;
unsigned char m_backgroundRed;
unsigned char m_backgroundGreen;
unsigned char m_backgroundBlue;
unsigned char m_backgroundAlpha;
unsigned char m_textColorRed;
unsigned char m_textColorGreen;
unsigned char m_textColorBlue;
unsigned char m_textColorAlpha;
float getTime()
{
return m_timeTicks/(float)m_ticksPerSecond;
}
TimeSeriesInternalData(int width, int height)
:m_width(width),
m_height(height),
m_pixelsPerUnit(-100),
m_zero(height/2.0),
m_timeTicks(0),
m_ticksPerSecond(100),
m_yScale(1),
m_bar(0),
m_backgroundRed(255),
m_backgroundGreen(255),
m_backgroundBlue(255),
m_backgroundAlpha(255),
m_textColorRed(0),
m_textColorGreen(0),
m_textColorBlue(255),
m_textColorAlpha(255)
{
}
};
TimeSeriesCanvas::TimeSeriesCanvas(struct Common2dCanvasInterface* canvasInterface, int width, int height, const char* windowTitle)
{
btAssert(canvasInterface);
m_internalData = new TimeSeriesInternalData(width,height);
m_internalData->m_canvasInterface = canvasInterface;
m_internalData->m_canvasIndex = m_internalData->m_canvasInterface->createCanvas(windowTitle,m_internalData->m_width,m_internalData->m_height);
}
void TimeSeriesCanvas::addDataSource(const char* dataSourceLabel, unsigned char red,unsigned char green,unsigned char blue)
{
DataSource dataSource;
dataSource.m_red = red;
dataSource.m_green = green;
dataSource.m_blue = blue;
dataSource.m_lastValue = 0;
dataSource.m_hasLastValue = false;
if (dataSourceLabel)
{
int numSources = m_internalData->m_dataSources.size();
int row = numSources%3;
int column = numSources/3;
grapicalPrintf(dataSourceLabel, sTimeSeriesFontData, 50+200*column,m_internalData->m_height-48+row*16,
red, green,blue,255);
}
m_internalData->m_dataSources.push_back(dataSource);
}
void TimeSeriesCanvas::setupTimeSeries(float yScale, int ticksPerSecond, int startTime)
{
m_internalData->m_pixelsPerUnit = -(m_internalData->m_height/3.f)/yScale;
m_internalData->m_ticksPerSecond = ticksPerSecond;
m_internalData->m_yScale = yScale;
m_internalData->m_dataSources.clear();
for (int i=0;i<m_internalData->m_width;i++)
{
for (int j=0;j<m_internalData->m_height;j++)
{
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex,i,j,
m_internalData->m_backgroundRed,
m_internalData->m_backgroundGreen,
m_internalData->m_backgroundBlue,
m_internalData->m_backgroundAlpha);
}
}
float zeroPixelCoord = m_internalData->m_zero;
float pixelsPerUnit = m_internalData->m_pixelsPerUnit;
float yPos = zeroPixelCoord+pixelsPerUnit*yScale;
float yNeg = zeroPixelCoord+pixelsPerUnit*-yScale;
grapicalPrintf("0", sTimeSeriesFontData, 2,zeroPixelCoord,m_internalData->m_textColorRed,m_internalData->m_textColorGreen,m_internalData->m_textColorBlue,m_internalData->m_textColorAlpha);
char label[1024];
sprintf(label,"%2.1f", yScale);
grapicalPrintf(label, sTimeSeriesFontData, 2,yPos,m_internalData->m_textColorRed,m_internalData->m_textColorGreen,m_internalData->m_textColorBlue,m_internalData->m_textColorAlpha);
sprintf(label,"%2.1f", -yScale);
grapicalPrintf(label, sTimeSeriesFontData, 2,yNeg,m_internalData->m_textColorRed,m_internalData->m_textColorGreen,m_internalData->m_textColorBlue,m_internalData->m_textColorAlpha);
m_internalData->m_canvasInterface->refreshImageData(m_internalData->m_canvasIndex);
}
TimeSeriesCanvas::~TimeSeriesCanvas()
{
if (m_internalData->m_canvasInterface && m_internalData->m_canvasIndex>=0)
{
m_internalData->m_canvasInterface->destroyCanvas(m_internalData->m_canvasIndex);
}
delete m_internalData;
}
float TimeSeriesCanvas::getCurrentTime() const
{
return m_internalData->getTime();
}
void TimeSeriesCanvas::grapicalPrintf(const char* str, void* fontData, int rasterposx,int rasterposy, unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha)
{
unsigned char c;
int x=0;
int xx=0;
while ((c = (unsigned char) *str++)) {
x=xx;
unsigned char* fontPtr = (unsigned char*) fontData;
char ch = c-32;
int sx=ch%16;
int sy=ch/16;
for (int i=sx*16;i<(sx*16+16);i++)
{
int y=0;
for (int j=sy*16;j<(sy*16+16);j++)
{
unsigned char packedColor = (fontPtr[i*3+255*256*3-(256*j)*3]);
//float colorf = packedColor ? 0.f : 1.f;
float colorf = packedColor/255.f;// ? 0.f : 1.f;
btVector4 rgba(colorf,colorf,colorf,1.f);
if (colorf)
{
if ((rasterposx+x>=0) && (rasterposx+x < m_internalData->m_width) &&
(rasterposy+y>=0) && (rasterposy+y<m_internalData->m_height))
{
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex,rasterposx+x,rasterposy+y,
red,green,blue,alpha);
}
}
y++;
}
x++;
}
xx+=10;
}
}
void TimeSeriesCanvas::shift1PixelToLeft()
{
int resetVal = 10;
int countdown = resetVal;
//shift pixture one pixel to the left
for (int j=0;j<m_internalData->m_height-48;j++)
{
for (int i=40;i<this->m_internalData->m_width;i++)
{
unsigned char red, green, blue, alpha;
m_internalData->m_canvasInterface->getPixel(m_internalData->m_canvasIndex,i,j,red,green,blue,alpha);
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex,i-1,j,red,green,blue,alpha);
}
if (!m_internalData->m_bar)
{
if (!countdown--)
{
countdown=resetVal;
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex,m_internalData->m_width-1,j,0,0,0,255);
} else
{
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex,m_internalData->m_width-1,j,255,255,255,255);
}
} else
{
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex,m_internalData->m_width-1,j,255,255,255,255);
}
}
{
int resetVal = 2;
static int countdown = resetVal;
if (!countdown--)
{
countdown=resetVal;
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex,m_internalData->m_width-1,m_internalData->m_zero,0,0,0,255);
}
}
{
int resetVal = 10;
static int countdown = resetVal;
if (!countdown--)
{
countdown=resetVal;
float zeroPixelCoord = m_internalData->m_zero;
float pixelsPerUnit = m_internalData->m_pixelsPerUnit;
float yPos = zeroPixelCoord+pixelsPerUnit*m_internalData->m_yScale;
float yNeg = zeroPixelCoord+pixelsPerUnit*-m_internalData->m_yScale;
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex,m_internalData->m_width-1,
yPos,0,0,0,255);
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex,m_internalData->m_width-1,
yNeg,0,0,0,255);
}
}
if (!m_internalData->m_bar)
{
char buf[1024];
float time = m_internalData->getTime();
sprintf(buf,"%3.2f",time);
grapicalPrintf(buf, sTimeSeriesFontData, m_internalData->m_width-53,m_internalData->m_zero+3,0,0,0,255);
m_internalData->m_bar=m_internalData->m_ticksPerSecond;
}
m_internalData->m_timeTicks++;
m_internalData->m_bar--;
}
void TimeSeriesCanvas::insertDataAtCurrentTime(float orgV, int dataSourceIndex, bool connectToPrevious)
{
btAssert(dataSourceIndex < m_internalData->m_dataSources.size());
float zero = m_internalData->m_zero;
float amp = m_internalData->m_pixelsPerUnit;
//insert some new value(s) in the right-most column
{
float time = m_internalData->getTime();
float v = zero+amp*orgV;
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex,m_internalData->m_width-1,v,
m_internalData->m_dataSources[dataSourceIndex].m_red,
m_internalData->m_dataSources[dataSourceIndex].m_green,
m_internalData->m_dataSources[dataSourceIndex].m_blue,
255
);
if (connectToPrevious && m_internalData->m_dataSources[dataSourceIndex].m_hasLastValue)
{
for (int value=m_internalData->m_dataSources[dataSourceIndex].m_lastValue;value<=v;value++)
{
if (value>=0 && value < float(m_internalData->m_height-1))
{
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex,m_internalData->m_width-1,value,
m_internalData->m_dataSources[dataSourceIndex].m_red,
m_internalData->m_dataSources[dataSourceIndex].m_green,
m_internalData->m_dataSources[dataSourceIndex].m_blue,
255
);
}
}
for (int value=v;value<=m_internalData->m_dataSources[dataSourceIndex].m_lastValue;value++)
{
if (value>=0 && value < float(m_internalData->m_height-1))
{
m_internalData->m_canvasInterface->setPixel(m_internalData->m_canvasIndex,m_internalData->m_width-1,value,
m_internalData->m_dataSources[dataSourceIndex].m_red,
m_internalData->m_dataSources[dataSourceIndex].m_green,
m_internalData->m_dataSources[dataSourceIndex].m_blue,
255);
}
}
}
m_internalData->m_dataSources[dataSourceIndex].m_lastValue = v;
m_internalData->m_dataSources[dataSourceIndex].m_hasLastValue = true;
}
}
void TimeSeriesCanvas::nextTick()
{
shift1PixelToLeft();
m_internalData->m_canvasInterface->refreshImageData(m_internalData->m_canvasIndex);
}