How to get all pixel code that I draw on HWND? - c
I build some simple Direct2d program.
I draw something, and I need the pixel code of my HWND.
There are maybe 1920 * 1080 * 4 byte of pixel code of my Direct2d program,
But I don't know how to reach them.
So here is my code, and program screenshot, please anyone help me.
How to print HEX code of all of pixeldata?
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <d2d1.h>
#include <dwrite.h>
#include <iostream>
#include <ctime>
#include <atlconv.h>
#include <string>
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "dwrite.lib")
ID2D1Factory* factory = NULL;
ID2D1HwndRenderTarget* target = NULL;
ID2D1SolidColorBrush* solid_brush;
IDWriteFactory* w_factory;
IDWriteTextFormat* w_format;
IDWriteTextLayout* w_layout;
using namespace std;
HWND hwnd;
int s_width = GetSystemMetrics(SM_CXSCREEN);
int s_height = GetSystemMetrics(SM_CYSCREEN);
clock_t start, endclock;
double result;
int fps = 0;
char fpsbuffer3[30];
char spectorbuffer[30];
void DrawString(string str, float fontSize, float x, float y, float r, float g, float b, float a)
{
RECT re;
GetClientRect(hwnd, &re);
FLOAT dpix, dpiy;
dpix = static_cast<float>(re.right - re.left);
dpiy = static_cast<float>(re.bottom - re.top);
USES_CONVERSION;
wstring bb(A2W(str.c_str()));
HRESULT res = w_factory->CreateTextLayout(bb.c_str(), bb.size(), w_format, 1920, 1080, &w_layout);
if (SUCCEEDED(res))
{
DWRITE_TEXT_RANGE range = { 0, str.length() };
w_layout->SetFontSize(fontSize, range);
solid_brush->SetColor(D2D1::ColorF(r, g, b, a));
target->DrawTextLayout(D2D1::Point2F(x, y), w_layout, solid_brush);
w_layout->Release();
w_layout = NULL;
}
}
void DrawBox(float x, float y, float width, float height, float thickness, float r, float g, float b, float a, bool filled)
{
solid_brush->SetColor(D2D1::ColorF(r, g, b, a));
if (filled) target->FillRectangle(D2D1::RectF(x, y, x + width, y + height), solid_brush);
else target->DrawRectangle(D2D1::RectF(x, y, x + width, y + height), solid_brush, thickness);
}
void DrawLine(float x1, float y1, float x2, float y2, float thickness, float r, float g, float b, float a) {
solid_brush->SetColor(D2D1::ColorF(r, g, b, a));
target->DrawLine(D2D1::Point2F(x1, y1), D2D1::Point2F(x2, y2), solid_brush, thickness);
}
void DrawCircle(float x, float y, float radius, float thickness, float r, float g, float b, float a, bool filled)
{
solid_brush->SetColor(D2D1::ColorF(r, g, b, a));
if (filled) target->FillEllipse(D2D1::Ellipse(D2D1::Point2F(x, y), radius, radius), solid_brush);
else target->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(x, y), radius, radius), solid_brush, thickness);
}
void DrawEllipse(float x, float y, float width, float height, float thickness, float r, float g, float b, float a, bool filled)
{
solid_brush->SetColor(D2D1::ColorF(r, g, b, a));
if (filled) target->FillEllipse(D2D1::Ellipse(D2D1::Point2F(x, y), width, height), solid_brush);
else target->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(x, y), width, height), solid_brush, thickness);
}
void Draw_Edge_String(string str, float fontSize, float x, float y, float r, float g, float b, float a)
{
DrawString(str, fontSize, x + 1, y, 0, 0, 0, 1);
DrawString(str, fontSize, x - 1, y, 0, 0, 0, 1);
DrawString(str, fontSize, x, y + 1, 0, 0, 0, 1);
DrawString(str, fontSize, x, y - 1, 0, 0, 0, 1);
DrawString(str, fontSize, x, y, r, g, b, a);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch (iMessage) {
case WM_CREATE:
return 0;
//case WM_PAINT:
//return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
void render()
{
UpdateWindow(hwnd);
WINDOWINFO info;
ZeroMemory(&info, sizeof(info));
info.cbSize = sizeof(info);
D2D1_SIZE_U siz;
siz.height = s_height;//((info.rcClient.bottom) - (info.rcClient.top));
siz.width = s_width;//((info.rcClient.right) - (info.rcClient.left));
SetWindowPos(hwnd, NULL, 0, 0, s_width, s_height, SWP_SHOWWINDOW);
target->Resize(&siz);
target->BeginDraw();
target->Clear(D2D1::ColorF(1.0, 0, 0, 1.0));
DrawCircle(300, 300, 100, 1, 0, 1, 0, 1, 1);
endclock = clock();
result = (double)(endclock - start);
fps++;
if (result > 1000)
{
sprintf(fpsbuffer3, "Fps: %d", fps);
fps = 0;
start = endclock;
}
std::string a = string(fpsbuffer3);
DrawString(a, 20, siz.width - 100 + 2, 2, 0, 0, 0, 1);
DrawString(a, 20, siz.width - 100, 0, 1, 1, 1, 1);
//in here I want to print my pixel code. :(
target->EndDraw();
}
int main()
{
WNDCLASS wc;
wc.cbClsExtra = NULL;
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = GetModuleHandle(NULL);
wc.lpfnWndProc = WndProc;
wc.lpszClassName = L"classname";
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClass(&wc);
HWND hwnd = CreateWindow(L"classname", L"windowname", WS_POPUP, 0, 0, s_width, s_height, NULL, NULL, GetModuleHandle(NULL), NULL);
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &factory);
HRESULT hr = factory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_HARDWARE,
D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED)),
D2D1::HwndRenderTargetProperties(hwnd, D2D1::SizeU(200, 200),
D2D1_PRESENT_OPTIONS_IMMEDIATELY), &target);
target->CreateSolidColorBrush(D2D1::ColorF(0.0f, 0.0f, 0.0f), &solid_brush);
target->SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&w_factory));
hr = w_factory->CreateTextFormat(L"-2002", NULL, DWRITE_FONT_WEIGHT_REGULAR,
DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, 15.0f, L"ko-KR", &w_format);
ShowWindow(hwnd, SW_SHOW);
MSG messages = { 0 };
start = clock();
while (messages.message != WM_QUIT) {
if (PeekMessage(&messages, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&messages);
DispatchMessage(&messages);
}
else {
render();
}
}
}
Related
Pixel to rect in win32api C
I'm creating an engine with primary operating system call. I can create a window and manipulate most of events. But I'm having trouble drawing images. I'm using stb_image to load the images, and it's doing well. When I try to draw the images with points I keep seems it drawing point by point 'cause it is doing in executing time. I would like to know if there's a way to put those pixels into a rect and then draw onto screen. Here is the functions I've already made: Image functions: typedef struct ImageTag ImageSet; struct ImageTag { B32U id; B8 * path; B32 w, h, bpp; size_t size; BO * data; B32U image_id; IMAGE_PUSH push; IMAGE_FLIP flip; IMAGE_MODE mode; ImageSet * preview, *next; STATUS (*load)(ImageSet * p); STATUS (*next_first)(ImageSet ** p, ImageSet * n); STATUS (*next_last)(ImageSet ** p, ImageSet * n); ImageSet * (*search)(ImageSet * p, B32U id); STATUS (*clone)(ImageSet ** p1, ImageSet * p2); STATUS (*pixel_set)(ImageSet * i, B32 x, B32 y, PixelSet * p); PixelSet (*pixel_get)(ImageSet * i, B32 x, B32 y); BO (*zoom_fit)(ImageSet * p, B32 w, B32 h); BO (*draw)(ImageSet * p, B32 x, B32 y); BO (*draw_map)(B32 x, B32 y); STATUS (*pop)(ImageSet * p); STATUS (*destroy)(ImageSet * p); }; static PixelSet image_of_pixel_get(ImageSet * i, B32 x, B32 y) { PixelSet c = pixel_start(); if (!i) return c; c.r = ((B8U*) i->data)[i->bpp * (y * i->w + x) + 0]; c.g = ((B8U*) i->data)[i->bpp * (y * i->w + x) + 1]; c.b = ((B8U*) i->data)[i->bpp * (y * i->w + x) + 2]; c.a = i->bpp >= 4 ? ((B8U*) i->data)[i->bpp * (y * i->w + x) + 3] : 0xff; return c; } BO static image_of_map_draw(B32 i, B32 j) { if ((!gear || !gear->map || !gear->map->image) || ((i < 0 && i > gear->map->image->w - gear->w) || (j < 0 && j > gear->map->image->h - gear->h))) return; switch (gear->up->system) { case SYSTEM_PRIMARY: { #if defined WIN32 || WIN64 || WINDOWS_XP B32 x, y; for (y = 0; y < gear->h; y++) { for (x = 0; x < gear->w; x++) { PixelSet c = pixel_rgba_start( ((B8U *) (gear->map->image->data))[gear->map->image->bpp * ((j + y) * gear->map->image->w + (i + x)) + 0], ((B8U *) (gear->map->image->data))[gear->map->image->bpp * ((j + y) * gear->map->image->w + (i + x)) + 1], ((B8U *) (gear->map->image->data))[gear->map->image->bpp * ((j + y) * gear->map->image->w + (i + x)) + 2], gear->map->image->bpp >= 4 ? ((B8U *) (gear->map->image->data))[gear->map->image->bpp * ((j + y) * gear->map->image->w + (i + x)) + 3] : 255); windows_put_pixel(x, y, &c); } } //printf("%i %i\n", i, j); #endif } break; case SYSTEM_ALLEGRO: case SYSTEM_SDL: break; case SYSTEM_CONSOLE: default: break; } } operating system functions: #include <place/plugin/graphic/primary-of.h> #if defined WIN32 || WIN64 || WINDOWS_XP #include <place/machine.h> #include <place/driver/opengl-of.h> #include <place/plugin/graphic/windows-of.h> #include <stdio.h> extern MachineSet *gear; LRESULT CALLBACK windows_callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); HBITMAP create_bitmap(HDC screen, void * data, B32 w, B32 h, B32 bpp) { BITMAPINFOHEADER bmih; bmih.biSize = sizeof(BITMAPINFOHEADER); bmih.biWidth = w; bmih.biHeight = h; bmih.biPlanes = 1; bmih.biBitCount = 32; bmih.biCompression = BI_RGB; bmih.biSizeImage = 0; bmih.biXPelsPerMeter = 10; bmih.biYPelsPerMeter = 10; bmih.biClrUsed = 0; bmih.biClrImportant = 0; BITMAPINFO dbmi; ZeroMemory(&dbmi, sizeof(dbmi)); dbmi.bmiHeader = bmih; dbmi.bmiColors->rgbBlue = 255; dbmi.bmiColors->rgbGreen = 255; dbmi.bmiColors->rgbRed = 255; dbmi.bmiColors->rgbReserved = 0; HDC dc = CreateCompatibleDC(NULL); HBITMAP image = CreateDIBSection(dc, &dbmi, DIB_RGB_COLORS, (void**) &data, NULL, 0); return image; } LRESULT CALLBACK windows_callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_PAINT: { if (gear->up->driver == GRAPHIC_PRIMARY) { PAINTSTRUCT ps; WINDOWS_PLUGIN(gear)->screen = BeginPaint(WINDOWS_PLUGIN(gear)->window, &ps); int choice = 1; switch (choice) { case 0: { // this is what I've tried unsuccessfully HBITMAP bmp = create_bitmap(WINDOWS_PLUGIN(gear)->screen, gear->map->image->data, gear->map->size->x, gear->map->size->y, gear->map->image->bpp); windows_draw(bmp, gear->map->size->x * 0.1, gear->map->size->y * 0.1); } break; case 1:{ // this is what I'm using gear->map->image->draw_map(gear->map->pos->x,gear->map->pos->y); }break; } EndPaint(WINDOWS_PLUGIN(gear)->window, &ps); } } return 0; // ... return DefWindowProc(hwnd, uMsg, wParam, lParam); } WINDOWS_OF_CALL BO WINDOWS_OF_TYPE windows_put_pixel(B32 x, B32 y, PixelSet * c) { SetPixel(WINDOWS_PLUGIN(gear)->screen, x, y, RGB(c->r, c->g, c->b)); } WINDOWS_OF_CALL BO WINDOWS_OF_TYPE windows_draw(HBITMAP bmp, B32 w, B32 h) { HDC hdcMem = CreateCompatibleDC(NULL); BitBlt(WINDOWS_PLUGIN(gear)->screen, 0, 0, w, h, hdcMem, 0, 0, SRCCOPY); DeleteDC(hdcMem); } #elif defined __linux__ // ... #endif I wanted to put those pixels onto a windows buffer before to draw it. This is the video showing what's happening https://youtu.be/Hhpm5459hoA
How do I draw multiple SDL_rects to the screen in sdl2?
So I have this function that takes a rect, RGB, alpha values and a char which determines if it will fill the rect or not. void make_rect(SDL_Rect rect, SDL_Renderer * renderer, int r, int g, int b, int a, char flag) { SDL_SetRenderDrawColor(renderer, r, g, b, a); if(drawmd == 'f') { SDL_RenderFillRect(renderer, &rect); } else if(drawmd == 'd') { SDL_RenderDrawRect(renderer, &rect); } SDL_RenderPresent(renderer); } I call the function twice with different rects: rect_1: SDL_Rect rect; rect.x = 241; rect.y = 389; rect.w = 104; rect.h = 69; int r = 32; int g = 186; int b = 247; int a = 255; char dm = 'f' make_rect(rect, renderer, r, g, b, a, dm); and the same with different values and names not listed here. All of these variables are within bounds and I don't get a compilation error it only draws one of the rects.
How do I draw a Pixmap with GTK?
Using GTK3, I have been trying to draw a Pixmap from a memory buffer. I have just created a memory buffer, and filled it with alternating rows of colours in the 32-bit RGBA format. I have been trying the following function: gdk_pixbuf_new_from_data(const guchar *data, GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, int width, int height, int rowstride, GdkPixbufDestroyNotify destroy_fn, gpointer destroy_fn_data) Using this, I have been able to wrap the memory buffer into a GdkPixbuf*, however when I attempt to draw the pixbuf to screen with Cairo, the image seems to be distorted. Here is my test program that I have been experimenting with: #include <gtk/gtk.h> #include <stdlib.h> #include <stdint.h> #include <stdbool.h> const int WIDTH = 1080; const int HEIGHT = 720; GtkWidget* mainWindow; int currentCol = 0; uint32_t* framebuffer = NULL; GdkPixbuf* pixbuf = NULL; typedef struct _rgbColor { uint8_t red; uint8_t green; uint8_t blue; uint8_t alpha; }rgbColor; void onWindowDestroy (GtkWidget* object, gpointer user_data) { gtk_main_quit(); } gboolean onTimerTick(gpointer user_data) { rgbColor c = {0, 0, 0, 255}; if (currentCol == 0) { c.red = 255; } if (currentCol == 1) { c.green = 255; } if (currentCol == 2) { c.blue = 255; currentCol = -1; } currentCol++; fillWithColour(framebuffer, c); rgbColor c1 = {0, 0, 255, 255}; fillEveryInterval(framebuffer, c1, 20); gtk_widget_queue_draw(mainWindow); return 1; } gboolean onDraw(GtkWidget* widget, cairo_t *cr, gpointer user_data) { gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0); cairo_paint(cr); return 0; } void fillWithColour(uint32_t* fb, rgbColor c) { for (int y = 0; y < HEIGHT; y++) { for (int x = 0; x < WIDTH; x++) { encodePixel(fb, c, x, y); } } } void fillEveryInterval(uint32_t* fb, rgbColor c, int interval) { for (int y = 1; y < HEIGHT; y += interval) { for (int x = 0; x < WIDTH; x++) { encodePixel(fb, c, x, y); } } } void encodePixel(uint32_t* fb, rgbColor c, int x, int y) { uint32_t r, g, b, a; r = c.red; g = c.green << 8; b = c.blue << 16; a = c.alpha << 24; *(fb + (sizeof(uint32_t)*y+x)) = b | g | r | a; } int main() { framebuffer = malloc(sizeof(uint32_t)*WIDTH*HEIGHT); rgbColor c = {255, 0, 0, 255}; fillWithColour(framebuffer, c); gtk_init(NULL, NULL); mainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(mainWindow), WIDTH, HEIGHT); gtk_window_set_title(GTK_WINDOW(mainWindow), "Framebuffer test"); GtkWidget* drawingArea = gtk_drawing_area_new(); gtk_container_add(GTK_CONTAINER(mainWindow), drawingArea); g_signal_connect(GTK_WINDOW(mainWindow), "destroy", (GCallback)onWindowDestroy, NULL); g_signal_connect(GTK_DRAWING_AREA(drawingArea), "draw", (GCallback)onDraw, NULL); g_timeout_add(500, onTimerTick, NULL); gtk_widget_show_all(GTK_WINDOW(mainWindow)); pixbuf = gdk_pixbuf_new_from_data(framebuffer, GDK_COLORSPACE_RGB, true, 8, WIDTH, HEIGHT, WIDTH*4, NULL, NULL); gtk_main(); } I can't seem to figure out what is causing the issue, I have experimented with eliminating the alpha channel and packing the RGB values into 24-bits, however I was not successful with that method either. I think it may have something to do with the rowstride, however I have not been able to find a value which corrects the issue. Am I on the right track here, or is there a better way to draw a RGB buffer to screen using GTK?
You're just storing the pixels in the wrong location. In encodePixel, change this line: *(fb + (sizeof(uint32_t)*y+x)) = b | g | r | a;` to this fb[WIDTH*y+x] = b | g | r | a; And on a sidenote: You should do something with the many warnings from the compiler.
Why dots cannot be drawn "smoothly" with XDrawPoint ( X Window )?
Here is the code snippet (Xlib): void update_screen() { int X,Y; for (X = 0; X < Wnd_X; X++) for (Y = 0; Y < Wnd_Y; Y++) { XDrawPoint(dsp, win, gc_2, X, Y); usleep(100); } return; } But it'll be like this: and then: Why dots cannot be drawn smoothly with XDrawPoint? And how to fill the window with green color fluently? Full code here: #include <X11/Xlib.h> // must precede most other headers! #include <stdlib.h> int Wnd_X=500; int Wnd_Y=500; void update_screen(); GC gc_2; Window win; Display *dsp; int main() { dsp = XOpenDisplay(NULL); int screen = DefaultScreen(dsp); win = XCreateWindow(dsp, DefaultRootWindow(dsp), 0, 0, Wnd_X, Wnd_Y, 0, 0, 0, 0, 0, 0); //XCreateSimpleWindow(dsp, DefaultRootWindow(dsp), 0, 0, Wnd_X, Wnd_Y, 0, 0x000000, 0xFFFFFF); Atom wmDelete = XInternAtom(dsp, "WM_DELETE_WINDOW", True); XSetWMProtocols(dsp, win, &wmDelete, 1); XGCValues gcvalues_2; gcvalues_2.function = GXcopy; gcvalues_2.plane_mask = AllPlanes; gcvalues_2.foreground = 0x00FF00; gcvalues_2.background = 0xFFFFFF; gc_2 = XCreateGC(dsp, win, GCFunction|GCPlaneMask|GCForeground|GCBackground, &gcvalues_2); XEvent evt; long eventMask = StructureNotifyMask; eventMask |= ButtonPressMask|ButtonReleaseMask|KeyPressMask|KeyReleaseMask; XSelectInput(dsp, win, eventMask); XMapWindow(dsp, win); // wait until window appears do { XNextEvent(dsp,&evt); } while (evt.type != MapNotify); update_screen(); XDestroyWindow(dsp, win); XCloseDisplay(dsp); return 0; } void update_screen() { int X,Y; for (X = 0; X < Wnd_X; X++) for (Y = 0; Y < Wnd_Y; Y++) { XDrawPoint(dsp, win, gc_2, X, Y); usleep(100); } return; }
You need to flush the updates to the X server. Try this: XDrawPoint(dsp, win, gc_2, X, Y); XFlush(dsp); usleep(100);
how to convert simple opengl line plotting code to use vertex array
I wrote a simple opengl application in C which plots sin(x). This is my current draw function which runs very slow. How do I have to convert this code to make use of the faster 'vertex array' mode? list of variables and functions used: N = total number of points x1 = min(x) x2 = max(x) y1 = min(y) y2 = max(y) func(x) = sin(x) and here's the entire code: /* to compile, do: $ gcc -o out simple.c -lglut */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <GL/glut.h> #include <time.h> float xmin = -10, xmax = 10, ymin = -5, ymax = 5; int nPoints = 3000; /* function to calculate each data point */ float func(float x) { return sin(x); } /* plotting function - very slow */ void draw(float (* func)(float x), float x1, float x2, float y1, float y2, int N) { float x, dx = 1.0/N; glPushMatrix(); glScalef(1.0 / (x2 - x1), 1.0 / (y2 - y1), 1.0); glTranslatef(-x1, -y1, 0.0); glColor3f(1.0, 1.0, 1.0); glBegin(GL_LINE_STRIP); for(x = x1; x < x2; x += dx) { glVertex2f(x, func(x)); } glEnd(); glPopMatrix(); }; /* Redrawing func */ void redraw(void) { clock_t start = clock(); glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // -x, +x, -y, +y, number points draw(func, xmin, xmax, ymin, ymax, nPoints); glutSwapBuffers(); printf("Time elapsed: %f\n", ((double)clock() - start) / CLOCKS_PER_SEC); }; /* Idle proc. Redisplays, if called. */ void idle(void) { // shift 'xmin' & 'xmax' by one. xmin++; xmax++; glutPostRedisplay(); }; /* Key press processing */ void key(unsigned char c, int x, int y) { if(c == 27) exit(0); }; /* Window reashape */ void reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 1, 0, 1, -1, 1); glMatrixMode(GL_MODELVIEW); }; /* Main function */ int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutCreateWindow("Graph plotter"); glutReshapeWindow(1024, 800); glutPostRedisplay(); // This call may or may not be necessary /* Register GLUT callbacks. */ glutDisplayFunc(redraw); glutKeyboardFunc(key); glutReshapeFunc(reshape); glutIdleFunc(idle); /* Init the GL state */ glLineWidth(2.0); /* Main loop */ glutMainLoop(); return 0; }
In terms of LodePNG's C-style vector struct/functions: // shared vector pts; vector_init( &pts, sizeof( float ) ); // whenever x1, x2, or N changes vector_cleanup( &pts ); float x, dx = 1.0/N; for(x = x1; x < x2; x += dx) { vector_resize( &pts, pts.size + 2 ); *(float*)vector_get( &pts, pts.size-2 ) = x; *(float*)vector_get( &pts, pts.size-1 ) = func(x); } // whenever you want to draw glPushMatrix(); glScalef(1.0 / (x2 - x1), 1.0 / (y2 - y1), 1.0); glTranslatef(-x1, -y1, 0.0); glColor3f(1.0, 1.0, 1.0); glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( 2, GL_FLOAT, 0, (float*)pts.data ); glDrawArrays( GL_LINE_STRIP, 0, pts.size / 2 ); glDisableClientState( GL_VERTEX_ARRAY ); glPopMatrix(); EDIT: Complete code: #include <stdio.h> #include <stdlib.h> #include <math.h> #include <GL/glut.h> #include <time.h> typedef struct vector /*dynamic vector of void* pointers. This one is used only by the deflate compressor*/ { void* data; size_t size; /*in groups of bytes depending on type*/ size_t allocsize; /*in bytes*/ unsigned typesize; /*sizeof the type you store in data*/ } vector; static unsigned vector_resize(vector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/ { if(size * p->typesize > p->allocsize) { size_t newsize = size * p->typesize * 2; void* data = realloc(p->data, newsize); if(data) { p->allocsize = newsize; p->data = data; p->size = size; } else return 0; } else p->size = size; return 1; } static void vector_cleanup(void* p) { ((vector*)p)->size = ((vector*)p)->allocsize = 0; free(((vector*)p)->data); ((vector*)p)->data = NULL; } static void vector_init(vector* p, unsigned typesize) { p->data = NULL; p->size = p->allocsize = 0; p->typesize = typesize; } static void* vector_get(vector* p, size_t index) { return &((char*)p->data)[index * p->typesize]; } float xmin = -10, xmax = 10, ymin = -5, ymax = 5; int nPoints = 3000; vector pts; /* function to calculate each data point */ float func(float x) { return sin(x); } void update(float (* func)(float x), float x1, float x2, int N) { float x, dx = 1.0/N; vector_cleanup( &pts ); for(x = x1; x < x2; x += dx) { vector_resize( &pts, pts.size + 2 ); *(float*)vector_get( &pts, pts.size-2 ) = x; *(float*)vector_get( &pts, pts.size-1 ) = func(x); } } /* plotting function - very slow */ void draw(float x1, float x2, float y1, float y2) { glPushMatrix(); glScalef(1.0 / (x2 - x1), 1.0 / (y2 - y1), 1.0); glTranslatef(-x1, -y1, 0.0); glColor3f(1.0, 1.0, 1.0); if( pts.size > 0 ) { glEnableClientState( GL_VERTEX_ARRAY ); glVertexPointer( 2, GL_FLOAT, 0, (float*)pts.data ); glDrawArrays( GL_LINE_STRIP, 0, pts.size / 2 ); glDisableClientState( GL_VERTEX_ARRAY ); } glPopMatrix(); }; /* Redrawing func */ void redraw(void) { clock_t start = clock(); glClearColor(0, 0, 0, 0); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // -x, +x, -y, +y, number points draw(xmin, xmax, ymin, ymax); glutSwapBuffers(); printf("Time elapsed: %f\n", ((double)clock() - start) / CLOCKS_PER_SEC); }; /* Idle proc. Redisplays, if called. */ void idle(void) { // shift 'xmin' & 'xmax' by one. xmin++; xmax++; update(func, xmin, xmax, nPoints); glutPostRedisplay(); }; /* Key press processing */ void key(unsigned char c, int x, int y) { if(c == 27) exit(0); }; /* Window reashape */ void reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 1, 0, 1, -1, 1); glMatrixMode(GL_MODELVIEW); }; /* Main function */ int main(int argc, char **argv) { vector_init( &pts, sizeof( float ) ); glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); glutCreateWindow("Graph plotter"); glutReshapeWindow(1024, 800); glutPostRedisplay(); // This call may or may not be necessary /* Register GLUT callbacks. */ glutDisplayFunc(redraw); glutKeyboardFunc(key); glutReshapeFunc(reshape); glutIdleFunc(idle); /* Init the GL state */ glLineWidth(2.0); /* Main loop */ glutMainLoop(); return 0; }