The design is based in part on how the Qt QGLWidget works.
You can grab the code from here
mount /dev/disk0s2 on / (hfs, local, journaled, noatime) devfs on /dev (devfs, local, nobrowse) /dev/disk1s2 on /Volumes/home (hfs, local, journaled) /dev/disk1s3 on /Volumes/spare (hfs, local, journaled) map -hosts on /net (autofs, nosuid, automounted, nobrowse) map auto_home on /home (autofs, automounted, nobrowse) localhost:/udRZrWiR2BXDgRrkJFCx2X on /Volumes/MobileBackups (mtmfs, nosuid, read-only, nobrowse) /dev/disk3s1 on /Volumes/UNTITLED (msdos, local, nodev, nosuid, noowners)
diskutil unmount /dev/disk3s1
dd bs=1m if=debian6-19-04-2012.img of=/dev/disk3 1859+1 records in 1859+1 records out 1950000000 bytes transferred in 1349.801573 secs (1444657 bytes/sec)Now this is done we should be able to put it into the pi and boot (username pi password raspberry)
sudo apt-get updateI also decided to update my kernel to the latest version. The good news is that there is a really simple tool to do this, here I had to do the following to get it working
sudo apt-get install ca-certificates sudo apt-get install gitOnce this is done follow the instructions on the link
adduser jmaceyBy default this user doesn't have access to the administrator (root) account, so we need to add it to the sudoers file. This is done by using the visudo tool. This will open up an editor and we can add our new user as shown
pi ALL=(ALL) ALL jmacey ALL=(ALL) ALLIn my case I've placed my username below the pi username, whilst I've left the pi user in, for security you may wish to remove this as it is a well known and documented username / password. To exit the editor use ctrl+k x to save and exit.
sudo apt-get install gpmWe now need to edit the config file to get the correct mouse device.
sudo vi /etc/gpm.conf # now change the device line to device=/dev/input/mouse0 # save then sudo /etc/init.d/gpm restartThis should now give you a mouse in the terminal
sudo apt-get install ssh sudo update-rc.d ssh defaultsOn a re-boot the ssh server will now be active. To make life easier on the pi you can follow this tutorial to not require a password.
#include <EGL/egl.h>On the debian "squeeze" image of the OS these headers can be found in /opt/vc/include, we also need to add the EGL library to our build using the flags -L/opt/vc/lib -lEGL (more on this later in the Makefile section).
EGLDisplay display; // get an EGL display connection display = eglGetDisplay(EGL_DEFAULT_DISPLAY); assert(display !=EGL_NO_DISPLAY);If this is successful it should return a valid display, else the EGL_NO_DISPLAY value will be returned.
// now lets initialise EGL and get the versions int major; int minor; EGLBoolean result; result = eglInitialize(display, &major, &minor); assert(result != EGL_FALSE ); std::cout<<"Major version "<<major<<" minor "<<minor<<"\n";On my version of the pi it gives the following output
Major version 1 minor 4
EGLint numConfigs; // first we call getConfigs with a NULL to see how many configs we have result=eglGetConfigs(display,NULL,0,&numConfigs); assert(result != EGL_FALSE ); std::cout<< "number of configs found "<<numConfigs<<"\n"; // now we create a buffer to store all our configs EGLConfig *configs = new EGLConfig[numConfigs]; // and copy them into our buffer (don't forget to delete once done) result=eglGetConfigs(display,configs,numConfigs,&numConfigs); assert(result != EGL_FALSE ); ...... // don't forget to delete once done delete [] configs;We can now gather the information from each of the configs using the eglGetConfigAttrib function. This requires you to pass in the attribute you wish to query and will return the value if set. The following code queries the attributes available on the pi (some that are in the spec are not on the pi)
for(int i=0; i<numConfigs; ++i)
{
std::cout<<"Config #"<<i<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_BUFFER_SIZE,&value);
std::cout<<"Buffer Size "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_RED_SIZE,&value);
std::cout<<"Red Size "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_GREEN_SIZE,&value);
std::cout<<"Green Size "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_BLUE_SIZE,&value);
std::cout<<"Blue Size "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_ALPHA_SIZE,&value);
std::cout<<"Alpha Size "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_CONFIG_CAVEAT,&value);
switch(value)
{
case EGL_NONE : std::cout<<"EGL_CONFIG_CAVEAT EGL_NONE\n"; break;
case EGL_SLOW_CONFIG : std::cout<<"EGL_CONFIG_CAVEAT EGL_SLOW_CONFIG\n"; break;
}
eglGetConfigAttrib(display,configs[i],EGL_CONFIG_ID,&value);
std::cout<<"Config ID "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_DEPTH_SIZE,&value);
std::cout<<"Depth size "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_MAX_PBUFFER_WIDTH,&value);
std::cout<<"Max pbuffer width "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_MAX_PBUFFER_HEIGHT,&value);
std::cout<<"Max pbuffer height "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_MAX_PBUFFER_PIXELS,&value);
std::cout<<"Max pbuffer pixels "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_NATIVE_RENDERABLE,&value);
std::cout<<"Native renderable "<<std::string(value ? "true" : "false")<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_NATIVE_VISUAL_ID,&value);
std::cout<<"Native visual ID "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_NATIVE_VISUAL_TYPE,&value);
std::cout<<"Native visual type "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_SAMPLE_BUFFERS,&value);
std::cout<<"Sample Buffers "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_SAMPLES,&value);
std::cout<<"Samples "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_SURFACE_TYPE,&value);
std::cout<<"Surface type "<<value<<"\n";
eglGetConfigAttrib(display,configs[i],EGL_TRANSPARENT_TYPE,&value);
}
This give a sample output like this (a full listing can be seen here or in the file output.txt in the code bundle)
Config #0 Buffer Size 32 Red Size 8 Green Size 8 Blue Size 8 Alpha Size 8 EGL_CONFIG_CAVEAT EGL_NONE Config ID 1 Depth size 24 Max pbuffer width 2048 Max pbuffer height 2048 Max pbuffer pixels 4194304 Native renderable true Native visual ID 37928 Native visual type 12344 Sample Buffers 0 Samples 0 Surface type 1639
CC=g++ CFLAGS=-c -Wall -O3 -I/usr/local/include -I/opt/vc/include -Iinclude/ngl -Isrc/ngl -Isrc/shaders -DNGL_DEBUG LDFLAGS=-L/opt/vc/lib -lEGL SOURCES=$(shell find ./ -name *.cpp) OBJECTS=$(SOURCES:%.cpp=%.o) EXECUTABLE=EGLgetConfig all: $(SOURCES) $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) $(CC) $(LDFLAGS) $(OBJECTS) -o $@ .cpp.o: $(CC) $(CFLAGS) $< -o $@ clean : rm -f *.o $(EXECUTABLE)That it for now but here is a sneak preview of NGL almost working
# This file is split into Three sections
# The first configures Qt and the source files for all platforms
# The second is the linux build
# The third the mac build
# (if your using windows you will need to add a fourth one!)
# first lets remove Qt core and gui not going to need it
QT -= core gui
# set the variable for the Maya Location, this will be different depending
# upon the platform / version of maya used
TARGET = HelloMaya
# for for mac we need a bundle so change the name
macx:TARGET=HelloMaya.bundle
# here we add the source files (and headers if required)
SOURCES+=HelloMaya.cpp
# these are defines required by Maya to re-define some C++
# stuff, we will add some more later to tell what platform
# we are on as well
DEFINES+=REQUIRE_IOSTREAM \
_BOOL
# These are the maya libs we need to link to, this will change depending
# upon which maya framework we use, just add them to the end of
# this list as required and they will be added to the build
MAYALIBS=-lOpenMaya \
-lFoundation
# now tell linux we need to build a lib
linux-g++-64:TEMPLATE = lib
# this tells qmake where maya is
linux-g++-64:MAYALOCATION=/usr/autodesk/maya2011-x64/
# under linux we need to use the version of g++ used to build maya
# in this case g++412
linux-g++-64:QMAKE_CXX = g++412
# set the include path for linux
linux-g++-64:INCLUDEPATH += $$MAYALOCATION/include \
/usr/X11R6/include
# set which libs we need to include
linux-g++-64:LIBS += -L$$MAYALOCATION/lib \
$$MAYALIBS
# tell maya we're building for linux
linux:DEFINES+=linux
# tell maya we're building for Mac
macx:DEFINES+=OSMac_
macx:MAYALOCATION=/Applications/Autodesk/maya2011
macx:CONFIG -= app_bundle
macx:INCLUDEPATH+=$$MAYALOCATION/devkit/include
# under mac we need to build a bundle, to do this use
# the -bundle flag but we also need to not use -dynamic lib so
# remove this
macx:LIBS +=-bundle
mac:LIBS -=-dynamiclib
macx:LIBS += -L$$MAYALOCATION/Maya.app/Contents/MacOS \
$$MAYALIBS
There are several sections to the .pro file above, mainly these are to make it easier to add to the project when needed. The two main distinctions between the linux and the Mac OSX version are how the plugin should be generated. Under linux the plugin is a normal shared object file (.so), however the mac version requires a bundle. To do this the -bundle flag is used and we also need to ensure that the extension .bundle is added to the Target.#include <maya/MSimple.h>
#include <maya/MIOStream.h>
#include <maya/MGlobal.h>
// This is a macro to create a simple command
// the compiler expands it to a bunch of code
DeclareSimpleCommand( HelloMaya , "NCCA", "Maya 2011");
MStatus HelloMaya::doIt( const MArgList& )
{
std::cout<<"This should come from the shell\n";
MGlobal::displayInfo("Hello Maya in the maya command shell");
return MS::kSuccess;
}
Once this program is build depending upon the platform there should be a plugin ready to load in the maya plugin manager. The image below show this and the info set from the Command above/* from the flex and bison book do a word count */
%{
int chars=0;
int words=0;
int lines=0;
%}
%%
[a-zA-Z]+ { words++; chars += strlen(yytext); }
\n { chars++; lines++; }
. { chars++; }
%%
int main(int argc, char **argv)
{
yylex();
printf("Word count %8d %8d %8d\n",lines,words,chars);
return 0;
}
To build and compile this we use the following command line
flex -o wc.c wc.l gcc -o WordCount wc.c -lflThis works fine, but as I use QtCreator as my ide I really want to configure Qt to do this all for me. QtCreator does have some limited lex and yacc support however I really wanted to use flex and bison, so need to add my own compiler to the qmake build system via the Qt project. To do this we use the QMAKE_EXTRA_COMPILERS flag in the project and build our own compile chain, the following extract shows how this works
# the is the name of the exe we want
TARGET=WordCount
# this is the source fed to the flex syste
FLEXSOURCES+=wc.l
# we then add this to the other files for editing
OTHER_FILES+=$$FLEXSOURCES
###########################################################################################
# now we are going to create a Qt compiler ojbect for the EXTRA_COMPILERS FLAG
# this basically has a number of attributes which we need to set as outlined below
###########################################################################################
# this flag list the sources we wish to input to this custom compiler, in this case listed above
# in the FLEXSOURCES variable
flex.input = FLEXSOURCES
# now we need to say what files to output, for flex we want to create the .c
flex.output = ${QMAKE_FILE_BASE}.c
# this is the actual compile command we wish to call in this case it wil be
# flex -o (output).c input.l
flex.commands = flex -o ${QMAKE_FILE_IN_BASE}.c ${QMAKE_FILE_IN}
# once this compiler has been run we need to add the output files to the linker stage in this case
# as we are generating .c files we just add it to the SOURCES variable and it will be compiled
flex.variable_out = SOURCES
# this flag ensures that the extra compiler is run before the main c one (as we need to have the .c files
# generated by flex before we use the gcc compiler)
flex.CONFIG += target_predeps
# this tells the make clean command what files to remove
flex.clean = ${QMAKE_FILE_IN_BASE}.c
# this is just the name of the extra compiler used in the make file (make flex for example)
flex.name = flex
# finally add this to the qmake project so it will have the makefile generated
QMAKE_EXTRA_COMPILERS += flex
# we need the fl lib for flex
LIBS+=-lfl
# tell qt we usign gcc
QMAKE_LINK=gcc
# this just cleans out some things for mac
CONFIG += console
CONFIG -= app_bundle
And that is about it, now I've got to read the rest of the book, but at least it makes the coding easier!
QGLFormat glf = QGLFormat::defaultFormat(); glf.setSampleBuffers(true); glf.setSamples(4); QGLFormat::setDefaultFormat(glf);Now when we create the GLWindow in the ngl:: demos this will be used for all windows created. Finally we need to enable GL_MULTISAMPLE when rendering which can be done using the following code
glEnable(GL_MULTISAMPLE);This method can also be used to enable things such as the new OpenGL core profile (under linux and windows for Qt 4.7 and with Qt 4.8 this will also work on the mac eventually, as long as you have Lion). You should be able to see from the documentation all the other features which can be enabled in this way.