3d array c/c++ initialization/conversion - c++

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 ***

Related

How to use the ROS tf listener to get the transform and apply it to my velocity data?

I have velocity data from the sensor, but somehow it is not in the robot body frame. It's been in a world frame, so it's not correct. So I need to transform it in the robot body frame as that how should be in the correct way. So I need a listener that will listen for transformations to be broadcast. Once broadcast I can use the listener to get the transform and apply it to your data.
I made a ROS nodes for broadcast and listener. But is still not correct the velocity. Here is the sensor data that include the linear velocity and its looks like this:
header:
seq: 182
stamp:
secs: 39
nsecs: 244000000
frame_id: "world"
child_frame_id: "rexrov2/base_link"
pose:
pose:
position:
x: -0.0462157448086
y: -0.0175201465699
z: -18.7747349396
orientation:
x: 0.00029722877228
y: -0.000159403004117
z: -0.00433868890864
w: 0.999990530967
covariance: [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]
twist:
twist:
linear:
x: -0.00672636768741
y: -0.00264084973057
z: 0.204243325029
angular:
x: -7.4723382137e-05
y: -0.00310117164775
z: -0.00108493763869
covariance: [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]
Then the robot frame is rexrov2/base_linkand the sensor is rexrov2/pose_sensor_link_default. The frame broadcaster is this one
#include <ros/ros.h>
#include <tf2_ros/transform_broadcaster.h>
#include <geometry_msgs/TransformStamped.h>
#include <nav_msgs/Odometry.h>
#include <geometry_msgs/TwistStamped.h>
#include <geometry_msgs/Twist.h>
#include <tf2/LinearMath/Quaternion.h>
void poseCallback(const nav_msgs::Odometry::ConstPtr& msg){
static tf2_ros::TransformBroadcaster br;
geometry_msgs::TransformStamped transformStamped;
transformStamped.header.stamp = ros::Time::now();
transformStamped.header.frame_id = "world";
transformStamped.child_frame_id = "rexrov2/base_link";
transformStamped.transform.translation.x = msg->pose.pose.position.x;
transformStamped.transform.translation.y = msg->pose.pose.position.y;
transformStamped.transform.translation.z = msg->pose.pose.position.z;
transformStamped.transform.rotation.x = msg->pose.pose.orientation.x;
transformStamped.transform.rotation.y = msg->pose.pose.orientation.y;
transformStamped.transform.rotation.z = msg->pose.pose.orientation.z;
transformStamped.transform.rotation.w = msg->pose.pose.orientation.w;
br.sendTransform(transformStamped);
}
int main(int argc, char** argv){
ros::init(argc, argv, "my_tf2_broadcaster");
ros::NodeHandle node;
ros::Subscriber sub = node.subscribe("rexrov2/pose_gt", 10, &poseCallback);
ros::spin();
return 0;
};
And the listener node is this one
#include <ros/ros.h>
#include <tf2_ros/transform_listener.h>
#include <geometry_msgs/TransformStamped.h>
#include <geometry_msgs/Twist.h>
int main(int argc, char** argv){
ros::init(argc, argv, "my_tf2_listener");
ros::NodeHandle node;
ros::Publisher robot_vel =node.advertise<geometry_msgs::Twist>("robot/vel", 10);
tf2_ros::Buffer tfBuffer;
tf2_ros::TransformListener tfListener(tfBuffer);
ros::Rate rate(10.0);
while (node.ok()){
geometry_msgs::TransformStamped transformStamped;
try{
transformStamped = tfBuffer.lookupTransform("rexrov2/base_link", "world", ros::Time(0));
}
catch (tf2::TransformException &ex) {
ROS_WARN("%s",ex.what());
ros::Duration(1.0).sleep();
continue;
}
geometry_msgs::Twist vel_msg;
vel_msg.linear.x = 0.5 * sqrt(pow(transformStamped.transform.translation.x, 2) + pow(transformStamped.transform.translation.y, 2));
robot_vel.publish(vel_msg);
rate.sleep();
}
return 0;
};
The sensor data that is not in the correct frame is published under rexrov2/pose_gt and the robot base link is rexrov2/base_link. The warnings I'm getting are:
[ WARN] [1635767328.332529320, 14554.020000000]: "rexrov2/pose_gt" passed to lookupTransform argument target_frame does not exist.
Any help?Thanks
The warning you are getting is because you don't have the TF frames connected. Please check them out with
rosrun rqt_tf_tree rqt_tf_tree
It seems you are not publishing anywhere the transform between "rexrov2/pose_gt" and "rexrov2/base_link". So run this command in a separate terminal to publish the transform so your node can get it:
rosrun tf2_ros static_transform_publisher 0 0 0 0 0 0 1 rexrov2/pose_gt resrov2/base_link
If you stop receiving the warning running that command, it means that you need to include it in a launch file along with your node in order to run all at the same time
<launch>
<node pkg="tf2_ros" type="static_transform_publisher" name="base_link_to_gt_broadcaster" args="1 0 0 0 0 0 1 resrov2/base_link rexrov2/pose_gt" />
</launch>
And replace the transformation 1 0 0 0 0 0 1 (x y z qx qy qz qw) by the correct one
In addition to this, I don't see any subscriber in your code, but I think it's because you're using the node to do preliminar tests with the ROS integration

Segfault in Tranposed matrix multiplication with .eval() with Eigen 3 library

I added two .eval() just in case. I got no compilation error, and no run time warning. Just segfault.
Thanks for helping me to fix this.
Test:
#include <Eigen/Eigen>
#include <iostream>
using namespace Eigen;
int main() {
Matrix<float, Dynamic, Dynamic> mat_b;
Matrix<float, Dynamic, Dynamic> mat_c;
mat_b << 1.0, 0.0, 0.5, 0.5,
0.0, 1.0, 0.5, 0.5,
1.0, 0.0, 1.0, 0.0,
0.0, 1.0, 0.0, 1.0;
mat_c << 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
1.0, 0.0, 1.0, 0.0, 0.0, 0.0,
1.0, 0.0, 0.0, 1.0, 0.0, 0.0;
std::cout << (mat_b.transpose().eval() * mat_c).eval() << "\n";
}
Result:
Segmentation fault (core dumped)
As stated in documentatipon
The comma initializer
Eigen offers a comma initializer syntax which allows the user to easily set all the coefficients of a matrix, vector or array. Simply list the coefficients, starting at the top-left corner and moving from left to right and from the top to the bottom. The size of the object needs to be specified beforehand. If you list too few or too many coefficients, Eigen will complain.
emphasis is mine. If you expect that Matrix ctor would deduce size from your formatting, that simply not possible in C++. Looks like you created 16x1 and 24x1 matrix and then try to multiply 1x16 (transposed first one) to 24x1 which is not legal.

VTK volume rendering of mammography

I am working on vtk volume rendering of mammography. I have a 50 DICOM slices in folder to construct volume. Here I need to give vtkColorTransferFunction and vtkPiecewiseFunction to set RGB color and scalar opacity.
I am not getting exact values of color and opacity with respect to mammo images (breast images). I need values for color and opacity with respect to breast x-ray images.
Any suggestions will be helpful.
vtkGPUVolumeRayCastMapper *volumeGPUmapper =
vtkGPUVolumeRayCastMapper::New();
volumeGPUmapper->SetInputConnection(clip->GetOutputPort());
// RGB and alpha funcions
double skinOnBlueMap[28][5] =
{
{0, 0.987853825092316, 1.0, 1.0, 0.9},
{10000, 0.987853825092316, 1.0, 1.0, 0.9},
{20000, 0.987853825092316, 1.0, 1.0, 1.0},
{30000, 0.987853825092316, 1.0, 1.0, 1.0},
{40000, 0.0, 0.0, 0.0, 1.0},
{50000, 1.0, 0.0, 0.0, 1.0},
{60000, 1.0, 0.999206542968750, 0.0, 1.0},
{70000, 1.0, 1.0, 1.0, 1.0}
};
vtkSmartPointer<vtkPiecewiseFunction> alphaChannelFunc = vtkSmartPointer<vtkPiecewiseFunction>::New();
vtkSmartPointer<vtkColorTransferFunction> colorFunc = vtkSmartPointer<vtkColorTransferFunction>::New();
for(int i = 0; i < sizeof(skinOnBlueMap)/(5*sizeof(double)); i++)
{
colorFunc->AddRGBPoint(skinOnBlueMap[i][0], skinOnBlueMap[i][1], skinOnBlueMap[i][2], skinOnBlueMap[i][3]);
alphaChannelFunc->AddPoint(skinOnBlueMap[i][0], skinOnBlueMap[i][4]);
}
vtkSmartPointer<vtkVolumeProperty> volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
volumeProperty->SetColor(colorFunc);
volumeProperty->SetInterpolationTypeToLinear();
volumeProperty->SetScalarOpacity(alphaChannelFunc);
vtkSmartPointer<vtkVolume> VTKvolume = vtkSmartPointer<vtkVolume>::New();
VTKvolume->SetMapper(volumeGPUmapper);
VTKvolume->SetProperty(volumeProperty);
Those scalar values seem strange to me. It could be the reason your results don't look correct. But to be sure we need the image stack and rendered result.
The scalar values are not even inside the range of the unsigned short type, that is generally used for the voxels.

Copying an Array of Arrays in stack to Array of Arrays in heap in C++

Ok, so I have a model class that contains a pointer to (what will be) an array of point3 objects:
point3* _vertices_colors;
Point3 has the following typedef:
typedef GLfloat point3[3];
Essentially making an array of point3 objects an array of arrays. Then in a derived classes' constructor, I allocate memory for the number of vertices and colors I want to store as follows:
_vertices_colors = new point3[16];
This means my object has 8 vertices with their own colors stored. I then define the following array on stack ready to copy to the pointer:
point3 verticesColors[] = {
{1.0, 1.0, 1.0}, {1.0, 0.0, 0.0},
{-1.0, 1.0, 1.0}, {1.0, 0.0, 0.0},
{-1.0, -1.0, 1.0},{1.0, 0.0, 0.0},
{1.0, -1.0, 1.0},{1.0, 0.0, 0.0},
{1.0, 1.0, -1.0}, {1.0, 0.0, 0.0},
{-1.0, 1.0, -1.0}, {1.0, 0.0, 0.0},
{-1.0, -1.0, -1.0},{1.0, 0.0, 0.0},
{1.0, -1.0, -1.0},{1.0, 0.0, 0.0}
};
Then, I use a for loop to copy to the array on heap:
for(int i = 0; i < 16; i++)
{
*_vertices_colors[i,0] = *verticesColors[i, 0];
*_vertices_colors[i,1] = *verticesColors[i, 1];
*_vertices_colors[i,2] = *verticesColors[i, 2];
printf("%15f", *_vertices_colors[i,0]);
printf("\t");
printf("%15f", *_vertices_colors[i,1]);
printf("\t");
printf("%15f", *_vertices_colors[i,2]);
printf("\n");
}
However, this appears to assign 1.0, 1.0, -1.0 to each of the 16 rows of the array. I've tried other ways of assigning the pointer to the array, for example the line:
_vertices_colors = verticesColors;
As verticesColors is a constant pointer to an array, I thought this would work, however it produces the same results. I also tried using memcpy:
memcpy(_vertices_colors, verticesColors, sizeof(_vertices_colors));
But this seems to produce some uncontrollable results. It assigns each of the first columns as 1.0 and the rest as very large negative integers. Can anyone see why my first method doesn't work?
This
*_vertices_colors[i,0] = *verticesColors[i, 0];
*_vertices_colors[i,1] = *verticesColors[i, 1];
*_vertices_colors[i,2] = *verticesColors[i, 2];
is equivalent to
*_vertices_colors[0] = *verticesColors[0];
*_vertices_colors[1] = *verticesColors[1];
*_vertices_colors[2] = *verticesColors[2];
You use a sequence operator , in the array subscription, which yields the last value of the sequence. In this case 0, 1 and 2.
Multi dimensional arrays are accessed as
_vertices_colors[i][0] = verticesColors[i][0];

How to make transparent window on linux

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.