Maximize MenuMinimize Menu

 

 

Back | Home

Getting Started with Rasteroid OpenGL ES
for Pocket PC using Pelles C

This tutorial was tested to run on a Windows 2000 machine and a 2003 Pocket PC, the hp iPaq Pocket PC h2215. Pelles C is a free ANSI C compiler. Please make donations to Pelles C if you find it useful.

 


1. Get the Rasteroid Free Non-Commercial OpenGL ES files here:

http://www.hybrid.fi/main/extra/noncom_es_info.php


Copy \bin\wince2003_pp\libGLES_CM.dll to your Pocket PC Windows directory or the directory you plan to run your program in.

Copy \include\GLES\gl.h and egl.h to PellesC\Include\Win\GLES (make a new directory)

Copy \lib\wince2003_pp\libGLES_CM.lib to PellesC\Lib\Win

2. Create a new Pelles C WinCE Pocket PC Program in Pelles C.

3. In Project Options Linker add libGLES_CM.lib to the list of Libraries and object files.




4. Paste the code below from the Rasteroid samples directory, compile, build and copy to the Pocket PC.

5. Run it on the Pocket PC!!!


Program Output on Pocket PC
A Spinning Cube

/*************************************************************************
*
* Gerbera/EGL sample app
* ----------------------
*
* (C) 2001-2004 Hybrid Graphics, Ltd.
* All Rights Reserved.
*
* This file consists of source code released by Hybrid
* Graphics under the terms of the accompanying End User License
* Agreement (EULA). By using this source code you agree to be
* bound by the terms of the EULA.
*
* Use and/or disclosure outside these terms may result in
* irreparable harm to Hybrid Graphics and legal action against
* the party in breach.
*
* This source code is distributed on an "as is" basis, with
* all express and implied warranties and conditions disclaimed,
* including, without limitation, any implied warranties and
* conditions of merchantability, satisfactory quality, fitness
* for a particular purpose, and non-infringement.
*
* The most up-to-date version of the OpenGL ES 1.1 specification can be
* found from http://www.khronos.org/opengles/spec.html
*
* Description: Sample application that renders a red spinning cube on
* a blue background.
*
* $Archive: /gerbera/samples/eglwince/sample.c $
* $Author: jasinb $
* $Revision: #1 $
*
************************************************************************/

#define SAMPLE_SURFACE_TYPE EGL_WINDOW_BIT
//#define SAMPLE_SURFACE_TYPE EGL_PIXMAP_BIT
//#define SAMPLE_SURFACE_TYPE EGL_PBUFFER_BIT

//#define PIXMAP_COLOR_FORMAT 555
//#define PIXMAP_COLOR_FORMAT 565
#define PIXMAP_COLOR_FORMAT 888

#if (PIXMAP_COLOR_FORMAT == 555) || (PIXMAP_COLOR_FORMAT == 565)
# define SAMPLE_PIXMAP_BITS 16
#elif (PIXMAP_COLOR_FORMAT == 888)
# define SAMPLE_PIXMAP_BITS 32
#else
# error PIXMAP_COLOR_FORMAT not properly defined.
#endif

#if defined (_MSC_VER)
# pragma warning(disable : 4115) /* named type definition in parentheses */
#endif

#include <windows.h>
#include <math.h>
#include "GLES/gl.h"
#include "GLES/egl.h"

#include <stdio.h>

// WinCE stuff
#define MAX_LOADSTRING 100
#define IDS_APP_TITLE 1
#define IDC_TESTAPP 3


/* EGL resources and Windows globals, defines, and prototypes */
static LONG WINAPI MainWndProc (HWND, UINT, WPARAM, LPARAM);
static void drawScene (int width, int height);

// GAPI is not used in emulators
#ifndef _X86_
# define USE_GAPI
#endif

#ifndef USE_GAPI
# define SAMPLE_WINDOW_WIDTH 120
# define SAMPLE_WINDOW_HEIGHT 120
#endif

static const char szAppName[] = "Gerbera OpenGL ES sample app";
static HWND ghWnd;

static EGLDisplay eglDisplay;
static EGLConfig eglConfig;
static EGLContext eglContext;
static EGLSurface eglWindowSurface;

static const EGLint s_configAttribs[] =
{
#if (PIXMAP_COLOR_FORMAT == 555)
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 5,
EGL_BLUE_SIZE, 5,
#elif (PIXMAP_COLOR_FORMAT == 565)
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
#elif (PIXMAP_COLOR_FORMAT == 888)
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
#else
# error You must define PIXMAP_COLOR_FORMAT
#endif
EGL_ALPHA_SIZE, EGL_DONT_CARE,
EGL_DEPTH_SIZE, 32,
EGL_STENCIL_SIZE, EGL_DONT_CARE,
EGL_SURFACE_TYPE, SAMPLE_SURFACE_TYPE,
EGL_NONE
};

#if (SAMPLE_SURFACE_TYPE == EGL_PBUFFER_BIT)
static const EGLint s_pbufferAttribs[] =
{
EGL_WIDTH, SAMPLE_WINDOW_WIDTH,
EGL_HEIGHT, SAMPLE_WINDOW_HEIGHT,
EGL_NONE
};
#endif

#if (SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT)

static HBITMAP pixmap;

/*-------------------------------------------------------------------*//*!
* \brief Create a DIB section bitmap.
* \param hDC DC handle.
* \return Returns the handle to the created bitmap.
*//*-------------------------------------------------------------------*/

DWORD* bits;

static HBITMAP createPixmap (
HDC hDC)
{


const size_t bmiSize = sizeof(BITMAPINFO) + 256U*sizeof(RGBQUAD);
BITMAPINFO* bmi;
DWORD* p;

bmi = (BITMAPINFO*)malloc(bmiSize);
memset(bmi, 0, bmiSize);

bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
#if defined (USE_GAPI)
bmi->bmiHeader.biWidth = GetSystemMetrics(SM_CXSCREEN),
bmi->bmiHeader.biHeight = -GetSystemMetrics(SM_CYSCREEN),
#else
bmi->bmiHeader.biWidth = SAMPLE_WINDOW_WIDTH;
bmi->bmiHeader.biHeight = -SAMPLE_WINDOW_HEIGHT;
#endif
bmi->bmiHeader.biPlanes = (short)1;
bmi->bmiHeader.biBitCount = (unsigned int) SAMPLE_PIXMAP_BITS;
bmi->bmiHeader.biCompression = BI_BITFIELDS;
bmi->bmiHeader.biSizeImage = 0;
bmi->bmiHeader.biXPelsPerMeter = 0;
bmi->bmiHeader.biYPelsPerMeter = 0;
bmi->bmiHeader.biClrUsed = 3;
bmi->bmiHeader.biClrImportant = 0;

p = (DWORD*)bmi->bmiColors;

#if (PIXMAP_COLOR_FORMAT == 555)
p[0] = 0x1F << 0; /* r */
p[1] = 0x1F << 5; /* g */
p[2] = 0x1F << 10; /* b */
#elif (PIXMAP_COLOR_FORMAT == 565)
p[0] = 0x1F << 0; /* r */
p[1] = 0x3F << 5; /* g */
p[2] = 0x1F << 11; /* b */
#elif (PIXMAP_COLOR_FORMAT == 888)
p[0] = 0xFF; /* r */
p[1] = 0xFF00; /* g */
p[2] = 0xFF0000; /* b */
#else
# error SAMPLE_PIXMAP_BITS must be either 16 or 32
#endif

return CreateDIBSection(hDC, bmi, DIB_RGB_COLORS, &bits, NULL, 0);
}

/*-------------------------------------------------------------------*//*!
* \brief Destroy the given bitmap.
* \param bitmap Bitmap handle.
*//*-------------------------------------------------------------------*/

static void deletePixmap (
HBITMAP bitmap)
{
DeleteObject(bitmap);
}

#endif /* SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT */

//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// It is important to call this function so that the application
// will get 'well formed' small icons associated with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
{
WNDCLASS wc;

wc.style = 0;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = szWindowClass;

return RegisterClass(&wc);
}

//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The window class name

// Initialize global strings
LoadString(hInstance, IDC_TESTAPP, szWindowClass, MAX_LOADSTRING);
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);

MyRegisterClass(hInstance, szWindowClass);

#if defined(USE_GAPI)
ghWnd = CreateWindow(szWindowClass,
szTitle,
WS_VISIBLE,
CW_USEDEFAULT,
CW_USEDEFAULT,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
NULL,
NULL,
hInstance,
NULL);
#else
ghWnd = CreateWindow(szWindowClass,
szTitle,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
CW_USEDEFAULT,
CW_USEDEFAULT,
SAMPLE_WINDOW_WIDTH,
SAMPLE_WINDOW_HEIGHT,
NULL,
NULL,
hInstance,
NULL);
#endif
if (!ghWnd)
return FALSE;

#if (SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT)
{
HDC dc = GetDC(ghWnd);
pixmap = createPixmap(dc);
ReleaseDC(ghWnd, dc);
}
#endif

{
/* EGL Setup */
EGLint numConfigs;
EGLint majorVersion;
EGLint minorVersion;

int error;

eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(eglDisplay, &majorVersion, &minorVersion);
eglGetConfigs(eglDisplay, NULL, 0, &numConfigs);
eglChooseConfig(eglDisplay, s_configAttribs, &eglConfig, 1, &numConfigs);
eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, NULL);

#if (SAMPLE_SURFACE_TYPE == EGL_WINDOW_BIT)
eglWindowSurface = eglCreateWindowSurface(eglDisplay, eglConfig, ghWnd, NULL);
#elif (SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT)
eglWindowSurface = eglCreatePixmapSurface(eglDisplay, eglConfig, pixmap, NULL);
#elif (SAMPLE_SURFACE_TYPE == EGL_PBUFFER_BIT)
eglWindowSurface = eglCreatePbufferSurface(eglDisplay, eglConfig, s_pbufferAttribs);
error = eglGetError();
#endif

eglMakeCurrent(eglDisplay, eglWindowSurface, eglWindowSurface, eglContext);
error = eglGetError();
}

ShowWindow(ghWnd, nCmdShow);
UpdateWindow(ghWnd);

return TRUE;
}


/*-------------------------------------------------------------------*//*!
* \brief Main procedure.
* \param hInstance Instance handle.
* \param hPrevInstance Previous instance handle.
* \param lpCmdLine Command line.
* \param nCmdShow Show command.
* \return Returns exit status.
*//*-------------------------------------------------------------------*/

int WINAPI WinMain (
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,
int nCmdShow)
{
int i;
MSG msg;

hPrevInstance;
lpCmdLine;

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

for(i = 0; i<6000; i++)
{
RECT rc;
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == TRUE)
{
if (GetMessage(&msg, NULL, 0, 0) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
return 0;
}

GetClientRect(ghWnd, &rc);
drawScene(rc.right, rc.bottom);
}
DestroyWindow(ghWnd);
return 0;
}

/*-------------------------------------------------------------------*//*!
* \brief Main window procedure.
* \param hWnd Window handle.
* \param uMsg Message.
* \param wParam Parameter.
* \param lParam Parameter.
* \return Returns the return status.
*//*-------------------------------------------------------------------*/

static LONG WINAPI MainWndProc (
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PAINTSTRUCT ps;
LONG lRet = 1;

// For sniffing messages:
#if 0
if (uMsg != WM_PAINT)
{
wchar_t str[128];
swprintf(str, L"0x%X (%d)\n", uMsg, uMsg);
//swprintf(str, L"0x%X (%d)\n", wParam, wParam);
OutputDebugString(str);
}
#endif

switch (uMsg)
{
case WM_PAINT:
{
HDC dc = BeginPaint(hWnd, &ps);
#if (SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT)
HDC hdcBitmap = CreateCompatibleDC((HDC)dc);
HDC old = SelectObject(hdcBitmap, pixmap);

int dx0 = 0;
int dy0 = 0;
# if defined (USE_GAPI)

int dx1 = GetSystemMetrics(SM_CXSCREEN);
int dy1 = GetSystemMetrics(SM_CYSCREEN);
# else
int dx1 = SAMPLE_WINDOW_WIDTH;
int dy1 = SAMPLE_WINDOW_HEIGHT;
# endif

int x=0,y=0;

for (x = 1; x < 4; x+=2)
for (y = 160; y < 260; y++)
((unsigned short*)bits)[y*240 + x] = 0xFFFF;

// memset(bits, 0xff, 240*240*2);

StretchBlt((HDC)dc, dx0, dy0, dx1, dy1, hdcBitmap, dx0, dy0, dx1, dy1, SRCCOPY);

SelectObject(hdcBitmap, old);
#else
(void)dc; /* unreferenced */
#endif
EndPaint(hWnd, &ps);
}
break;

case WM_SIZE:
/* Resizing is handled each frame */
break;

case WM_KILLFOCUS:
case WM_CLOSE:
DestroyWindow (hWnd);
break;

case WM_DESTROY:
/* Destroy all EGL resources */
eglMakeCurrent(eglDisplay, NULL, NULL, NULL);
eglDestroyContext(eglDisplay, eglContext);
eglDestroySurface(eglDisplay, eglWindowSurface);
eglTerminate(eglDisplay);
#if (SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT)
deletePixmap(pixmap);
#endif
PostQuitMessage (0);
break;

// exit with every key pressed
case WM_KEYDOWN:
DestroyWindow (hWnd);

/* FALLTHROUGH */

default:
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
break;
}

return lRet;
}

/* OpenGL code */

/*-------------------------------------------------------------------*//*!
* \brief Sets the perspective matrix to OpenGL.
* \param fovy Vertical field-of-view.
* \param aspect Aspect ratio.
* \param zNear Distance to near plane.
* \param zFar Distance to far plane.
*//*-------------------------------------------------------------------*/

static void perspective (
GLfloat fovy,
GLfloat aspect,
GLfloat zNear,
GLfloat zFar)
{
GLfloat xmin, xmax, ymin, ymax;

ymax = zNear * (GLfloat)tan(fovy * 3.1415962f / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;

glFrustumf(xmin, xmax, ymin, ymax, zNear, zFar);
}

/*-------------------------------------------------------------------*//*!
* \internal
* \brief Update state.
* \param width Rendering width.
* \param height Rendering height.
*//*-------------------------------------------------------------------*/

static void updateState (
int width,
int height)
{
static const GLfloat light_position[] = { -50.f, 50.f, 200.f, 0.f };
static const GLfloat light_ambient[] = { 0.25f, 0.25f, 0.25f, 1.f };
static const GLfloat light_diffuse[] = { 1.f, 1.f, 1.f, 1.f };
static const GLfloat material_spec[] = { 0.f, 0.f, 0.f, 0.f };

float aspect = height ? (float)width/(float)height : 1.0f;

glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();

glLightfv (GL_LIGHT0, GL_POSITION, light_position);
glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv (GL_LIGHT0, GL_SPECULAR, light_diffuse);
glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, material_spec);

glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glEnable (GL_COLOR_MATERIAL);
glEnable (GL_CULL_FACE);
glEnable (GL_NORMALIZE);

glDisable (GL_DEPTH_TEST);
glDepthMask (GL_FALSE);
glClearDepthf (1);

glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);

glShadeModel (GL_FLAT);
glDisable (GL_DITHER);
glClearColor (0.1f, 0.2f, 0.1f, 0.f );
glColor4x (0x10000, 0, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);

glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
perspective (60.f, aspect, 0.1f, 100.f);
}

/*-------------------------------------------------------------------*//*!
* \brief Draw the scene.
* \param width Rendering width in pixels
* \param height Rendering height in pixels
*//*-------------------------------------------------------------------*/

static void drawScene (
int width,
int height)
{
/* Vertices */
static const GLbyte cubeVertices[] =
{
-10, 10, 10,
10, -10, 10,
10, 10, 10,
-10, -10, 10,
-10, 10, -10,
10, -10, -10,
10, 10, -10,
-10, -10, -10
};

/* Vertex indices */
static const GLubyte cubeIndices[] =
{
0, 3, 1, 2, 0, 1, /* front */
6, 5, 4, 5, 7, 4, /* back */
4, 7, 3, 0, 4, 3, /* left */
2, 1, 5, 6, 2, 5, /* right */
4, 0, 2, 6, 4, 2, /* top */
3, 7, 1, 7, 5, 1 /* bottom */
};

/* Normals */
static const GLbyte cubeNormals[] =
{
-1, 1, 1,
1, -1, 1,
1, 1, 1,
-1, -1, 1,
-1, 1, -1,
1, -1, -1,
1, 1, -1,
-1, -1, -1
};

const double time = fmod(GetTickCount() / 1000.0, 360.0);

updateState (width, height);

glClearColor (0.1f, 0.2f, 0.4f, 0.f);
glClear (GL_COLOR_BUFFER_BIT);
glVertexPointer (3, GL_BYTE, 0, cubeVertices);
glNormalPointer (GL_BYTE, 0, cubeNormals);

glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();

glTranslatef (0.f, 0.f, -30.f);
glRotatef ((float)(time*30.77f), 1.f, 2.f, 0.f);
glRotatef ((float)(time*21.311f), -.1f, 0.f, -5.f);

glDrawElements (GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, cubeIndices);

#if (SAMPLE_SURFACE_TYPE == EGL_WINDOW_BIT)
eglSwapBuffers (eglDisplay, eglWindowSurface);
#elif (SAMPLE_SURFACE_TYPE == EGL_PIXMAP_BIT)
InvalidateRect(ghWnd, NULL, FALSE);
#endif
}

/*----------------------------------------------------------------------*/


END OF LESSON

BACK


  ©Copyright TrajectoryLabs.com. All Rights Reserved.