I have this piece of code, the main idea is to draw a robot arm and move it whenever a data is received ob the 9090 port using UDP.
I want to figure out why after displaying the robot arm, I have no message displayed on the console.
Moreover I want to know how to modify the code just after if(number%2 ==0) in order to move the arm.
#include <GL/glut.h>
#include <math.h>
#define BASE_HEIGHT 4.0/2
#define BASE_RADIUS 1.0/2
#define HEAD_HEIGHT 1.25/2
#define HEAD_RADIUS 0.75/2
#define NECK_HEIGHT 0.5/2
#define EYE_LEVEL 0.75/2
#define NOSE_LENGTH 0.5/2
#define LOWER_ARM_HEIGHT 2.0/2
#define LOWER_ARM_WIDTH 0.5/2
#define UPPER_ARM_HEIGHT 1.25/2
#define UPPER_ARM_WIDTH 0.5/2
#define ARM_TRANSLATION 0.22/2
#define alpha 0.0
#define pi 3.14159265
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUFSIZE 2048
//***********************
struct sockaddr_in myaddr; /* our address */
struct sockaddr_in remaddr; /* remote address */
socklen_t addrlen = sizeof(remaddr); /* length of addresses */
int recvlen; /* # bytes received */
int fd; /* our socket */
unsigned char buf[BUFSIZE]; /* receive buffer */
#define SERVICE_PORT 9090
int a2i(unsigned char *s)
{
int sign=1;
if(*s == '-')
sign = -1;
s++;
int num=0;
while(*s)
{
num=((*s)-'0')+num*10;
s++;
}
return num*sign;
}
// The robot arm is specified by (1) the angle that the upper arm makes
// relative to the x-axis, called shoulderAngle, and (2) the angle that the
// lower arm makes relative to the upper arm, called elbowAngle. These angles
// are adjusted in 5 degree increments by a keyboard callback.
static int shoulderAngle = 0, elbowAngle = 0;
// Handles the keyboard event: the left and right arrows bend the elbow, the
// up and down keys bend the shoulder.
void special(int key, int, int) {
switch (key) {
case GLUT_KEY_LEFT: (elbowAngle += 5) %= 360; break;
case GLUT_KEY_RIGHT: (elbowAngle -= 5) %= 360; break;
case GLUT_KEY_UP: (shoulderAngle += 5) %= 360; break;
case GLUT_KEY_DOWN: (shoulderAngle -= 5) %= 360; break;
default: return;
}
glutPostRedisplay();
}
// wireBox(w, h, d) makes a wireframe box with width w, height h and
// depth d centered at the origin. It uses the GLUT wire cube function.
// The calls to glPushMatrix and glPopMatrix are essential here; they enable
// this function to be called from just about anywhere and guarantee that
// the glScalef call does not pollute code that follows a call to myWireBox.
void wireBox(GLdouble width, GLdouble height, GLdouble depth) {
glPushMatrix();
glScalef(width, height, depth);
glutWireCube(1.0);
glPopMatrix();
}
// Displays the arm in its current position and orientation. The whole
// function is bracketed by glPushMatrix and glPopMatrix calls because every
// time we call it we are in an "environment" in which a gluLookAt is in
// effect. (Note that in particular, replacing glPushMatrix with
// glLoadIdentity makes you lose the camera setting from gluLookAt).
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
// Draw the upper arm, rotated shoulder degrees about the z-axis. Note that
// the thing about glutWireBox is that normally its origin is in the middle
// of the box, but we want the "origin" of our box to be at the left end of
// the box, so it needs to first be shifted 1 unit in the x direction, then
// rotated.
glRotatef((GLfloat)shoulderAngle, 0.0, 0.0, 1.0);
glTranslatef(1.0, 0.0, 0.0);
wireBox(2.0, 0.4, 1.0);
// Now we are ready to draw the lower arm. Since the lower arm is attached
// to the upper arm we put the code here so that all rotations we do are
// relative to the rotation that we already made above to orient the upper
// arm. So, we want to rotate elbow degrees about the z-axis. But, like
// before, the anchor point for the rotation is at the end of the box, so
// we translate <1,0,0> before rotating. But after rotating we have to
// position the lower arm at the end of the upper arm, so we have to
// translate it <1,0,0> again.
glTranslatef(1.0, 0.0, 0.0);
glRotatef((GLfloat)elbowAngle, 0.0, 0.0, 1.0);
glTranslatef(1.0, 0.0, 0.0);
wireBox(2.0, 0.4, 1.0);
glPopMatrix();
glFlush();
}
// Handles the reshape event by setting the viewport so that it takes up the
// whole visible region, then sets the projection matrix to something reason-
// able that maintains proper aspect ratio.
void reshape(GLint w, GLint h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65.0, GLfloat(w)/GLfloat(h), 1.0, 20.0);
}
// Perfroms application specific initialization: turn off smooth shading,
// sets the viewing transformation once and for all. In this application we
// won't be moving the camera at all, so it makes sense to do this.
void init() {
glShadeModel(GL_FLAT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1,2,8, 0,0,0, 0,1,0);
}
// Initializes GLUT, the display mode, and main window; registers callbacks;
// does application initialization; enters the main event loop.
int main(int argc, char** argv) {
/* create a UDP socket */
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("cannot create socket\n");
return 0;
}
/* bind the socket to any valid IP address and a specific port */
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(SERVICE_PORT);
if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
perror("bind failed");
return 0;
}
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(80, 80);
glutInitWindowSize(800, 600);
glutCreateWindow("Robot Arm");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutSpecialFunc(special);
init();
glutMainLoop();
/* now loop, receiving data and printing what we received */
for (;;) {
printf("waiting on port %d\n", SERVICE_PORT);
recvlen = recvfrom(fd, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr, &addrlen);
printf("received %d bytes\n", recvlen);
if (recvlen > 0) {
buf[recvlen] = 0;
printf("received message: \"%s\"\n", buf);
int number = a2i( buf );
if(number%2 ==0) {
printf("pair message: \"%s\"\n", buf);
}
}
}
/* never exits */
//*******************
}
glutMainLoop() never returns:
glutMainLoop enters the GLUT event processing loop. This routine should be called at most once in a GLUT program. Once called, this routine will never return. It will call as necessary any callbacks that have been registered.
You have several options:
Switch to non-blocking sockets and service your network connection in a glutIdleFunc() callback.
Use FreeGLUT's glutMainLoopEvent() and friends to wrest back some control over your event loop. Be careful how long you block waiting on network traffic.
Keep using blocking sockets and spin up a thread to service the network connection; how you communicate state updates from the thread to your main program is up to you.
Related
I keep calling glutMainLoopEvent to process the graphics. However, after someone closed the window, I would like to exit the loop and show Code reached here. . it seems when a window is closed, an exit function is called and the entire application stops. While I need the application to continue. How should I fix the code?
#include <stdio.h>
#include <GL/freeglut.h>
//display function - draws a triangle rotating about the origin
void cback_render()
{
//keeps track of rotations
static float rotations = 0;
//OpenGL stuff for triangle
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(rotations, 0, 0, 1);
glBegin(GL_TRIANGLES);
glVertex3f(0,0,0);
glVertex3f(1,0,0);
glVertex3f(0,1,0);
glEnd();
//display on screen
glutSwapBuffers();
//rotate triangle a little bit, wrapping around at 360°
if (++rotations > 360) rotations -= 360;
}
void timer(int value )
{
glutPostRedisplay();
glutMainLoopEvent();
glutTimerFunc(30, timer, 1);
}
int main(int argc, char **argv)
{
//initialisations
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(100, 100);
glutInitWindowSize(512, 512);
//create window and register display callback
glutCreateWindow("freegluttest");
glutDisplayFunc (cback_render);
glutTimerFunc(30, timer, 1);
//loop forever
long i=0;
while(1)
{
printf("[%ld]\n",i);
i++;
glutMainLoopEvent();
}
printf("Code reached here.");
return 0;
}
Use GLUT_ACTION_ON_WINDOW_CLOSE to allow your program to continue when a window is closed.
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS);
Sources:
http://www.lighthouse3d.com/cg-topics/glut-and-freeglut/
http://freeglut.sourceforge.net/docs/api.php
I want to get started with modern OpenGL while reading the superbible book by coding a cellular automata using a 2d-array texture of size 1280x1280x2 and computing the next state to another layer in a compute shader. The idea is impiously stolen from glumpy examples.
However, while having such ambition in mind, I got confused at even trying to display it, not even passing the samplers into shaders.
Below I included both, the generator, which works OK, and the piece of code that does contain a problem.
gen
#!/usr/bin/env perl
use strict;
use warnings;
sub get_arg {
return (scalar #ARGV == 0) ? shift : shift #ARGV;
}
my $size = get_arg 1280;
my $rate = get_arg ($size >> 1);
my $symbol = (sub { ((shift) < $rate) ? '*' : '_' } );
print "$size\n";
for (0..$size) {
print $symbol->(int(rand() * $size)) for (0..$size);
print "\n";
}
code
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
// including opengl libraries on linux/osx
//include glew
#include <GL/glew.h>
//include opengl
#if defined (__APPLE_CC__)
#include <OpenGL/gl3.h>
#else
#include <GL/gl3.h> /* assert OpenGL 3.2 core profile available. */
#endif
//include glfw3
#define GLFW_INCLUDE_GL3 /* don't drag in legacy GL headers. */
#define GLFW_NO_GLU /* don't drag in the old GLU lib - unless you must. */
#include <GLFW/glfw3.h>
// ----------- the program itself
GLFWwindow *g_window;
#define SIZE 1280
#define WIDTH SIZE
#define HEIGHT SIZE
#define DEPTH 2
init_glfw(const char *name) {
// start GL context and O/S window using the GLFW helper library
assert(glfwInit());
#if defined(__APPLE_CC__)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif
g_window = glfwCreateWindow(WIDTH, HEIGHT, name, NULL, NULL);
assert(g_window != NULL);
glfwMakeContextCurrent(g_window);
// start GLEW extension handler
glewExperimental = GL_TRUE;
glewInit();
// tell GL to only draw onto a pixel if the shape is closer to the viewer
glEnable(GL_DEPTH_TEST); // enable depth-testing
glDepthFunc(GL_LESS); // depth-testing interprets a smaller value as "closer"
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
typedef enum { FILLED = '*', EMPTY = '_' } SYMBOL;
load_array(GLubyte array[SIZE * SIZE * DEPTH], FILE *stream) {
static char c;
for(int i = 0; i < SIZE; ++i) {
for(int j = 0; j < SIZE; ++j) {
bool approved = false;
GLubyte *it = &array[SIZE * i + j];
while(!approved) {
approved = true;
c = getc(stream);
assert(c != EOF);
switch(c) {
case FILLED:
*it = 0x00;
break;
case EMPTY:
*it = 0xff;
break;
default:
approved = false;
break;
}
}
assert(*it == 0x00 || *it == 0xff);
it[SIZE * SIZE] = it[0];
}
}
}
GLuint create_2d_texture() {
static GLuint texture = 0;
assert(texture == 0);
static GLubyte field[SIZE * SIZE << 1];
load_array(field, stdin);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_ALPHA8, SIZE, SIZE, DEPTH);
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, SIZE, SIZE, DEPTH, GL_ALPHA, GL_UNSIGNED_BYTE, field);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D_ARRAY,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
return texture;
}
display() {
GLuint texture = create_2d_texture();
assert(texture != 0);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT_AND_BACK);
while(!glfwWindowShouldClose(g_window)) {
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, texture);
glPushMatrix();
glEnable(GL_TEXTURE_2D_ARRAY);
glBegin(GL_QUADS);
glTexCoord3s(0, SIZE, 0); glVertex3f( 0.0f, 0.0f, 0.0 );
glTexCoord3s(SIZE, SIZE, 0); glVertex3f( SIZE, 0.0f, 0.0 );
glTexCoord3s(0, SIZE, 0); glVertex3f( SIZE, SIZE, 0.0 );
glTexCoord3s(0, 0, 0); glVertex3f( 0.0f, SIZE, 0.0 );
glEnd();
glPopMatrix();
glfwSwapBuffers(g_window);
glfwPollEvents();
if(glfwGetKey(g_window, GLFW_KEY_ESCAPE)) {
glfwSetWindowShouldClose(g_window, 1);
}
}
}
main() {
init_glfw("I want to display a texture");
display();
glfwDestroyWindow(g_window);
glfwTerminate();
}
Could you help me to analyse the issues with displaying the 2d array on the screen, please? What I am trying to achieve is to make the whole window randomly black-and-white, but so far I ended up completely confused just adding more layers from googled solutions and man pages.
I am not asking for a working code, just a comprehensible explanation which would help me to get through this problem.
glEnable(GL_TEXTURE_2D_ARRAY);
That gave you an OpenGL error. Even in compatibility profiles, you cannot enable an array texture of any kind. Why?
Because you cannot used fixed-function processing with array textures at all. You cannot use glTexEnv to fetch from an array texture. They're wholly and completely shader-based constructs.
So if you want to use an array texture, you must use a shader.
I want to implement a MS-Paint-like program (although my actual program will do more than this) where one can draw using mouse.
I am using SDL2 and also SDL2_gfx.
I want to maintain an SDL_Texture where the user will do the drawing in a continuously way without clearing (unless requested by the user) at any time.
And then continuously update the SDL_Texture on to the screen.
My question specifically is how to draw SDL2_gfx primitives on the SDL_Texture and copy that to the renderer. Any completely different way than to use texture will also do for me but must be using SDL2.
Below is a minimal runnable extraction from my code:
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <SDL2/SDL.h>
#include <SDL2_gfxPrimitives.h>
#define WIDTH (320)
#define HEIGHT (240)
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;
SDL_RendererInfo rendererInfo;
SDL_Texture* texture = NULL;
SDL_Event event;
Sint16 cx = WIDTH/2, cy = HEIGHT/2;
uint8_t quit = 0;
void init()
{
SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(WIDTH, HEIGHT, SDL_WINDOW_OPENGL, &window, &renderer);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, WIDTH, HEIGHT); // create texture to draw on to
// SDL_SetRenderTarget(renderer, texture); // this one I have removed
}
void draw()
{
pixelRGBA(renderer, cx, cy, 0xff, 0xff, 0x00, 0xff); // draw a pixel here, or whatever cx and cy are mouse position
// what I want is to draw on to the texture, and not directly on the screen buffer
}
void render()
{
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); // set clear color
SDL_RenderClear(renderer); // clear the buffer
SDL_RenderCopy(renderer, texture, NULL, NULL); // now copy the drawn texture to the buffer
SDL_RenderPresent(renderer); // now update window
}
int main(int argc, char* argv[])
{
int p;
init();
while(!quit)
{
SDL_PumpEvents();
p = SDL_PollEvent(&event);
if(p>0)
{
if(event.type==SDL_QUIT) quit = 1;
else
{
// here other things are there to handle the mouse positions etc for drawing exactly what the user wants
// ...
draw();
render();
}
}
}
SDL_Quit();
return 0;
}
Thanks in advance.
I'm trying to use the Cairo graphics library on Linux in C to make a pretty lightweight x11 GUI.
After trying very hard to follow the woefully incomplete guide that cairo gives for x11, this is the best I've got:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cairo.h>
#include <cairo-xlib.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/renderproto.h>
//This function should give us a new x11 surface to draw on.
cairo_surface_t* create_x11_surface(int x, int y)
{
Display* d;
Drawable da;
int screen;
cairo_surface_t* sfc;
if((d = XOpenDisplay(NULL)) == NULL)
{
printf("failed to open display\n");
exit(1);
}
screen = DefaultScreen(d);
da = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, x, y, 0, 0, 0);
XSelectInput(d, da, ButtonPressMask | KeyPressMask);
XMapWindow(d, da);
sfc = cairo_xlib_surface_create(d, da, DefaultVisual(d, screen), x, y);
cairo_xlib_surface_set_size(sfc, x, y);
return sfc;
}
int main(int argc, char** argv)
{
//create a new cairo surface in an x11 window as well as a cairo_t* to draw
//on the x11 window with.
cairo_surface_t* surface = create_x11_surface(300, 200);
cairo_t* cr = cairo_create(surface);
while(1)
{
//save the empty drawing for the next time through the loop.
cairo_push_group(cr);
//draw some text
cairo_select_font_face(cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(cr, 32.0);
cairo_set_source_rgb(cr, 0, 0, 1.0);
cairo_move_to(cr, 10.0, 25.0);
if((argc == 2) && (strnlen(argv[1], 100) < 50))
cairo_show_text(cr, argv[1]);
else
cairo_show_text(cr, "usage: ./p1 <string>");
//put the drawn text onto the screen(?)
cairo_pop_group_to_source(cr);
cairo_paint(cr);
cairo_surface_flush(surface);
//pause for a little bit.
int c = getchar();
//change the text around so we can see the screen update.
for(int i = 0; i < strnlen(argv[1], 100); i++)
{
argv[1][i] = argv[1][i + 1];
}
if(c == 'q')
{
break;
}
}
cairo_surface_destroy(surface);
return 0;
}
On Linux systems that have Cairo installed, it can be compiled with
gcc -o myprog $(pkg-config --cflags --libs cairo x11) -std=gnu99 main.c
And it should be run with a single argument.
For reasons I don't understand at all, inserting the line
cairo_pop_group_to_source(cr);
cairo_paint(cr);
cairo_surface_write_to_png (surface, "hello.png"); //<--------- inserted
cairo_surface_flush(surface);
Puts something on the screen, but there are 2 problems:
Text that I draw with this method is persistent, creating a smearing effect.
I don't want some .png file mediating between my program and an x11 window. Data should be sent directly!
Several issues:
In X11, the X11 server doesn't save what you drew to a window, but instead sends an ExposeEvent to your window that tells it to redraw. This means you get a black window, because you do not handle this event.
getchar only gives you something after a line break, so just typing something won't help.
libX11 buffers stuff and only sends it to the X11 server when you wait for an event (or the buffer fills up). Since you never wait for an event, it never flushes. Calling XFlush explicitly helps.
The group that you push is useless. Just get rid of it.
Your code to move the string one direction to the left easily goes beyond the end of the string. You apparently know this already, because you 'fixed' this with a strnlen.
Here is a little better solution, but it still gives you an initially black window, because you draw to it before it is mapped:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <cairo-xlib.h>
#include <X11/Xlib.h>
//This function should give us a new x11 surface to draw on.
cairo_surface_t* create_x11_surface(Display *d, int x, int y)
{
Drawable da;
int screen;
cairo_surface_t* sfc;
screen = DefaultScreen(d);
da = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, x, y, 0, 0, 0);
XSelectInput(d, da, ButtonPressMask | KeyPressMask);
XMapWindow(d, da);
sfc = cairo_xlib_surface_create(d, da, DefaultVisual(d, screen), x, y);
return sfc;
}
int main(int argc, char** argv)
{
Display *d = XOpenDisplay(NULL);
if (d == NULL) {
fprintf(stderr, "Failed to open display\n");
return 1;
}
//create a new cairo surface in an x11 window as well as a cairo_t* to draw
//on the x11 window with.
cairo_surface_t* surface = create_x11_surface(d, 300, 200);
cairo_t* cr = cairo_create(surface);
char *text = argv[1];
size_t text_len = 0;
if (argc != 2)
text = NULL;
else
text_len = strlen(text);
while(1)
{
// Clear the background
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_paint(cr);
//draw some text
cairo_select_font_face(cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size(cr, 32.0);
cairo_set_source_rgb(cr, 0, 0, 1.0);
cairo_move_to(cr, 10.0, 25.0);
if (text)
cairo_show_text(cr, text);
else
cairo_show_text(cr, "usage: ./p1 <string>");
cairo_surface_flush(surface);
XFlush(d);
//pause for a little bit.
int c = getchar();
//change the text around so we can see the screen update.
memmove(text, &text[1], text_len);
if (text_len > 0)
text_len--;
printf("got char %c\n", c);
if(c == 'q')
{
break;
}
}
// XXX: Lots of other stuff isn't properly destroyed here
cairo_surface_destroy(surface);
return 0;
}
Edit: Also, why exactly do you feel like cairo only gives you a woefully incomplete guide? It tells you how to get the cairo parts working and it also explains you some parts about X11, even though you should already know those if you want to use cairo-x11. That's none of its business. The guide you linked to even provides a complete, working and self-contained example: https://www.cypherpunk.at/files/2014/11/cairo_xlib_simple.c
I've you would have read the complete text of this "imcomplete guide" you would have seen that there is a link to the full sample: https://www.cypherpunk.at/files/2014/11/cairo_xlib_simple.c .
i am trying to draw a line using OpenGL while the both end coordinates of the line are set in the idle function , but it is not getting drawn while I am sending the endpoint coordinates over the network using sockets.
below is the snap of the code
int main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitWindowSize( 1024,1024); /* A x A pixel screen window */
glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE);
glutCreateWindow("Skeleton Tracker"); /* window title */
glutDisplayFunc(display); /* tell OpenGL main loop what */
glutIdleFunc(idle);
//first create the connection then we wil talk about the data transfer...
/*****Code for server connection *****/
processRequest();
return 0;
}
void processrequest()
{
byte_sent = send(ClientSocket,(char*)&msg_pkt,sizeof(MSG_PACKET),0);
ofile<<"\nByte sent for start generating "<<byte_sent<<endl;
Sleep(1000);
memset(buf,0,sizeof(buf));
glutMainLoop();
}
void display(void)
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); /* clear the window */
glColor3f ( 0.0, 1.0 , 0.0); /* draw in light red */
glBegin(GL_LINES);
glVertex2f(x[0] , y[0]);
glVertex2f(x[1] , y[1]);
glEnd();
glEnd();
glFlush();
}
void idle(void)
{
printf("\nIn Idle function\n");
nRetVal = recv(ClientSocket , (char*)mainbuf , 192,0);
printf("\nAmount of data received : %d\n" , nRetVal);
memcpy(buf , mainbuf , sizeof(buf)); //buf is of 8 bytes to hold 2 floating nos.
memcpy( &x[p] ,buf , 4); // upto 3
x[p] = x[p]/10.0;
memcpy( &y[p] ,buf+4 , 4); //upto 7
y[p] = y[p]/10.0;
glutPostRedisplay();
}
Design of your program is questionable - you have blocking recv() function in your idle function which is not good, idle should be as fast as possible to not affect your rendering.
consider creating one thread for rendering and the second thread for network communication, or at least use non-blockable recv() in your idle function to check whether there is any data on the socket available before reading (recv'ing) from it.
Thanks buddies for your time ... actually I forget to define the orthographic projection matrix before calling the glutMainloop ...
gluOrtho2D( -250, 250, -250, 250);
its working now.