AncaA's tech journal

12 Feb, 2008

3D Mobile Rendering Using OpenGL ES presentation

Posted by: Anca Alimanescu In: Mobile Dev| OpenGL ES

For the PDF version click here.
Soon I will add also the source code for the application I developed and give some hints about usefull tutorials!

  • Share/Bookmark

12 Feb, 2008

How to play sound on the PocketPC using Win32

Posted by: Anca Alimanescu In: Mobile Dev

There are some functions that allow you to play sounds on a PPC:

* MessageBeep function is useful when you need to play a system alert.
MessageBeep(0xFFFFFFFF);

* PlaySound function should be used to play a .wav file from any source (file, resources and memory.

PlaySound(_T(”\\Windows\\empty.wav”), NULL, SND_ASYNC | SND_FILENAME);

* waveOut… functions are useful to play custom sound that is generated by your program. These functions are often used in games development.

  • Share/Bookmark

17 Jan, 2008

Bitmapped fonts

Posted by: Anca Alimanescu In: OpenGL ES

Due to the fact that OpenGL ES does not provide any kind of fonts, we need think a way to create the characters and display them efficiently. In order to use fonts in OpenGL ES, we will use a widely used technique called: bitmapped fonts. That is, we store into a texture all characters of a font (there are many programs that produces this kind of textures). The texture will be black (0,0,0) in the places that we want it will be transparent (we will not render the whole quad, only the character inside), and white (1,1,1) in the places we want to see (the character itself). This will allow us, with a blend function of (GL_ONE, GL_ONE).

Because we have a white color, we can safely use glColor4x call to color our font.

Also, we need the right texture coordinates to isolate the right character in the texture, so we will precompute all texture coordinates for characters from 0 to 127 (our texture has 128 characters) in order to access directly to them in runtime, and draw a textured-blended-quad (actually, a triangle strip, because we do not have quads…).

So first we will create a suitable texture, with all characters that we will need. This texture has 8 rows and 16 columns, and each cell has 16×16 texels, and the characters are stored in the ASCII order. We need to isolate the texture coordinates of a character, so we do the next computations:

const float rows = 8.0f;
const float columns = 16.0f;
const float xoffset = 1.0f / columns;
const float yoffset = 1.0f / rows;

const float cx = (float)(c % 16) * xoffset;
const float cy = (float)(c / 16) * yoffset;

Where c is the ASCII code of the character we want to access, substracting 32, because in our texture we do not store the first 32 ASCII characters. cx and cy are the initial position, in both axis, of the character. With these two values we have the texture coordinates of the first corner of the quad.

The BitmappedFont class will encapsulate all this code:

class BitmappedFont {

public:

BitmappedFont(GLuint textureFontID, int fontWidth = 15, int fontHeight = 15);
~BitmappedFont();
static void EnableStates(); //Begin Print
void Print(int x, int y, const char *fmt, ...);
static void DisableStates(); //EndPrint

private:

GLuint m_textureFontID;
int m_fontWidth,m_fontHeight;
//2 = st, 4 = vertices per character, 8 = rows, 16 = columns
static GLfixed m_textureCoordinates[2 * 4 * 8 * 16];
/*boolean to compute texture coordinates only when the first
instance is created*/
static bool m_instanced;

};

  • Share/Bookmark

17 Jan, 2008

Texture Loader

Posted by: Anca Alimanescu In: OpenGL ES

In order to load a texture we will use the following function :

bool LoadTexture(const char *fileName, GLuint *id)

This function will receive a texture filename and a pointer to a texture identifier. This identifier will be initialized from inside the function (if proceed). It will return true if the texture was successfully loaded, otherwise it will return false.

First we will read the texture file:

bool LoadTexture(const char *fileName, GLuint *id) {

FILE *f = fopen(fileName, "rb");
GLubyte *pixels = NULL;
if(!f) return false;

WORD width = 0, height = 0;
byte headerLength = 0;
byte imageType = 0;
byte bits = 0;
int format= 0;
int lineWidth = 0;

fread(&headerLength, sizeof(byte), 1, f);
//skip next byte
fseek(f,1,SEEK_CUR);

//read in the imageType (RLE, RGB, etc...)
fread(&imageType, sizeof(byte), 1, f);

//skip information we don't care about
fseek(f, 9, SEEK_CUR);

/*read the width, height and bits per pixel (16, 24 or 32). We only
will take care of 24 bits uncompressed TGAs*/
fread(&width, sizeof(WORD), 1, f);
fread(&height, sizeof(WORD), 1, f);
fread(&bits, sizeof(byte), 1, f);

//move the file pointer to the pixel data
fseek(f, headerLength + 1, SEEK_CUR);

//check if the image is not compressed.
if(imageType != 10)
{
//check if the image is a 24
if(bits == 24)
{
/*Another (faster) way to divide between 8. We want to know the
pixel size in bytes.*/
format = bits >> 3;
lineWidth = format * width;
pixels = new GLubyte[lineWidth * height];
//we are going to load the pixel data line by line
for(int y = 0; y < height; y++)
{
//Read current line of pixels
GLubyte *line = &(pixels[lineWidth * y]);
fread(line, lineWidth, 1, f);
/*Because the TGA is BGR instead of RGB, we must swap the R
and G components (OGL ES does not have the
GL_BGR_EXT extension*/


Now we will create the OpenGL Texture:

//Ask for a free texture name
glGenTextures(1, id);
/*first binding implies the texture object creation*/
glBindTexture(GL_TEXTURE_2D, *id);
/*Set texture properties: filtering and clamping modes*/
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
/*Upload pixels to the texture object*/
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB,
GL_UNSIGNED_BYTE, pixels);
/*Our copy in main main memory is no longer needed*/
delete [] pixels;
return true;

}

The texture will be loaded in the texture1 variable like this:

Gluint texture1 = 0;
bool result = LoadTexture("texturename.tga",&texture1);

  • Share/Bookmark

17 Jan, 2008

OBJ File Loader for OpenGL

Posted by: Anca Alimanescu In: OpenGL| OpenGL ES

In the followings a simple Obj File Loader using OpenGL ES will be described. For that, I used a structure to describe the mesh object:

typedef struct _ObjMesh { ObjVertex *m_aVertexArray; ObjNormal *m_aNormalArray; ObjTexCoord *m_aTexCoordArray; ObjFace *m_aFaces;

unsigned long int *m_aIndices; unsigned long int m_iNumberOfVertices,

m_iNumberOfNormals,
m_iNumberOfTexCoords,
m_iNumberOfFaces;

struct _ObjMesh *m_pNext; ObjFile m_iMeshID; unsigned char m_iMode; unsigned long int m_iDisplayListNum; } ObjMesh;

Each of the Vertices,Normals and Texture coordinates are also described in a structure:

typedef struct {

float x, /* The x component of the vertex position */
y, /* The y component of the vertex position */
z; /* The z component of the vertex position */

} ObjVertex;

typedef struct {

float x, /* The x component of the normal vector */
y, /* The y component of the normal vector */
z; /* The z component of the normal vector */

} ObjNormal;

typedef struct {

float u, /* The u parametric texturing co-ordinate */
v; /* The v parametric texturing co-ordinate */

} ObjTexCoord;

In the source file, each row of the file will be read in the loadFile(”file.obj”) method and the values will be recorderd in the structure. In order to draw the shape the DrawObj() method will be used.

  • Share/Bookmark

17 Jan, 2008

OBJ File Format & OBJ File Loader

Posted by: Anca Alimanescu In: OpenGL| OpenGL ES

The OBJ file format is a text file format, which means you can edit OBJ files in a text editor if you are hard-core. Unfortunately, the original specification didn’t seem to state what the end of line character should be, so some tools use carriage-returns and some use linefeeds. You may have to convert the end of line characters depending on which tools you are reading the OBJ file in from. (Most notably the OBJIMP plugin for 3DS MAX will crash when reading in any of the OBJ files that shipped with Poser.) Also your Windows text editors may think the files are binary because of this.

The first character of each line specifies the type of command. If the first character is a pound sign, #, the line is a comment and the rest of the line is ignored. Any blank lines are also ignored. The file is read in by a tool and parsed from top to bottom just like you would read it. In the descriptions that follow, the first character is a command, followed by any arguments. Anything shown in square brackets is optional.

# a comment line

These are always ignored. Usually the first line of every OBJ file will be a comment that says what program wrote the file out. Also, its quite common for comments to contain the number of verticies and/or faces an object used.

v x y z

The vertex command, this specifies a vertex by its three coordinates. The vertex is implicitly named by the order it is found in the file. For example, the first vertex in the file is referenced as ‘1’, the second as ‘2’ and so on. None of the vertex commands actually specify any geometry, they are just points in space.

vt u v [w]

The vertex texture command specifies the UV (and optionally W) mapping. These will be floating point values between 0 and 1 which say how to map the texture. They really don’t tell you anything by themselves, they must be grouped with a vertex in a ‘f’ face command.

vn x y z

The vertex normal command specifies a normal vector. A lot of times these aren’t used, because the ‘f’ face command will use the order the ‘v’ commands are given to determine the normal instead. Like the ‘vt’ commands, they don’t mean anything until grouped with a vertex in the ‘f’ face command.

f v1[/vt1][/vn1] v2[/vt2][/vn2] v3[/vt3][/vn3] …

The face command specifies a polygon made from the verticies listed. You may have as many verticies as you like. To reference a vertex you just give its index in the file, for example ‘f 54 55 56 57’ means a face built from vertecies 54 – 57. For each vertex, there may also be an associated vt, which says how to map the texture at this point, and/or a vn, which specifies a normal at this point. If you specify a vt or vn for one vertex, you must specify one for all. If you want to have a vertex and a vertex normal, but no vertex texture, it will look like: ‘f v1//vt1’. The normal is what tells it which way the polygon faces. If you don’t give one, it is determined by the order the verticies are given. They are assumed to be in counter-clockwise direction. If you aren’t using vn’s to specify the normal and you wanted to ‘flip the normal’ you would reverse the order of the verticies. In most 3D programs, if the normal points the wrong way, there will appear to be a hole in the object. g name

The group name command specifies a sub-object grouping. All ‘f’ face commands that follow are considered to be in the same group.

usemtl name

The use material command lets you name a material to use. All ‘f’ face commands that follow will use the same material, until another usemtl command is encountered. For all of the Poser OBJ files I’ve seen, all ‘g’ commands should be followed by a ‘usemtl’ command.

Remember that for verticies, they can be interspersed throughout the file, only the order they appear makes a difference. The faces can also be spread throughout the file, except they must follow the verticies they use (I think), and they will be part of whichever group and/or material they follow. That said, most OBJ files follow a consistant layout. Now the ‘normal’ layout of the file will be:

# comment about what application generated this file. # all of the ‘v’ commands will be listed v x y z v … # all of the ‘vn’ commands will be listed, although most Poser OBJ files # do not use the ‘vn’ commands vn x y z vn … # all of the ‘vt’ commands will be listed vt x y z vt … # the object and its material will be set g object usemtl material # all of the ‘f’ commands are listed f 1/1 2/2 3/3 4/4 f ….

Additional Items:

If you had two OBJ files and wanted to merge them, you can cut all the ‘v’, ‘vt’, and ‘vn’ commands from the second file and paste them at the end of the first. However, you cannot just copy over the ‘f’ commands, because they will have to have all their verticies offset. I’m thinking there has to be a tool out there somewhere that will do this for you, but I don’t know of any.

Hair objects with separate pieces like the ponytails that have a hairtie that can be colored separately, are actually a single group. They use additional usemtl commands to perform their magic. You can setup the additional material parameters in the .hr2 file (MAC). Example OBJ:

v x y z v … g hair usemtl hair f 1 2 3 4 f … # there is NOT another g command here usemtl hairTie f 10 11 12 13 f …

  • Share/Bookmark

17 Jan, 2008

Sample Win32 C++ Windows Mobile 5.0 application

Posted by: Anca Alimanescu In: Mobile Dev

ou will be presented a basic Windows Mobile application written in native code.

The IDE used to develop it has been VSTO 2005 Proffesional Edition and we have also used the Windows Mobile 5.0 Pocket PC SDK. In order to see how to setup a project and create a “Hello World” application you can check Microsoft’s tutorial.

In order to be able to add a custom menu to the application, open the resource panel and from the Menu folder start customizing the .dlg file. In my application I added a File→Exit menu and an Options→Option1,Options→Option2 menus. They will be defined in the resourceppc.h header file.

#define ID_FILE_EXIT 32771
#define ID_OPTIONS_OPTION1 32772
#define ID_OPTIONS_OPTION2 32773

In the WndProc produre, we will handle the messages in the main window and for the WM_Create message we will build the menu bar.

case WM_CREATE:

SHMENUBARINFO mbi;
memset(&mbi, 0, sizeof(SHMENUBARINFO));
mbi.cbSize = sizeof(SHMENUBARINFO);
mbi.hwndParent = hWnd;
mbi.nToolBarId = IDR_MENU;
mbi.hInstRes = g_hInst;
mbi.dwFlags = SHCMBF_HMENU;

if (SHCreateMenuBar(&mbi))
{
HMENU hMenu = (HMENU)::SendMessage(mbi.hwndMB, SHCMBM_GETMENU, 0, 0);
MENUITEMINFO mii;
memset((char *)&mii, 0, sizeof(mii));
mii.cbSize = sizeof(mii);
LRESULT lResult = 0;

UINT i = 0;

while(true)
{
if(0 == ::GetMenuItemInfo(hMenu, i, TRUE, &mii))
{
break;
}
mii.fType |= MFT_OWNERDRAW;
lResult = ::SetMenuItemInfo(hMenu, i, TRUE, &mii);
++i;
}
g_hWndMenuBar = mbi.hwndMB;

}
else
{

g_hWndMenuBar = NULL;

}
// Initialise la structure d'informations sur l'activation du shell
memset(&s_sai, 0, sizeof (s_sai));
s_sai.cbSize = sizeof (s_sai);

break;

Each of the submenus will be handeled when the WM_COMMAND message is received:

case WM_COMMAND:

wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Analyse les sélections de menu :
switch (wmId)
{
case IDM_HELP_ABOUT:
DialogBox(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, About);
break;
case IDM_OK:
SendMessage (hWnd, WM_CLOSE, 0, 0);
break;
case ID_FILE_EXIT:
SendMessage (hWnd, WM_CLOSE, 0, 0);
break;
case ID_OPTIONS_OPTION1:
DialogBox (g_hInst, // Handle to the application instance.
(LPCTSTR)IDD_DIALOG1, // Identifies the dialog box template.
hWnd, // Handle to the owner window.
ReplaceDialogProc); // Pointer to the dialog box procedure.
break;
case ID_OPTIONS_OPTION2:
DialogBox (g_hInst, // Handle to the application instance.
(LPCTSTR)IDD_DIALOG2, // Identifies the dialog box template.
hWnd, // Handle to the owner window.
ReplaceDialogProc); // Pointer to the dialog box procedure.
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;

For each of the options chosen a custom dialog box will be displayed:

DialogBox (g_hInst, // Handle to the application instance.
(LPCTSTR)IDD_DIALOG2, // Identifies the dialog box template.
hWnd, // Handle to the owner window.
ReplaceDialogProc); // Pointer to the dialog box procedure.

It is important to know that for desingning dialog boxes you have to make sure to design one for the wide screen and one for the tight screen and to make sure to choose the right one according to the screen resolution. The example below shows how to choose the right About dialog box according to the phone’s settings.

#ifdef _DEVICE_RESOLUTION_AWARE

case WM_SIZE:
{
DRA::RelayoutDialog(
g_hInst,
hDlg,
DRA::GetDisplayMode() != DRA::Portrait ? MAKEINTRESOURCE(IDD_ABOUTBOX_WIDE) : MAKEINTRESOURCE(IDD_ABOUTBOX));
}
break;

#endif

In order to handle the mouse events and the key events, the application must handle the mouse button and the key pressed messages:

case WM_LBUTTONDOWN:

{

// Retrieve the handle to the display device context.
hdc = GetDC (hWnd);

// start drawing the text that will be displayed
int bReturn;
TCHAR szHelloStr[50];

StringCchCopy(szHelloStr, 50, L"Mouse clicked!");

// Set text color.
SetTextColor (hdc, RGB(0,0,0));

bReturn = ExtTextOut (hdc, 10 , 140, 0, NULL,
szHelloStr, lstrlen(szHelloStr), NULL);

// Release the device context.

ReleaseDC(hWnd, hdc);

}
break;
case WM_CHAR:
{

//if the space key was pressed
if (wParam == VK_SPACE)
{
MessageBox(hWnd,L"You pressed Space.", L"Space key", MB_OK | MB_ICONINFORMATION);
}
else
{
MessageBox(hWnd,L"You have not pressed Space key.", L"Space key", MB_OK | MB_ICONINFORMATION);
}
}
break;

In our sample application when the left mouse button is clicked, a message will be displayed on the screen. If the Space key is pressed, a message box will appear confirming the user that he has pressed the Space key, or if not, other key.

  • Share/Bookmark

15 Jan, 2008

3D Tree on the Pocket PC

Posted by: Anca Alimanescu In: Mobile Dev| OpenGL ES

 

I loaded the tree using a mesh from a file and used OpenGL to render it. Soon I will put also some code samples used for loading the file and using OpenGL Es. Also I will add some performance statistics related to the execution of a 3D application using OpenGL.

Posted by Picasa
  • Share/Bookmark

04 Jan, 2008

Motorola introduces mobile video player

Posted by: Anca Alimanescu In: New things

Motorola, the world’s third-biggest cell phone maker, on Thursday introduced a mobile media player that shows live television, on-demand video clips, and programming saved on digital video recorders.

More on this here.

  • Share/Bookmark

In order to start the development of an Open GL ES application for the Pocket PC we will need the following:

1.An OpenGL ES implementation(Vincent Mobile 3D Rendering Library,Hybrid’s “Rasteroid” Implementation etc.) 2.Visual Studio 2005 Standard Edition(at least) as it contains the emulator and template projects for mobile development. 3.Pocket PC 2003 SDK.

In the following I am going to present you the steps needed to create an PocketPC application, on VSTO 2005, using OpenGL ES(Vincent implementation).

Steps on setting up the application:

1.Download the Vincent implementation library for Windows.

2.Unzip it and copy the header files and the library files in the Visual Studio directory Microsoft Visual Studio 8\SmartDevices\SDK\PocketPC2003\Include\ and Microsoft Visual Studio 8\SmartDevices\SDK\PocketPC2003\Lib\armv4, in the Pocket PC SDK. Make sure that in the Include folder you create a subfolder named GLES for example, where you include the header files located in the \include\GLES from the Vincent library. In the library Studio 8\SmartDevices\SDK\PocketPC2003\Lib\armv4 copy the content of the \bin\arm\Release folder.

3.Open Visual Studio 2005 and click File→ Create new project. Choose Visual C++ as programming language and select the Smart Device menu. From the project templates available choose Project Smart Device Win32 template. If you want to use Glut ES in implementing your project, you will specify in the wizard that you want a Win32 Console application. If you want to use just OpenGL ES you will choose a Win32 Windows application.

4.In the header file of the main cpp file make sure to include the OpenGl ES headers:

#include GLES/gl.h
#include GLES/egl.h

If you are using Glut Es make sure to add the

#include GLES/glutes.h

You should now link the project as well to the Glut Es library by cliking Project→ Project Properties→Configuration Properties→Linker→Command line. In the Command line here make sure to add glutes.lib library.

5.In order to test the project on the Pocket PC emulator, first you have to copy the libGLES_CM.dll file from the Vincent library in the Windows directory of the emulator(the same thing must be done for the mobile device). If you are using Glut ES, make sure to copy the glutes.dll file to the Windows directory of the emulator/pocket pc.

6.When launching the application you can run it either on the emulator or directy on the mobile device.

  • Share/Bookmark

Arhive

Mobile Barcode

qrcode

This is a 2D-barcode containing the address of my mobile site.If your mobile has a barcode reader, simply snap this bar code with the camera and launch the site.

About me

Client-focused software engineer with high intellectual mobility and experience in international teams.

Some of my interests are open innovation, design patterns, networking, personal branding, blogging and study of foreign languages.

Enjoy your visit and don’t hesitate to leave me a feedback!


Software entropy

1. A computer program that is used will be modified.

2. When a program is modified, its complexity will increase, provided that one does not actively work against this.

Switch to our mobile site