How to make transparent window on linux - c++
I want to make application an application with a splash screen on Linux.
I want to use X11 and glx (OpenGL application).
I've found a way to remove the border around the window, but I can't find how to make it transparent. How can I accomplish this?
This is the real answer of my question
/*------------------------------------------------------------------------
* A demonstration of OpenGL in a ARGB window
* => support for composited window transparency
*
* (c) 2011 by Wolfgang 'datenwolf' Draxinger
* See me at comp.graphics.api.opengl and StackOverflow.com
* License agreement: This source code is provided "as is". You
* can use this source code however you want for your own personal
* use. If you give this source code to anybody else then you must
* leave this message in it.
*
* This program is based on the simplest possible
* Linux OpenGL program by FTB (see info below)
The simplest possible Linux OpenGL program? Maybe...
(c) 2002 by FTB. See me in comp.graphics.api.opengl
--
<\___/>
/ O O \
\_____/ FTB.
------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>
#include <X11/Xutil.h>
#define USE_CHOOSE_FBCONFIG
static void fatalError(const char *why)
{
fprintf(stderr, "%s", why);
exit(0x666);
}
static int Xscreen;
static Atom del_atom;
static Colormap cmap;
static Display *Xdisplay;
static XVisualInfo *visual;
static XRenderPictFormat *pict_format;
static GLXFBConfig *fbconfigs, fbconfig;
static int numfbconfigs;
static GLXContext render_context;
static Window Xroot, window_handle;
static GLXWindow glX_window_handle;
static int width, height;
static int VisData[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_DOUBLEBUFFER, True,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 16,
None
};
static int isExtensionSupported(const char *extList, const char *extension)
{
const char *start;
const char *where, *terminator;
/* Extension names should not have spaces. */
where = strchr(extension, ' ');
if ( where || *extension == '\0' )
return 0;
/* It takes a bit of care to be fool-proof about parsing the
OpenGL extensions string. Don't be fooled by sub-strings,
etc. */
for ( start = extList; ; ) {
where = strstr( start, extension );
if ( !where )
break;
terminator = where + strlen( extension );
if ( where == start || *(where - 1) == ' ' )
if ( *terminator == ' ' || *terminator == '\0' )
return 1;
start = terminator;
}
return 0;
}
static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
{
return d && e && arg && (e->type == MapNotify) && (e->xmap.window == *(Window*)arg);
}
static void describe_fbconfig(GLXFBConfig fbconfig)
{
int doublebuffer;
int red_bits, green_bits, blue_bits, alpha_bits, depth_bits;
glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_DOUBLEBUFFER, &doublebuffer);
glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_RED_SIZE, &red_bits);
glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_GREEN_SIZE, &green_bits);
glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_BLUE_SIZE, &blue_bits);
glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_ALPHA_SIZE, &alpha_bits);
glXGetFBConfigAttrib(Xdisplay, fbconfig, GLX_DEPTH_SIZE, &depth_bits);
fprintf(stderr, "FBConfig selected:\n"
"Doublebuffer: %s\n"
"Red Bits: %d, Green Bits: %d, Blue Bits: %d, Alpha Bits: %d, Depth Bits: %d\n",
doublebuffer == True ? "Yes" : "No",
red_bits, green_bits, blue_bits, alpha_bits, depth_bits);
}
static void createTheWindow()
{
XEvent event;
int x,y, attr_mask;
XSizeHints hints;
XWMHints *startup_state;
XTextProperty textprop;
XSetWindowAttributes attr = {0,};
static char *title = "FTB's little OpenGL example - ARGB extension by WXD";
Xdisplay = XOpenDisplay(NULL);
if (!Xdisplay) {
fatalError("Couldn't connect to X server\n");
}
Xscreen = DefaultScreen(Xdisplay);
Xroot = RootWindow(Xdisplay, Xscreen);
fbconfigs = glXChooseFBConfig(Xdisplay, Xscreen, VisData, &numfbconfigs);
fbconfig = 0;
for(int i = 0; i<numfbconfigs; i++) {
visual = (XVisualInfo*) glXGetVisualFromFBConfig(Xdisplay, fbconfigs[i]);
if(!visual)
continue;
pict_format = XRenderFindVisualFormat(Xdisplay, visual->visual);
if(!pict_format)
continue;
fbconfig = fbconfigs[i];
if(pict_format->direct.alphaMask > 0) {
break;
}
}
if(!fbconfig) {
fatalError("No matching FB config found");
}
describe_fbconfig(fbconfig);
/* Create a colormap - only needed on some X clients, eg. IRIX */
cmap = XCreateColormap(Xdisplay, Xroot, visual->visual, AllocNone);
attr.colormap = cmap;
attr.background_pixmap = None;
attr.border_pixmap = None;
attr.border_pixel = 0;
attr.event_mask =
StructureNotifyMask |
EnterWindowMask |
LeaveWindowMask |
ExposureMask |
ButtonPressMask |
ButtonReleaseMask |
OwnerGrabButtonMask |
KeyPressMask |
KeyReleaseMask;
attr_mask =
CWBackPixmap|
CWColormap|
CWBorderPixel|
CWEventMask;
width = DisplayWidth(Xdisplay, DefaultScreen(Xdisplay))/2;
height = DisplayHeight(Xdisplay, DefaultScreen(Xdisplay))/2;
x=width/2, y=height/2;
window_handle = XCreateWindow( Xdisplay,
Xroot,
x, y, width, height,
0,
visual->depth,
InputOutput,
visual->visual,
attr_mask, &attr);
if( !window_handle ) {
fatalError("Couldn't create the window\n");
}
#if USE_GLX_CREATE_WINDOW
int glXattr[] = { None };
glX_window_handle = glXCreateWindow(Xdisplay, fbconfig, window_handle, glXattr);
if( !glX_window_handle ) {
fatalError("Couldn't create the GLX window\n");
}
#else
glX_window_handle = window_handle;
#endif
textprop.value = (unsigned char*)title;
textprop.encoding = XA_STRING;
textprop.format = 8;
textprop.nitems = strlen(title);
hints.x = x;
hints.y = y;
hints.width = width;
hints.height = height;
hints.flags = USPosition|USSize;
startup_state = XAllocWMHints();
startup_state->initial_state = NormalState;
startup_state->flags = StateHint;
XSetWMProperties(Xdisplay, window_handle,&textprop, &textprop,
NULL, 0,
&hints,
startup_state,
NULL);
XFree(startup_state);
XMapWindow(Xdisplay, window_handle);
XIfEvent(Xdisplay, &event, WaitForMapNotify, (char*)&window_handle);
if ((del_atom = XInternAtom(Xdisplay, "WM_DELETE_WINDOW", 0)) != None) {
XSetWMProtocols(Xdisplay, window_handle, &del_atom, 1);
}
}
static int ctxErrorHandler( Display *dpy, XErrorEvent *ev )
{
fputs("Error at context creation", stderr);
return 0;
}
static void createTheRenderContext()
{
int dummy;
if (!glXQueryExtension(Xdisplay, &dummy, &dummy)) {
fatalError("OpenGL not supported by X server\n");
}
#if USE_GLX_CREATE_CONTEXT_ATTRIB
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
render_context = NULL;
if( isExtensionSupported( glXQueryExtensionsString(Xdisplay, DefaultScreen(Xdisplay)), "GLX_ARB_create_context" ) ) {
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
if( glXCreateContextAttribsARB ) {
int context_attribs[] =
{
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
//GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
None
};
int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
render_context = glXCreateContextAttribsARB( Xdisplay, fbconfig, 0, True, context_attribs );
XSync( Xdisplay, False );
XSetErrorHandler( oldHandler );
fputs("glXCreateContextAttribsARB failed", stderr);
} else {
fputs("glXCreateContextAttribsARB could not be retrieved", stderr);
}
} else {
fputs("glXCreateContextAttribsARB not supported", stderr);
}
if(!render_context)
{
#else
{
#endif
render_context = glXCreateNewContext(Xdisplay, fbconfig, GLX_RGBA_TYPE, 0, True);
if (!render_context) {
fatalError("Failed to create a GL context\n");
}
}
if (!glXMakeContextCurrent(Xdisplay, glX_window_handle, glX_window_handle, render_context)) {
fatalError("glXMakeCurrent failed for window\n");
}
}
static int updateTheMessageQueue()
{
XEvent event;
XConfigureEvent *xc;
while (XPending(Xdisplay))
{
XNextEvent(Xdisplay, &event);
switch (event.type)
{
case ClientMessage:
if (event.xclient.data.l[0] == del_atom)
{
return 0;
}
break;
case ConfigureNotify:
xc = &(event.xconfigure);
width = xc->width;
height = xc->height;
break;
}
}
return 1;
}
/* 6----7
/| /|
3----2 |
| 5--|-4
|/ |/
0----1
*/
GLfloat cube_vertices[][8] = {
/* X Y Z Nx Ny Nz S T */
{-1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0}, // 0
{ 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0}, // 1
{ 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0}, // 2
{-1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0}, // 3
{ 1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0}, // 4
{-1.0, -1.0, -1.0, 0.0, 0.0, -1.0, 1.0, 0.0}, // 5
{-1.0, 1.0, -1.0, 0.0, 0.0, -1.0, 1.0, 1.0}, // 6
{ 1.0, 1.0, -1.0, 0.0, 0.0, -1.0, 0.0, 1.0}, // 7
{-1.0, -1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0}, // 5
{-1.0, -1.0, 1.0, -1.0, 0.0, 0.0, 1.0, 0.0}, // 0
{-1.0, 1.0, 1.0, -1.0, 0.0, 0.0, 1.0, 1.0}, // 3
{-1.0, 1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 1.0}, // 6
{ 1.0, -1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0}, // 1
{ 1.0, -1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.0}, // 4
{ 1.0, 1.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0}, // 7
{ 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0}, // 2
{-1.0, -1.0, -1.0, 0.0, -1.0, 0.0, 0.0, 0.0}, // 5
{ 1.0, -1.0, -1.0, 0.0, -1.0, 0.0, 1.0, 0.0}, // 4
{ 1.0, -1.0, 1.0, 0.0, -1.0, 0.0, 1.0, 1.0}, // 1
{-1.0, -1.0, 1.0, 0.0, -1.0, 0.0, 0.0, 1.0}, // 0
{-1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0}, // 3
{ 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0}, // 2
{ 1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 1.0, 1.0}, // 7
{-1.0, 1.0, -1.0, 0.0, 1.0, 0.0, 0.0, 1.0}, // 6
};
static void draw_cube(void)
{
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(GLfloat) * 8, &cube_vertices[0][0]);
glNormalPointer(GL_FLOAT, sizeof(GLfloat) * 8, &cube_vertices[0][3]);
glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat) * 8, &cube_vertices[0][6]);
glDrawArrays(GL_QUADS, 0, 24);
}
float const light0_dir[]={0,1,0,0};
float const light0_color[]={78./255., 80./255., 184./255.,1};
float const light1_dir[]={-1,1,1,0};
float const light1_color[]={255./255., 220./255., 97./255.,1};
float const light2_dir[]={0,-1,0,0};
float const light2_color[]={31./255., 75./255., 16./255.,1};
static void redrawTheWindow()
{
float const aspect = (float)width / (float)height;
static float a=0;
static float b=0;
static float c=0;
glDrawBuffer(GL_BACK);
glViewport(0, 0, width, height);
// Clear with alpha = 0.0, i.e. full transparency
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-aspect, aspect, -1, 1, 2.5, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glLightfv(GL_LIGHT0, GL_POSITION, light0_dir);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_color);
glLightfv(GL_LIGHT1, GL_POSITION, light1_dir);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_color);
glLightfv(GL_LIGHT2, GL_POSITION, light2_dir);
glLightfv(GL_LIGHT2, GL_DIFFUSE, light2_color);
glTranslatef(0., 0., -5.);
glRotatef(a, 1, 0, 0);
glRotatef(b, 0, 1, 0);
glRotatef(c, 0, 0, 1);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHT1);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glColor4f(1., 1., 1., 0.5);
glCullFace(GL_FRONT);
draw_cube();
glCullFace(GL_BACK);
draw_cube();
a = fmod(a+0.1, 360.);
b = fmod(b+0.5, 360.);
c = fmod(c+0.25, 360.);
glXSwapBuffers(Xdisplay, glX_window_handle);
}
int main(int argc, char *argv[])
{
createTheWindow();
createTheRenderContext();
while (updateTheMessageQueue()) {
redrawTheWindow();
}
return 0;
}
I take this from this link
I spend 10-15 min to find difference between this example and my code and 3-4 hours to get on my mind that i must change something on KDE
Thank for solicitude
This is definitely something that you will want to offload to the GPU. I would not recommend directly using the X11 lib for performance reasons. Let OpenGL do it. I did find the following link for glXChooseVisual.
Also, here is another S.O. question that may be helpful.
Furthermore, this is for windows, but it should still apply.
In order to have a transparent window under X11, you need
an X11 server with composite extension
a composite manager
an ARGB visual for your window
You don't need to use OpenGL directly: the composite manager could use it to render the screen.
If you're going in the GTK path, have a look to
gdk_x11_display_composite
gdk_screen_is_composited
gdk_display_supports_composite
gdk_screen_get_rgba_visual
gdk_screen_get_rgba_colormap
But you could also use Qt or another toolkit.
Related
Two spheres collision
I have to make a program which is doing the collision between two spheres. I made this but when the spheres collide everything is blocked. I can't move the sphere anymore. I made only the sphere1 to move and the other to be static. The code is written in VB/ C++. #include "GLOS.H" #include <math.h> #include <GL/gl.h> #include <GL/glu.h> #include <glaux.h> GLfloat max1=0,max2=0,v,v1; FLOAT d,distanta=0; int i,j; void myinit(void); void CALLBACK display(void); void CALLBACK myReshape(GLsizei w, GLsizei h); void CALLBACK MutaStanga(void); void CALLBACK MutaDreapta(void); int k=0,k1=0; int dist_ramasa; static float dx1=200,dy1=300,dz1=0; int deplasare=100; float rez; static int flag=1; float pxc,pyc,pzc,sum,suma_raze; void myinit (void) { //iluminating glClearColor(1.0, 1.0, 1.0, 1.0); GLfloat mat_ambient[] = { 0.3, 0.3, 0.3, 1.0 }; GLfloat mat_diffuse[] = { 0.8, 0.8, 0.8, 1.0 }; GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_shininess[] = { 100.0 }; GLfloat light_ambient[] = { 0.4, 0.4, 0.4, 1.0 }; GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat light_position[] = { 1.0, 1.0, 0.0, 0.0 }; GLfloat lmodel_ambient[] = { 0.5, 0.5, 0.5, 1.0 }; glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient); glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); glEnable(GL_LIGHTING); // activare iluminare glEnable(GL_LIGHT0); // activare sursa 0 glColorMaterial(GL_FRONT,GL_DIFFUSE); glEnable(GL_COLOR_MATERIAL); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); } struct sfera //the spheres { GLfloat raza, xcentru, ycentru, zcentru; //the radius and the centers GLfloat xd1,xd2,yd1,yd2,zd1,zd2; }sf[2]; void initRaza(){ //radius init sf[0].raza=100; sf[1].raza=100; } int conditie(void){ //this is where I verify if collide initRaza(); double xac1,yac1,zac1,xac2,yac2,zac2;//the new centers after the movement xac1=sf[0].xcentru+dx1; yac1=sf[0].ycentru+dy1; zac1=sf[0].zcentru+dz1; //static sphere xac2=sf[1].xcentru+700; yac2=sf[1].ycentru+300; zac2=sf[1].zcentru; pxc = pow((xac1-xac2),2); pyc = pow((yac1-yac2),2); pzc = pow((zac1-zac2),2); sum=(pxc + pyc + pzc); distanta=sqrt(sum); //the distance between the centers //the sum of the radiuses suma_raze=sf[0].raza+sf[1].raza; dist_ramasa=distanta-sf[0].raza-sf[1].raza; // we compare the distance and the sum of radiuses //if the distance is lower than the sum -> collide if(distanta>suma_raze) return 1; else return 0; } void CALLBACK MutaStanga(void) //movement left { if(conditie()==1){ if(dist_ramasa<deplasare) dx1=dx1-dist_ramasa; else dx1=dx1-deplasare; } } void CALLBACK MutaDreapta(void) //movement right { if(conditie()==1){ if(dist_ramasa<deplasare) dx1=dx1+dist_ramasa; else dx1=dx1+deplasare; } } void CALLBACK MutaSus(void) //movement up { if(conditie()==1){ if(dist_ramasa<deplasare) dy1=dy1+dist_ramasa; else dy1=dy1+deplasare; } } void CALLBACK MutaJos(void) //movement down { if(conditie()==1){ if(dist_ramasa<deplasare) dy1=dy1-dist_ramasa; else dy1=dy1-deplasare; } } void drawBall1() //the first sphere { glPushMatrix(); glColor3f(0,1,0); glTranslatef(dx1, dy1, 0.0); glRotatef(30,1,0,0); auxSolidSphere(sf[0].raza); glPopMatrix(); } void drawBall2() //the second sphere { glPushMatrix(); glColor3f(1,0,0); glTranslatef(700,300,0); glRotatef(30,1,0,0); auxWireSphere(sf[1].raza); glPopMatrix(); } void CALLBACK display (void) { initRaza(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity (); drawBall1(); drawBall2(); auxSwapBuffers(); } void CALLBACK myReshape(GLsizei w, GLsizei h) { if (!h) return; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho (0, 800.0, 0*(GLfloat)h/(GLfloat)w, -860.0*(GLfloat)h/(GLfloat)w, -200.0, 200.0); else glOrtho (0*(GLfloat)w/(GLfloat)h, 900.0*(GLfloat)w/(GLfloat)h, 0, 900.0, -500.0, 500.0); glMatrixMode(GL_MODELVIEW); } int main(int argc, char** argv) { auxInitDisplayMode (AUX_SINGLE | AUX_RGB | AUX_DEPTH16); auxInitPosition (0, 0, 900, 700); auxInitWindow ("Bounding sphere collision"); myinit (); auxKeyFunc (AUX_LEFT, MutaStanga); auxKeyFunc (AUX_RIGHT, MutaDreapta); auxKeyFunc (AUX_UP, MutaSus); auxKeyFunc(AUX_DOWN,MutaJos); auxReshapeFunc (myReshape); auxMainLoop(display); return(0); } I don't know what is not working. When they collide I want to reject each other . I hope you can help me.
Once the spheres collide, your function conditie will return 1. All your keypress functions check this before modifying the sphere's position, thus, once they collide, you can no longer move the sphere.
opengl rotate an object around fixed axes
Hi I'm trying to implement a opengl program with rotation&translation. But I got this problem that, the world axes will rotating along with my object(a cube). It's like, first I rotate cube along Z-axis, it works fine, then I middle-click the mouse and want to rotate the cube along the original Y-axis. At the moment I click, the cube will stop rotating along Z and start to rotate along Y. But it turns out it will rotate along a "new and invisible" Y-axis. I figure out that's because when I rotate the cube along Z with glRotatef(), the other two axis:X,Y also rotate. How can I fix the axes when I'm rotating the cube. I know the glRotatef() will multiply all matrix in screen with a rotation axis, so I tried added a glLoadIdentity() in each rotation but it still not work. can anyone give me the solution? the code is here for reference: #include <stdlib.h> #include <GL/glut.h> #include <iostream> GLfloat vertices[8][3] = { { -1.0, -1.0, -1.0 }, { 1.0, -1.0, -1.0 }, { 1.0, 1.0, -1.0 }, { -1.0, 1.0, -1.0 }, { -1.0, -1.0, 1.0 }, { 1.0, -1.0, 1.0 }, { 1.0, 1.0, 1.0 }, { -1.0, 1.0, 1.0 } }; GLuint listName; GLfloat theta[3] = { 0.0, 0.0, 0.0 }; GLint axis = 2; GLfloat delta = 0.02; GLint stop = 0; GLfloat distance = 0; void face(int a, int b, int c, int d) { glBegin(GL_POLYGON); //glColor3fv(colors[a]); glVertex3fv(vertices[a]); //glColor3fv(colors[b]); glVertex3fv(vertices[b]); //glColor3fv(colors[c]); glVertex3fv(vertices[c]); //glColor3fv(colors[d]); glVertex3fv(vertices[d]); glEnd(); } void cube(void) { glColor3f(1.0f,1.0f,1.0f); face(0, 3, 2, 1); face(2, 3, 7, 6); face(0, 4, 7, 3); face(1, 2, 6, 5); face(4, 5, 6, 7); face(0, 1, 5, 4); glutWireCube(2.5f); glutPostRedisplay(); } void drawAxis(void){ // save previous matrix glPushMatrix(); // clear matrix glLoadIdentity(); // draw our axes glRotatef(45.0, 1.0, 0.0, 0.0); glRotatef(45.0, 0.0, -1.0, 0.0); glBegin(GL_LINES); // draw line for x axis glColor3f(1.0, 0.0, 0.0); glVertex3f(0.0, 0.0, 0.0); glVertex3f(10.0, 0.0, 0.0); // draw line for y axis glColor3f(0.0, 1.0, 0.0); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0, 10.0, 0.0); // draw line for Z axis glColor3f(0.0, 0.0, 1.0); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0, 0.0, 10.0); glEnd(); // load the previous matrix glPopMatrix(); glutPostRedisplay(); } void spinCube() { theta[axis] += delta; if (theta[axis] > 360.0) theta[axis] -= 360.0; glutPostRedisplay(); } void display(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glRotatef(45.0, 1.0, 0.0, 0.0); glRotatef(45.0, 0.0, -1.0, 0.0); drawAxis(); glPushMatrix(); glRotatef(theta[0], 1.0, 0.0, 0.0); glRotatef(theta[1], 0.0, 1.0, 0.0); glRotatef(theta[2], 0.0, 0.0, 1.0); glTranslatef(0.0, 0.0, distance + 2.0); glCallList(listName); glPopMatrix(); glutSwapBuffers(); } void myReshape(int w, int h) { GLfloat aspect = (GLfloat) w / (GLfloat) h; glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho(-10.0, 10.0, -10.0 / aspect, 10.0 / aspect, -50.0, 50.0); else glOrtho(-10.0*aspect, 10.0*aspect, -10.0, 10.0, -50.0, 50.0); glMatrixMode(GL_MODELVIEW); } void mouse(int btn, int state, int x, int y) { if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { axis = 0; } if (btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) { axis = 1; } if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) { axis = 2; } } void keyboard(unsigned char key, int x, int y) { if (key == 'q' || key == 'Q') exit(0); if (key == ' ') { stop = !stop; } if (stop) glutIdleFunc(NULL); else glutIdleFunc(spinCube); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB); glutInitWindowSize(600, 600); glutCreateWindow("cube"); glutReshapeFunc(myReshape); glutDisplayFunc(display); glutIdleFunc(spinCube); glutMouseFunc(mouse); glutKeyboardFunc(keyboard); //creating a display list: listName = glGenLists(1); glNewList(listName, GL_COMPILE); cube(); glEndList(); glEnable(GL_DEPTH_TEST); glutMainLoop(); return 0; }
What you're after might be accumulating arbitrary rotations. This can't be done with euler angles, which gimbal lock. It's pretty common to have euler angle rotations and in most cases the issue is simply to do with the order they're applied in. The first thing I'd suggest is to reverse the order of your x/y/z rotations. Next, if you want to accumulate rotations you'll really want to get into quaternions. This can be done with matrices but can easily become numerically unstable. Quaternions can be normalized which solves this issue. If you rotate around X, the first call is of course, glRotatef(a, 1, 0, 0); draw(). Then you want to rotate the object and its current rotation around y. Note that the object and current rotation are grouped in this line of thinking. So you glRotatef(b, 0, 1, 0); glRotatef(a, 1, 0, 0); draw();. Each time you rotate, you add the rotation behind the existing list of transforms. If you added in front, it'd transform the object in its local space and not global. What you could do is this (near-pseudo-code with an imaginary matrix implementation): Keep a current object transform matrix M In spinCube, M = rotationMatrix(delta, axis==0?1:0, axis==1?1:0, axis==2?1:0) * M (note it's rotation * M and not M * rotation. Before you draw the cube, glMultMatrixf(M.data) The problem is floating point error will build up over time and the matrix will start to skew/scale your object in weird ways. Instead, you'll want a quaternion implementation (again near-pseudo-code): Q = rotationQuaternion(delta, axis==0?1:0, axis==1?1:0, axis==2?1:0) * Q Q.normalize() ... glMultMatrixf(Q.toMatrix().data)
glEvalCoord when used with glFeedback is not giving output as expected
I am trying to read the value from glEvalCoord, but not getting the exact values which I should get. My code is GLfloat ctrlpoints[4][3] = { { -4.0, -4.0, 0.0}, { -2.0, 4.0, 0.0}, { 2.0, -4.0, 0.0}, { 4.0, 4.0, 0.0}}; void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glEnable(GL_LIGHTING); glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]); glEnable(GL_MAP1_VERTEX_3); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); GLint size; GLfloat feedBuffer[1024]; glFeedbackBuffer (1024, GL_3D, feedBuffer); glRenderMode (GL_FEEDBACK); glBegin (GL_POINTS); for (int i=0; i<=30; ++i) { GLfloat t = GLfloat(i)/30; glEvalCoord1f(t); } glEnd(); size = glRenderMode (GL_RENDER); cerr<<size<<endl; } Now, I am not sure but shouldn't it give me 30*3 values for each of the x, y and z coordinates of the curve?? But I am getting only 7*3 values. And the output of size is 28.
I think your size is 28 because your projection/modelview pair is clipping out some points. "In feedback mode, each primitive that would be rasterized ... generates a block of values that's copied into the feedback array." Try this: #include <GL/glut.h> #include <iostream> using namespace std; void display() { glClear( GL_COLOR_BUFFER_BIT ); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); double w = glutGet( GLUT_WINDOW_WIDTH ); double h = glutGet( GLUT_WINDOW_HEIGHT ); double ar = w / h; glOrtho( -5 * ar, 5 * ar, -5, 5, -1, 1 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); GLfloat ctrlpoints[4][3] = { { -4.0, -4.0, 0.0 }, { -2.0, 4.0, 0.0 }, { 2.0, -4.0, 0.0 }, { 4.0, 4.0, 0.0 } }; glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, &ctrlpoints[0][0]); glEnable(GL_MAP1_VERTEX_3); GLfloat feedBuffer[1024]; glFeedbackBuffer (1024, GL_3D, feedBuffer); glRenderMode (GL_FEEDBACK); glPointSize( 5 ); glColor3ub( 255, 255, 255 ); glBegin (GL_POINTS); for (int i=0; i<=30; ++i) { GLfloat t = GLfloat(i)/30; glEvalCoord1f(t); } glEnd(); GLint size = glRenderMode (GL_RENDER); cerr << size << endl; glutSwapBuffers(); } int main( int argc, char **argv ) { glutInit( &argc, argv ); glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE ); glutInitWindowSize( 640, 480 ); glutCreateWindow( "GLUT" ); glutDisplayFunc( display ); glutMainLoop(); return 0; } I added a slightly larger projection matrix. With that I get a size of 124: 31 points * 3 floats per point = 93 31 points * 1 GL_POINT_TOKEN per point = 31 31 + 91 = 124
OpenGL evaluator only partially lit
I was trying to make a small wave generator in OpenGL with C++, using an evaluator. However, I haven't had much luck since my evaluator only gets partially lit. Why does this happen? Below I include full source code for completeness' sake, you'll probably only have to look at init(), display() and the constants at the top of the file. #include <gl/glui.h> #include <math.h> const int DIMX = 500; const int DIMY = 500; const int INITIALPOS_X = 200; const int INITIALPOS_Y = 200; // Aspect ratio (calculated on the fly) float xy_aspect; // UI aux. matrices float view_rotate[16] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 }; float obj_pos[] = { 0.0, 0.0, 0.0 }; float obj_pan[] = { 0.0, 0.0, 0.0 }; // Referential axis double axis_radius_begin = 0.2; double axis_radius_end = 0.0; double axis_lenght = 16.0; int axis_nslices = 8; int axis_nstacks = 1; // Light 0 properties float light0_position[] = {5.0, 5.0, 5.0, 0.0}; float light0_ambient[] = {0.0, 0.0, 0.0, 1.0}; float light0_diffuse[] = {0.6, 0.6, 0.6, 1.0}; float light0_specular[] = {1.0, 1.0, 1.0, 1.0}; float light0_kc = 0.0; float light0_kl = 1.0; float light0_kq = 0.0; double light0x = 5.0; double light0y = 5.0; double light0z = 5.0; double symb_light0_radius = 0.2; int symb_light0_slices = 8; int symb_light0_stacks =8; // Ambient light source properties float light_ambient[] = {0.5, 0.5, 0.5, 1.0}; /* Set the background ambient lighting. */ // Windowing related variables int main_window; GLUquadric* glQ; GLUI *glui; const unsigned int gridSize = 40; float grid[gridSize][gridSize][3]; const int uSize = gridSize; const int vSize = gridSize; GLfloat ambient[] = {0.2, 0.2, 0.2, 1.0}; GLfloat position[] = {0.0, 0.0, 2.0, 1.0}; GLfloat mat_diffuse[] = {0.6, 0.6, 0.6, 1.0}; GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0}; float mat_shininess[] = {50.0}; void display(void) { static float value = 0; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glFrustum( -xy_aspect*.04, xy_aspect*.04, -.04, .04, .1, 50.0 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef( obj_pos[0], obj_pos[1], -obj_pos[2]-25 ); glTranslatef( obj_pan[0], obj_pan[1], obj_pan[2] ); glRotated( 20.0, 1.0,0.0,0.0 ); glRotated(-45.0, 0.0,1.0,0.0 ); glMultMatrixf( view_rotate ); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); glColor3f(1.0,0.0,0.0); glPushMatrix(); glRotated(90.0, 0.0,1.0,0.0 ); gluCylinder(glQ, axis_radius_begin, axis_radius_end, axis_lenght, axis_nslices, axis_nstacks); glPopMatrix(); glColor3f(0.0,1.0,0.0); glPushMatrix(); glRotated(-90.0, 1.0,0.0,0.0 ); gluCylinder(glQ, axis_radius_begin, axis_radius_end, axis_lenght, axis_nslices, axis_nstacks); glPopMatrix(); glColor3f(0.0,0.0,1.0); glPushMatrix(); gluCylinder(glQ, axis_radius_begin, axis_radius_end, axis_lenght, axis_nslices, axis_nstacks); glPopMatrix(); light0_position[0] = light0x; light0_position[1] = light0y; light0_position[2] = light0z; glLightfv(GL_LIGHT0, GL_POSITION, light0_position); glColor3f(1.0,1.0,0.0); gluQuadricOrientation( glQ, GLU_INSIDE); glPushMatrix(); glTranslated(light0x,light0y,light0z); gluSphere(glQ, symb_light0_radius, symb_light0_slices, symb_light0_stacks); glPopMatrix(); gluQuadricOrientation( glQ, GLU_OUTSIDE); gluQuadricDrawStyle(glQ, GLU_FILL); gluQuadricNormals(glQ, GLU_SMOOTH); gluQuadricOrientation(glQ, GLU_OUTSIDE); gluQuadricTexture(glQ, GL_FALSE); for (unsigned int y = 0; y < vSize; ++y) { for (unsigned int x = 0; x < uSize; ++x) { float xVal = 5*3.14/gridSize*x; float yVal = 5*3.14/gridSize*y; grid[y][x][0] = (float) x/gridSize*10.0; grid[y][x][1] = sin(xVal + value) + sin(yVal + value); grid[y][x][2] = (float) y/gridSize*10.0; } } glMap2f(GL_MAP2_VERTEX_3, 0, 1 , 3, uSize, 0, 1, uSize * 3, vSize, &grid[0][0][0]); glEvalMesh2(GL_FILL, 0, gridSize, 0, gridSize); value += 3.14/25; if (value > 3.14*2) value = 0; // swapping the buffers causes the rendering above to be shown glutSwapBuffers(); glFlush(); } /* Mouse handling */ void processMouse(int button, int state, int x, int y) { if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { } if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) { } glutPostRedisplay(); } void processMouseMoved(int x, int y) { // pedido de refrescamento da janela glutPostRedisplay(); } void processPassiveMouseMoved(int x, int y) { // pedido de refrescamento da janela glutPostRedisplay(); } void reshape(int w, int h) { int tx, ty, tw, th; GLUI_Master.get_viewport_area( &tx, &ty, &tw, &th ); glViewport( tx, ty, tw, th ); xy_aspect = (float)tw / (float)th; glutPostRedisplay(); } void keyboard(unsigned char key, int x, int y) { switch (key) { case 27: // tecla de escape termina o programa exit(0); break; } } void glut_idle( void ) { if ( glutGetWindow() != main_window ) glutSetWindow(main_window); glutPostRedisplay(); } void init() { glQ = gluNewQuadric(); glFrontFace(GL_CCW); // Front faces defined using a counterclockwise rotation glDepthFunc(GL_LEQUAL); // Por defeito e GL_LESS glEnable(GL_DEPTH_TEST); // Use a depth (z) buffer to draw only visible objects glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); // Face Culling para aumentar a velocidade glEnable(GL_CULL_FACE); glCullFace(GL_BACK); // GL_FRONT, GL_BACK, GL_FRONT_AND_BACK // Define que modelo de iluminacao utilizar; consultar o manual de referencia glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light_ambient); // define luz ambiente glLightModelf (GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); glLightModeli (GL_LIGHT_MODEL_LOCAL_VIEWER, 1); // por defeito a cor de fundo e o preto // glClearColor(1.0,1.0,1.0,1.0); // cor de fundo a branco // declaracoes para a fonte luz GL_LIGHT0 glLightfv(GL_LIGHT0, GL_AMBIENT, light0_ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, light0_diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, light0_specular); glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, light0_kc); glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, light0_kl); glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, light0_kq); // NOTA: a direccao e a posicao de GL_LIGHT0 estao na rotina display(), pelo // que as isntrucoes seguntes nao sao necessarias //glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 90.0); //glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spot_direction); //glLightfv(GL_LIGHT0, GL_POSITION, light0_position); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_NORMALIZE); glEnable(GL_MAP2_VERTEX_3); glMapGrid2f(gridSize, 0.0, 1.0, gridSize, 0.0, 1.0); glShadeModel(GL_SMOOTH); glPolygonMode(GL_FRONT, GL_FILL); //glPolygonMode(GL_FRONT, GL_LINE); } void do_nothing(int key, int x, int y) {} int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowSize (DIMX, DIMY); glutInitWindowPosition (INITIALPOS_X, INITIALPOS_Y); main_window = glutCreateWindow (argv[0]); glutDisplayFunc(display); GLUI_Master.set_glutReshapeFunc(reshape); GLUI_Master.set_glutKeyboardFunc (keyboard); GLUI_Master.set_glutMouseFunc(processMouse); glutMotionFunc(processMouseMoved); glutPassiveMotionFunc(processPassiveMouseMoved); GLUI_Master.set_glutSpecialFunc( do_nothing ); /*** Create the bottom subwindow ***/ glui = GLUI_Master.create_glui_subwindow( main_window, GLUI_SUBWINDOW_BOTTOM ); glui->set_main_gfx_window( main_window ); GLUI_Rotation *view_rot = glui->add_rotation( "Rotation", view_rotate ); view_rot->set_spin( 1.0 ); glui->add_column( false ); GLUI_Translation *trans_z = glui->add_translation( "Zoom", GLUI_TRANSLATION_Z, &obj_pos[2] ); trans_z->set_speed( .1 ); glui->add_column(false); GLUI_Translation *trans_pan = glui->add_translation("Pan", GLUI_TRANSLATION_XY, &obj_pan[0]); trans_pan->set_speed(.1); GLUI_Master.set_glutIdleFunc( glut_idle ); init(); glutMainLoop(); return 0; }
You say OpenGL evaluators don't need normals to set. This is only partly true. You only don't need to set normals if you enable automatically generated normals for evaluators by calling: glEnable(GL_AUTO_NORMAL); Just enabling GL_NORMALIZE won't do it. But you can of course also specify your own normals by providing control points for GL_MAP2_NORMAL in the same way like for GL_MAP2_VERTEX_3. And the answer won't be complete without mentioning that OpenGL evaluators are highly deprecated and most probably implemented in softare by the driver. So just rolling your own Bezier evaluation code (which is not very hard) and generating a simple mesh grid drawn as GL_TRIANGLES will surely be a better idea.
3d array c/c++ initialization/conversion
float sampleGrid1[5][5][5] = { { {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0} }, { {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0} }, { {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 1.0, 1.0, 1.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0} }, { {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0} }, { {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0} } }; typedef struct { int Nx; int Ny; int Nz; float*** M; }OG; Relevant function: OG *newOG(){ OG *newOG = (OG *)malloc(sizeof(OG)); if (newOG == NULL) { throw std::exception("newOG : no memory is available"); } return newOG; } int initiateOG(OG *MyOG) { ifstream dump("OGdump3.txt"); if (dump.is_open()) { while ( dump.good() ) { dump >> MyOG->Nx; dump >> MyOG->Ny; dump >> MyOG->Nz; MyOG->M = new float**[MyOG->Nx]; for(int i = 0; i < MyOG->Nx; i++) { MyOG->M[i] = new float*[MyOG->Ny]; for(int j = 0; j < MyOG->Ny; j++) { MyOG->M[i][j] = new float[MyOG->Nz]; } } for(int z=0;z < MyOG->Nz; z++){ for(int y=0;y < MyOG->Ny; y++){ for(int x=0;x < MyOG->Nx; x++){ dump >> MyOG->M[x][y][z]; } } } } dump.close(); } else return 0; return 1; } I want to hard code some sample grids into the code, but don't know the best way to create them, do i have to use for loops? i don't want to change my typedef struct OG, if possible Modified: OG *occupancyGrid; void initialize3dArray(int x, int y, int z,float*** array) { array = new float**[x]; for(int i = 0; i < x; i++) { array[i] = new float*[y]; for(int j = 0; j < y; j++) { array[i][j] = new float[z]; } } } void sampleOG1() { occupancyGrid = newOG(); occupancyGrid->Nx = 5; occupancyGrid->Ny = 5; occupancyGrid->Nz = 5; initialize3dArray(5, 5, 5,occupancyGrid->M); for(int z=0;z < occupancyGrid->Nz; z++){ for(int y=0;y < occupancyGrid->Ny; y++){ for(int x=0;x < occupancyGrid->Nx; x++){ occupancyGrid->M[x][y][z] = sampleGrid1[x][y][z]; } } } } initialize3dArray this function doesn't have compiling error, but still causing the program to crash
Yes. that will not compile, because float[5][5][5] and float *** aren't same type. They're not even compatible type. One cannot convert to other automatically. However, float[5][5][5] can convert to float (*)[5][5] automatically. So this is legal code: float (*m)[5][5]; m = sampleGrid1; //legal - allowed! Demo : http://ideone.com/RwAwI So define OG as, struct OG { int Nx; int Ny; int Nz; float (*M)[5][5]; }; If you OG as defined above, then you can write this: OG* temp = newOG(); temp->Nx = 5; temp->Ny = 5; temp->Nz = 5; occupancyGrid->M = sampleGrid1; //DONT use &
Isn't the error clear? float[5][5][5] is not as related to float*** as you think it is. Use a std::vector<std::vector<std::vector<float> > > instead and avoid the whole mess.
float x[2][2] is a 2D array of float - it's not an 1D array of pointers to float. The conversion from array to pointer only works for the first dimension of such arrays. Given float x[2][2] you reserve space for 4 floats. A float ** variable on the other hand is a pointer to a pointer to a float - there's no pointers anywhere in float x[2][2] The same of course holds true for a 3D array - your 3D array has no sneakily hidden pointers inside it, it cannot be treated as a float ***