mirror of
https://github.com/bulletphysics/bullet3
synced 2024-12-15 14:10:11 +00:00
ab8f16961e
Apply clang-format-all.sh using the _clang-format file through all the cpp/.h files. make sure not to apply it to certain serialization structures, since some parser expects the * as part of the name, instead of type. This commit contains no other changes aside from adding and applying clang-format-all.sh
331 lines
10 KiB
C++
331 lines
10 KiB
C++
#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)
|
|
{
|
|
m_internalData = new TimeSeriesInternalData(width, height);
|
|
|
|
m_internalData->m_canvasInterface = canvasInterface;
|
|
|
|
if (canvasInterface)
|
|
{
|
|
m_internalData->m_canvasIndex = m_internalData->m_canvasInterface->createCanvas(windowTitle, m_internalData->m_width, m_internalData->m_height, 20, 50);
|
|
}
|
|
}
|
|
|
|
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, bool clearCanvas)
|
|
{
|
|
if (0 == m_internalData->m_canvasInterface)
|
|
return;
|
|
|
|
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();
|
|
|
|
if (clearCanvas)
|
|
{
|
|
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 = 50; 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, "%2.0f", time);
|
|
grapicalPrintf(buf, sTimeSeriesFontData, m_internalData->m_width - 25, 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)
|
|
{
|
|
if (0 == m_internalData->m_canvasInterface)
|
|
return;
|
|
|
|
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);
|
|
}
|