increasing the Framerate to this Processing Script - svg

I'm currently working on this script for a project I'm doing, and I'm not happy with the current frame rate. It's bouncing around FPS, and I need at least 30 so I can further use it in a video installation without lag.
Since my math is terrible, and I didn't quite understand how the original other did the math, I can't figure out where the redundant code is.
I've been working on that for a whole day with no results.
Holler if you need the original .aif or the svg.
I think you can substitute with any kind of audio track, because as much as I can gather, these calculation are run separately.
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;
Minim minim;
AudioPlayer data1;
AudioPlayer data2;
AudioPlayer data3;
AudioPlayer data4;
/* OpenProcessing Tweak of *#*http://www.openprocessing.org/sketch/6598*#* */
/* !do not delete the line above, required for linking your tweak if you upload again */
float grid[][][];
PGraphics boundary;
int page = 0;
int sides = 3;
float w = PI/10;
PShape world;
public void setup() {
size(1920, 1080, FX2D);
//fullScreen(FX2D, 0);
frameRate(30);
grid = new float[2][width-1][height-1];
boundary = createGraphics(width, height);
world = loadShape("world.svg");
makeBoundary(sides);
loadPixels();
minim = new Minim (this);
data1 = minim.loadFile ("indo.aif");
data1.loop();
data1.play();
data2 = minim.loadFile ("chile.aif");
data2.loop();
data2.play();
data3 = minim.loadFile ("fuku.aif");
data3.loop();
data3.play();
data4 = minim.loadFile ("samoa.aif");
data4.loop();
data4.play();
}
void makeBoundary(int sides) {
for (int i=0; i<width-1; i++) {
for (int j=0; j<height-1; j++) {
grid[page][i][j] = 0;
grid[page^1][i][j] = 0;
}
}
boundary.beginDraw();
boundary.background(0);
boundary.fill(255);
boundary.shape(world, 0, 0, 1860, 1020);
boundary.endDraw();
}
public void draw() {
println(frameRate);
float thresh = map(mouseX, 0, width, 0, 255);
oscillator(data1, 380, 700, 32); // Indonesian Wellenquelle
oscillator(data2, 1470, 780, 32);
oscillator(data3, 570, 400, 32);
oscillator(data4, 700, 750, 32);
for (int i=1; i<width-2; i++) {
for (int j=1; j<height-2; j++) {
int wa = boundary.pixels[i+width*j];
float dx = (wa == 0xffffffff) ? 0: (grid[page][i-1][j] + grid[page][i+1][j]);
float dy = (wa == 0xffffffff) ? 0: (grid[page][i][j-1] + grid[page][i][j+1]);
float value = (dx+dy )/2 - grid[page^1][i][j] ;
grid[page^1][i][j] = value * 0.992;
int val = (int) (abs(value) * 512);
val = val > 255 ? 255 : val;
pixels[i+j*width] = 0xFF000000 | val << 16 | val << 8 | val;
}
}
page ^= 1;
updatePixels();
fill(0);
ellipse(380, 700, 64, 64);
ellipse(1470, 780, 64, 64);
ellipse( 570, 400, 64, 64);
ellipse(700, 750, 64, 64);
}
public void oscillator(AudioPlayer data, int x, int y, int r) {
//grid[page][cx][cy] = sou.mix.level() * 60; // Zahl ändert Anzahl von Kreisen/Wellen
//w += PI/16;
int r2 = r * r;
int area = r2 << 2;
int rr = r << 1;
for (int i = 0; i < area; i++)
{
int tx = (i % rr) - r;
int ty = (i / rr) - r;
if (tx * tx + ty * ty <= r2)
grid[page][x + tx][y + ty] = data.mix.level() * 30;
//SetPixel(x + tx, y + ty, c);
}
}
public void mousePressed() {
makeBoundary(++sides);
}
public void keyPressed() {
if (key == ' ') {
sides = 3;
makeBoundary(sides);
}
//saveFrame();
}

Related

Exception thrown: read access violation. this->pt_mat was 0x1110112

I got this error while using a double pointer in a class function to set coefficient and using it in the main.
The class function is used in a stand-alone function to set the coefficient using a class type pointer.
The class code is:
class Matrix
{
private:
int size_m, size_n;
double **pt_mat;
public:
Matrix() {};
Matrix(int m, int n)
{
pt_mat = new double *[m];
for (int i = 0; i < m; i++)
{
pt_mat[i] = new double[n];
}
}
void set_size(int m, int n)
{
size_m = m;
size_n = n;
}
void set_coef(int i, int j, double x)
{
pt_mat[i][j] = x;
}
void get_size(int *pt_m, int *pt_n)
{
*pt_m = size_m;
*pt_n = size_n;
}
double get_coef(int i, int j)
{
return pt_mat[i][j];
}
void print(ofstream &fout)
{
fout << size_m << " " << size_n << endl;
int i, j;
for (i = 0; i < size_m; i++)
{
for (j = 0; j < size_n; j++)
{
fout << pt_mat[i][j] << " ";
}
fout << endl;
}
}
void max_min(int *pt_imax, int *pt_jmax, double *pt_max, int *pt_imin, int *pt_jmin, double *pt_min)
{
double max, min;
int i, j, imax = 0, imin = 0, jmax = 0, jmin = 0;
max = pt_mat[0][0];
for (i = 0; i < size_m; i++)
{
for (j = 0; j < size_n; j++)
{
if (pt_mat[i][j] > max)
{
max = pt_mat[i][j];
imax = i;
jmax = j;
}
}
}
*pt_max = max;
*pt_imax = imax;
*pt_jmax = jmax;
min = pt_mat[0][0];
for (i = 0; i < size_m; i++)
{
for (j = 0; j < size_n; j++)
{
if (pt_mat[i][j] < min)
{
min = pt_mat[i][j];
imin = i;
jmin = j;
}
}
}
*pt_min = min;
*pt_imin = imin;
*pt_jmin = jmin;
}
};
The stand-alone function:
void mat_add(Matrix a, Matrix b, Matrix *pt_c)
{
Matrix c;
pt_c = &c;
int a_m, a_n, *p_am = &a_m, *p_an = &a_n;
a.get_size(p_am, p_an);
c.set_size(a_m, a_n);
int m, n, *pt_m = &m, *pt_n = &n;
double coef;
a.get_size(pt_m, pt_n);
int i, j;
for (i = 0; i < m; i++)
for (j = 0; j < n; j++)
{
coef = a.get_coef(i, j) + b.get_coef(i, j);
c.set_coef(i, j, coef);
}
}
please help me in this regard if you can. I have no syntax error showing.enter code here

how to store pieces in gomoku

am currently learning MFC and decided to make the game Gomoku. this is the code I have so far.
**mainframe.h**
class CMainFrame : public CFrameWnd
{
public:
CMainFrame();
protected:
DECLARE_DYNAMIC(CMainFrame)
public:
public:
public:
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
DECLARE_MESSAGE_MAP()
void DrawBoard(CDC* pDC);
int m_nNextChar;
int board[15][15];
static const int EMPTY = 0, WHITE = 1, BLACK = 2;
public:
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg void OnPaint();
};
**mainframe.cpp**
#include "stdafx.h"
#include "01.win32tomfc.h"
#include "MainFrm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CMainFrame
IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
ON_WM_LBUTTONDOWN()
ON_WM_RBUTTONDOWN()
ON_WM_PAINT()
END_MESSAGE_MAP()
int diameter = 23;
int size = 40;
int xCod;
int yCod;
int xCodx;
int yCody;
// CMainFrame ¹¹Ôì/Îö¹¹
CMainFrame::CMainFrame()
{
m_nNextChar = BLACK;
Create(NULL, _T("Generic Sample Application"));
CRect rect(0, 0, 700, 700);
CalcWindowRect(&rect);
SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(),
SWP_NOZORDER | SWP_NOMOVE | SWP_NOREDRAW);
}
CMainFrame::~CMainFrame()
{
}
// CMainFrame Õï¶Ï
#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
CFrameWnd::AssertValid();
}
void CMainFrame::Dump(CDumpContext& dc) const
{
CFrameWnd::Dump(dc);
}
#endif //_DEBUG
// CMainFrame ÏûÏ¢´¦Àí³ÌÐò
void CMainFrame::DrawBoard(CDC * pDC)
{
CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CPen* pOldPen = pDC->SelectObject(&pen);
for (int i = 1; i <= 16; i++) {
pDC->MoveTo(40 * i, 40);
pDC->LineTo(40 * i, 640);
pDC->MoveTo(40, 40 * i);
pDC->LineTo(640, 40 * i);
}
pDC->SelectObject(pOldPen);
}
void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(this);
CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CPen* pOldPen = dc.SelectObject(&pen);
dc.SelectStockObject(BLACK_BRUSH);
xCod = (point.x + (size / 2)) / size;
xCod = (xCod * size) - diameter / 2;
yCod = (point.y + (size / 2)) / size;
yCod = (yCod * size) - diameter / 2;
xCodx = xCod + diameter;
yCody = yCod + diameter;
if (m_nNextChar != BLACK )
return;
else {
if (xCod > 20 && yCod <= 640 && xCodx < 655 && yCody > 40) {
dc.Ellipse(xCod, yCod, xCodx, yCody);
}
}
m_nNextChar = WHITE;
CFrameWnd::OnLButtonDown(nFlags, point);
}
void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(this);
CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CPen* pOldPen = dc.SelectObject(&pen);
dc.SelectStockObject(WHITE_BRUSH);
xCod = (point.x + (size / 2)) / size;
xCod = (xCod * size) - diameter / 2;
yCod = (point.y + (size / 2)) / size;
yCod = (yCod * size) - diameter / 2;
xCodx = xCod + diameter;
yCody = yCod + diameter;
if (m_nNextChar != WHITE)
return;
else {
if (xCod > 20 && yCod <= 640 && xCodx < 655 && yCody > 40) {
dc.Ellipse(xCod, yCod, xCodx, yCody);
}
}
m_nNextChar = BLACK;
CFrameWnd::OnRButtonDown(nFlags, point);
}
void CMainFrame::OnPaint()
{
CPaintDC dc(this);
DrawBoard(&dc);
}
the code I have draws a 15 X 15 grid in the function DrawBoard() and draws the black and white pieces in the OnLButtonDown and OnRButtonDown respectively. thing is when I run the program and click to draw the black piece and then the white piece, the white piece can be drawn over the black piece and vice versa. so I thought to create a two-dimensional array board[15][15] to store a piece when its drawn so that a different piece cannot be drawn over a current piece would be best(am I on the right track here). I tried but I can't seem to figure out how to do it. am not very good at programming and realize this might be easy but some help would really be appreciated. please explain how I would go about it the right way.
this is what I tried.
void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(this);
CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CPen* pOldPen = dc.SelectObject(&pen);
dc.SelectStockObject(BLACK_BRUSH);
xCod = (point.x + (size / 2)) / size;
xCod = (xCod * size) - diameter / 2;
yCod = (point.y + (size / 2)) / size;
yCod = (yCod * size) - diameter / 2;
xCodx = xCod + diameter;
yCody = yCod + diameter;
if ((m_nNextChar != BLACK) && (board[xCod][yCod] = WHITE) )
return;
else {
if (xCod > 20 && yCod <= 640 && xCodx < 655 && yCody > 40) {
dc.Ellipse(xCod, yCod, xCodx, yCody);
board[xCod][yCod] = BLACK;
}
}
void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
{
CClientDC dc(this);
CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
CPen* pOldPen = dc.SelectObject(&pen);
dc.SelectStockObject(WHITE_BRUSH);
xCod = (point.x + (size / 2)) / size;
xCod = (xCod * size) - diameter / 2;
yCod = (point.y + (size / 2)) / size;
yCod = (yCod * size) - diameter / 2;
xCodx = xCod + diameter;
yCody = yCod + diameter;
if (m_nNextChar != WHITE && (board[xCod][yCod] = BLACK))
return;
else {
if (xCod > 20 && yCod <= 640 && xCodx < 655 && yCody > 40) {
dc.Ellipse(xCod, yCod, xCodx, yCody);
board[xCod][yCod] = WHITE;
}
}
m_nNextChar = BLACK;
CFrameWnd::OnRButtonDown(nFlags, point);
}
You should do all the drawings in OnPaint. Don't draw in other functions such as OnLButtonDown. Instead, get the necessary information from OnLButtonDown and call Invalidate, this will repaint the window.
Here is an example. For simplicity, I created a structure info and a 2-dimensional array data. data stores all the information for each cell, that is the rectangle and color. You have to initialize data once, and paint based on the information in data
#include <vector>
class CMainFrame : public CFrameWnd
{
...
struct info
{
CRect rect;
int color;
};
std::vector<std::vector<info>> data;
};
CMainFrame::CMainFrame()
{
...
data.resize(15);
for(int i = 0; i < data.size(); i++)
data[i].resize(15);
int xoffset = 20;
int yoffset = 20;
for(int row = 0; row < 15; row++)
{
for(int col = 0; col < 15; col++)
{
data[row][col].rect.SetRect(0, 0, size + 1, size + 1);
data[row][col].rect.MoveToXY(xoffset + row * size, yoffset + col * size);
}
}
}
void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point)
{
CFrameWnd::OnLButtonDown(nFlags, point);
for(int row = 0; row < 15; row++)
{
for(int col = 0; col < 15; col++)
{
if(data[row][col].color)
break;
if(data[row][col].rect.PtInRect(point))
{
data[row][col].color = WHITE;
break;
}
}
}
Invalidate(FALSE);
}
void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point)
{
CFrameWnd::OnRButtonDown(nFlags, point);
for(int row = 0; row < 15; row++)
{
for(int col = 0; col < 15; col++)
{
if(data[row][col].color)
break;
if(data[row][col].rect.PtInRect(point))
{
data[row][col].color = BLACK;
break;
}
}
}
Invalidate(FALSE);
}
void CMainFrame::OnPaint()
{
CPaintDC dc(this);
CPen pen(PS_SOLID, 1, RGB(0, 0, 0));
dc.SelectObject(&pen);
CBrush white, black;
white.CreateSolidBrush(RGB(255, 255, 255));
black.CreateSolidBrush(RGB(0, 0, 0));
for(int row = 0; row < 15; row++)
{
for(int col = 0; col < 15; col++)
{
dc.Rectangle(data[row][col].rect);
if(data[row][col].color)
{
CBrush *oldbrush;
if(data[row][col].color == WHITE)
oldbrush = dc.SelectObject(&white);
else
oldbrush = dc.SelectObject(&black);
dc.Ellipse(data[row][col].rect);
dc.SelectObject(oldbrush);
}
}
}
}

Problems while using threading with arguments

I have been trying to get this working for a while and I am not very skilled at C++/CLI. I am trying to loop through a 2d array and when it contains certain number create a thread to run but I keep getting errors while compiling.
Here is the thread creation:
if (map[x][y] == 8)
{
Pos^ p = gcnew Pos(x, y, map);
Thread^ t = gcnew Thread(gcnew ParameterizedThreadStart(p, &Pos::moverX));
t->Start(p);
}
else if (map[x][y] == 9)
{
Pos^ p = gcnew Pos(x, y, map);
Thread^ t = gcnew Thread(gcnew ParameterizedThreadStart(p, &Pos::moverY));
t->Start(p);
}
Here is the Pos class:
public ref class Pos
{
public:
static int px, py;
static int ** mapa;
Pos(int x, int y, int ** map)
{
px = x;
py = y;
mapa = map;
}
int getX(){ return px; }
int getY(){ return py; }
int** getMap(){ return mapa; }
static void moverX(Pos p)
{
int dy = 1;
while (true)
{
if (mapa[p.getX()+dy][p.getY()] == 1){ dy *= -1; }
Console::BackgroundColor = ConsoleColor::Black;
Console::SetCursorPosition(p.getY() + 30, p.getX() + 5);
cout << " ";
Console::SetCursorPosition(p.getY() + 30, p.getX() + 5+dy);
cout << (char)164;
Thread::Sleep(1000);
}
}
static void moverY(Pos p)
{
int dy = 1;
while (true)
{
if (mapa[p.getX()][p.getY() + dy] == 1){ dy *= -1; }
Console::BackgroundColor = ConsoleColor::Black;
Console::SetCursorPosition(p.getY() + 30, p.getX() + 5);
cout << " ";
Console::SetCursorPosition(p.getY() + 30 + dy, p.getX() + 5);
cout << (char)164;
Thread::Sleep(1000);
}
}
};

Import FBX Vertex And Index Buffer To DirectX 11

Ok, I'm still trying to figure out how to correctly import FBX vertex and index buffer into DirectX 11. I wrote a controller for doing that and passing the vertex and index buffer to the DX11 renderer, the output should look like a cube but it is not, I only see triangles that don't make sense.
The code is shown below. I did multiply the Z values by -1, though.
What do I need to modify to get the render right?
#pragma once
#include "Array.h"
#include "Vector.h"
#include "fbxsdk.h"
#include <assert.h>
#include "constants.h"
class FbxController
{
public:
FbxController();
~FbxController();
void Import(const char* lFilename)
{
lImporter = FbxImporter::Create(lSdkManager, "");
bool lImportStatus = lImporter->Initialize(lFilename, -1, lSdkManager->GetIOSettings());
if (!lImportStatus) {
printf("Call to FbxImporter::Initialize() failed.\n");
printf("Error returned: %s\n\n", lImporter->GetStatus().GetErrorString());
exit(-1);
}
lScene = FbxScene::Create(lSdkManager, "myScene");
lImporter->Import(lScene);
FbxNode* lRootNode = lScene->GetRootNode();
int childCount = lRootNode->GetChildCount();
FbxNode *node1 = lRootNode->GetChild(0);
const char* nodeName1 = node1->GetName();
fbxsdk::FbxMesh *mesh = node1->GetMesh();
int cpCount1 = mesh->GetControlPointsCount();
fbxsdk::FbxVector4 *controlPoints = mesh->GetControlPoints();
for (int i = 0; i < cpCount1; i++)
{
fbxsdk::FbxVector4 cpitem = controlPoints[i];
printf("%d, %d, %d, %d", cpitem[0], cpitem[1], cpitem[2], cpitem[3] );
VERTEXPOSCOLOR vpc;
vpc.Color.x = 0.5f;
vpc.Color.y = 0.5f;
vpc.Color.z = 0.5f;
vpc.Position.x = cpitem[0];
vpc.Position.y = cpitem[1];
vpc.Position.z = cpitem[2] * -1.0f;
m_vertices.add(vpc);
}
int pvCount = mesh->GetPolygonVertexCount();
int polyCount = mesh->GetPolygonCount();
for (int i = 0; i < polyCount; i++)
{
int polyItemSize = mesh->GetPolygonSize(i);
assert(polyItemSize == 3);
for (int j = 0; j < polyItemSize; j++)
{
int cpIndex = mesh->GetPolygonVertex(i, j);
m_indices.add(cpIndex);
float x = controlPoints[cpIndex].mData[0];
float y = controlPoints[cpIndex].mData[1];
float z = controlPoints[cpIndex].mData[2];
}
}
fbxsdk::FbxMesh *mesh2;
bool isT = mesh->IsTriangleMesh();
FbxNode *node2 = lRootNode->GetChild(1);
FbxNode *node3 = lRootNode->GetChild(2);
//lImporter->Destroy();
}
Array<VERTEXPOSCOLOR> GetVertexPosColors()
{
return m_vertices;
}
Array<unsigned int> getIndexBuffer()
{
return m_indices;
}
protected:
FbxManager *lSdkManager;
FbxIOSettings *ios;
FbxImporter *lImporter;
bool lImportStatu;
FbxScene *lScene;
private:
Array<VERTEXPOSCOLOR> m_vertices;
Array<unsigned int> m_indices;
};
I think you have some problems in your index buffer creation.
You simply gives an index for each vertex, and index buffer not working that way.
let me know if you solve this.

Performance difference between DrawLine and DrawLines?

Im using GDI+ in C++ to draw a chart control. I want to know if there is any performance difference between the above 2 functions. I am not lazy to write code for DrawLines() but it is that doing so makes my code complex. So im weighin the chances of whether to make code execution faster at the expense of reducing readability and potentially increasing errors and bugs.
Any help wud be appreciated.
Eraj.
There shouldn't be a significant difference between the two for most drawing activities, but to be sure, I wrote up a test project to compare the difference between them (well, actually 3 of them).
For a very large number of lines (x25000) on my machine, DrawLines() (640ms) was about 50% faster over DrawLine() (420ms). To be honest here, I also misread the question the first time around and wrote my initial test in C#. Performance was about the same between the two, which is to be expected as .NET Graphics are based upon GDI+.
Just out of curiosity, I tried regular GDI, which I expect would be faster. Using the win32 PolyLine() (530ms) function was about 20% faster, with 45000 lines. This is 116% faster than using GDI+ DrawLines(). Even more stunning, perhaps, is that using win32 LineTo() instead of GDI+ DrawLine() results in times under 125ms. With an assumed time of 125ms and 45000 lines, this method is at least 800% faster. (Timer resolution and thread timing make it difficult to measure performance in this threshold without resorting to QueryPerformanceCounter and other timing methods of higher frequency.)
However, I should caution against making the assumption that this is a significant bottleneck in drawing code. Many of the performance improvements that can be made will have nothing to do with what objects have to be drawn. I would guess that your requirements will probably dictate that a few hundred items may need to be drawn in normal operation for your control. In that case, I would recommend you write your drawing code to be as straightforward and bug-free as you can, as debugging drawing issues can be an expensive use of time and potentially less beneficial as improving the rest of your control or your application.
Also, if you need to actively update thousands of items, you will see much higher performance gains by moving to a back-buffered solution. This should also make it easier to develop code to draw your control, aside from managing the off-screen buffer.
Here are my source code examples. Each of them handles mouse clicks to alternate between using bulk drawing versus itemized drawing.
GDI+, hosted in a barebones MFC SDI App
This assumes that someone has already declared GDI+ headers and written code to initialize/teardown GDI+.
In ChildView.h
// Attributes
public:
bool m_bCompositeMode;
// Operations
public:
void RedrawScene(Graphics &g, int lineCount, int width, int height);
PointF *CreatePoints(int lineCount, int width, int height);
void ReportTime(Graphics &g, int lineCount, DWORD tickSpan);
public:
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
In ChildView.cpp, added to PreCreateWindow()
m_bCompositeMode = false;
Remainder of ChildView.cpp, including OnPaint() and Message Map changes.
BEGIN_MESSAGE_MAP(CChildView, CWnd)
ON_WM_PAINT()
ON_WM_LBUTTONUP()
END_MESSAGE_MAP()
void CChildView::OnPaint()
{
CPaintDC dc(this); // device context for painting
RECT rcClient;
::GetClientRect(this->GetSafeHwnd(), &rcClient);
Graphics g(dc.GetSafeHdc());
g.Clear(Color(0, 0, 0));
RedrawScene(g, 25000, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
}
void CChildView::RedrawScene(Graphics &g, int lineCount, int width, int height)
{
DWORD tickStart = 0;
DWORD tickEnd = 0;
Pen p(Color(0, 0, 0x7F));
PointF *pts = CreatePoints(lineCount, width, height);
tickStart = GetTickCount();
if (m_bCompositeMode)
{
g.DrawLines(&p, pts, lineCount);
}
else
{
int i = 0;
int imax = lineCount - 1;
for (i = 0; i < imax; i++)
{
g.DrawLine(&p, pts[i], pts[i + 1]);
}
}
tickEnd = GetTickCount();
delete[] pts;
ReportTime(g, lineCount, tickEnd - tickStart);
}
void CChildView::ReportTime(Graphics &g, int lineCount, DWORD tickSpan)
{
CString strDisp;
if(m_bCompositeMode)
{
strDisp.Format(_T("Graphics::DrawLines(Pen *, PointF *, INT) x%d took %dms"), lineCount, tickSpan);
}
else
{
strDisp.Format(_T("Graphics::DrawLine(Pen *, PointF, PointF) x%d took %dms"), lineCount, tickSpan);
}
// Note: sloppy, but simple.
Font font(L"Arial", 14.0f);
PointF ptOrigin(0.0f, 0.0f);
SolidBrush br(Color(255, 255, 255));
Status s = g.DrawString(strDisp, -1, &font, ptOrigin, &br);
}
PointF* CChildView::CreatePoints(int lineCount, int width, int height)
{
if(lineCount <= 0)
{
PointF *ptEmpty = new PointF[2];
ptEmpty[0].X = 0;
ptEmpty[0].Y = 0;
ptEmpty[1].X = 0;
ptEmpty[1].Y = 0;
return ptEmpty;
}
PointF *pts = new PointF[lineCount + 1];
int i = 1;
while(i < lineCount)
{
pts[i].X = (float)(rand() % width);
pts[i].Y = (float)(rand() % height);
i++;
}
return pts;
}
void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
{
m_bCompositeMode = !m_bCompositeMode;
this->Invalidate();
CWnd::OnLButtonUp(nFlags, point);
}
C#.NET, hosted in a basebones WinForms App, with default class Form1
Set a default size for the form, equal to the size of the MFC version if you are comparing the two. A size-change handler could be added as well.
public Form1()
{
InitializeComponent();
bCompositeMode = false;
}
bool bCompositeMode;
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.Black);
RedrawScene(e.Graphics, 25000, this.ClientRectangle.Width, this.ClientRectangle.Height);
}
private void RedrawScene(Graphics g, int lineCount, int width, int height)
{
DateTime dtStart = DateTime.MinValue;
DateTime dtEnd = DateTime.MinValue;
using (Pen p = new Pen(Color.Navy))
{
Point[] pts = CreatePoints(lineCount, width, height);
dtStart = DateTime.Now;
if (bCompositeMode)
{
g.DrawLines(p, pts);
}
else
{
int i = 0;
int imax = pts.Length - 1;
for (i = 0; i < imax; i++)
{
g.DrawLine(p, pts[i], pts[i + 1]);
}
}
dtEnd = DateTime.Now;
}
ReportTime(g, lineCount, dtEnd - dtStart);
}
private void ReportTime(Graphics g, int lineCount, TimeSpan ts)
{
string strDisp = null;
if (bCompositeMode)
{
strDisp = string.Format("DrawLines(Pen, Point[]) x{0} took {1}ms", lineCount, ts.Milliseconds);
}
else
{
strDisp = string.Format("DrawLine(Pen, Point, Point) x{0} took {1}ms", lineCount, ts.Milliseconds);
}
// Note: sloppy, but simple.
using (Font font = new Font(FontFamily.GenericSansSerif, 14.0f, FontStyle.Regular))
{
g.DrawString(strDisp, font, Brushes.White, 0.0f, 0.0f);
}
}
private Point[] CreatePoints(int count, int width, int height)
{
Random rnd = new Random();
if (count <= 0) { return new Point[] { new Point(0,0), new Point(0,0)}; }
Point[] pts = new Point[count + 1];
pts[0] = new Point(0, 0);
int i = 1;
while (i <= count)
{
pts[i] = new Point(rnd.Next(width), rnd.Next(height));
i++;
}
return pts;
}
private void Form1_Click(object sender, EventArgs e)
{
bCompositeMode = !bCompositeMode;
Invalidate();
}
Regular GDI, hosted in a barebones MFC SDI App
In ChildView.h
// Attributes
public:
bool m_bCompositeMode;
// Operations
public:
void RedrawScene(HDC hdc, int lineCount, int width, int height);
POINT *CreatePoints(int lineCount, int width, int height);
void ReportTime(HDC hdc, int lineCount, DWORD tickSpan);
public:
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
In ChildView.cpp
Update PreCreateWindow() just as in the GDI+ sample.
BEGIN_MESSAGE_MAP(CChildView, CWnd)
ON_WM_PAINT()
ON_WM_LBUTTONUP()
END_MESSAGE_MAP()
void CChildView::OnPaint()
{
CPaintDC dc(this); // device context for painting
HDC hdc = dc.GetSafeHdc();
HBRUSH brClear = (HBRUSH)::GetStockObject(BLACK_BRUSH);
RECT rcClient;
::GetClientRect(this->m_hWnd, &rcClient);
::FillRect(hdc, &rcClient, brClear);
::DeleteObject(brClear);
RedrawScene(hdc, 45000, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
}
void CChildView::RedrawScene(HDC hdc, int lineCount, int width, int height)
{
DWORD tickStart = 0;
DWORD tickEnd = 0;
HPEN p = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0x7F));
POINT *pts = CreatePoints(lineCount, width, height);
HGDIOBJ prevPen = SelectObject(hdc, p);
tickStart = GetTickCount();
if(m_bCompositeMode)
{
::Polyline(hdc, pts, lineCount);
}
else
{
::MoveToEx(hdc, pts[0].x, pts[0].y, &(pts[0]));
int i = 0;
int imax = lineCount;
for(i = 1; i < imax; i++)
{
::LineTo(hdc, pts[i].x, pts[i].y);
}
}
tickEnd = GetTickCount();
::SelectObject(hdc, prevPen);
delete pts;
::DeleteObject(p);
ReportTime(hdc, lineCount, tickEnd - tickStart);
}
POINT *CChildView::CreatePoints(int lineCount, int width, int height)
{
if(lineCount <= 0)
{
POINT *ptEmpty = new POINT[2];
memset(&ptEmpty, 0, sizeof(POINT) * 2);
return ptEmpty;
}
POINT *pts = new POINT[lineCount + 1];
int i = 1;
while(i < lineCount)
{
pts[i].x = rand() % width;
pts[i].y = rand() % height;
i++;
}
return pts;
}
void CChildView::ReportTime(HDC hdc, int lineCount, DWORD tickSpan)
{
CString strDisp;
if(m_bCompositeMode)
{
strDisp.Format(_T("PolyLine(HDC, POINT *, int) x%d took %dms"), lineCount, tickSpan);
}
else
{
strDisp.Format(_T("LineTo(HDC, HPEN, int, int) x%d took %dms"), lineCount, tickSpan);
}
HFONT font = (HFONT)::GetStockObject(SYSTEM_FONT);
HFONT fontPrev = (HFONT)::SelectObject(hdc, font);
RECT rcClient;
::GetClientRect(this->m_hWnd, &rcClient);
::ExtTextOut(hdc, 0, 0, ETO_CLIPPED, &rcClient, strDisp.GetString(), strDisp.GetLength(), NULL);
::SelectObject(hdc, fontPrev);
::DeleteObject(font);
}
void CChildView::OnLButtonUp(UINT nFlags, CPoint point)
{
m_bCompositeMode = !m_bCompositeMode;
this->Invalidate();
CWnd::OnLButtonUp(nFlags, point);
}

Resources