Friday, September 07, 2007

Three Steps Build a Haptic Model

I suggest you start from simple model, mine is a big H. You can do a sphere, cube as your first try. To keep the model as simple as you can will give you a clear field levels in X3D file. It will be helpful to understand where the haptic field goes from the beginning.

Step 1: Build a normal 3D model

You can use any 3D modeling application you're familiar with. I do not have 3D Max on my computer, so I created my model with blender. It's free and fabulous. Oh, don't forget assign material for your model, a default material will do.

Step 2: Export the model as X3D file

This is too easy to blog anyting on it, just export the file you created.

Step 3: Edit X3D file

Here comes something new. Open the X3D file you just exported with a text editor. Find the field <Appearance> and just after <Appearance> we add a new field <SmoothSurface/>. OK that's all, now you can use H3DLoad to check your model with default SmoothSurface.
Currently, without any programming work we have three haptic surface nodes to choose from. They are:
  • SmoothSurfce - a surface without friction
  • FrictionalSurface - a surface with friction
  • MagneticSurface - makes the shape magnetic
Note: H3DLoad comes with h3dapi package, you can download it from here
Pre requirement: a haptic stylus of course

PS: some H3DLoad options:
  • -f for fullscreen
  • -m for mirror
  • -s for with spacemouse




Labels:

Thursday, September 06, 2007

A Simple OpenGL Sample as Firefox plugin


Introduction

It does OpenGL rendering as Firefox plugin. Don't know whether it's useful. I did it for fun!

Background

I was trying to render x3d file with OpenGL as a Firefox plugin. I know there are many such x3d file viewers, but mine intends to handle haptic field...well, this sample is just a by-product.

Tinkering the code

You will first need to download Gecko plugin API and Firefox source code.

Download Gecko SDK extract to \yourroot\gecko-sdk\

Download Firefox source code from here, extract to \yourroot\mazilla. Then we start from a basic plugin sample, come to the folder: yourroot\mozilla\modules\plugin\tools\sdk\samples\basic\windows

Here's a little trick, we need to run unix2dos on npbasic.dsp and npbasic.dsw under this folder. Then we open and cover the project by Visual C++ Express, will be successed now. From project properties change the Additional include directories to yourroot\gecko-sdk\include;yourroot\mozilla\modules\plugin\tools\sdk\samples\include. Try to build now, if successed, we continue...

Open plugin.cpp, after

#include "plugin.h"

add

#include <gl/gl.h>

then after the line

static WNDPROC lpOldProc = NULL; add two functions EnableOpenGL and DisableOpenGL

void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC);
void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC);

and in

NPBool nsPluginInstance::init(NPWindow* aWindow)

{

.................

//we add EnableOpenGL and SetTimmer

 EnableOpenGL( mhWnd, &hDC, &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;hRC );
SetTimer(mhWnd, 0, 1, (TIMERPROC) NULL);
// no timer callback

............

}

then in

void nsPluginInstance::shut()

{

// subclass it back

//We add DisableOpenGL

    DisableOpenGL( mhWnd, hDC, hRC );

....

}

then in PluginWinProc we need to handle WM_TIMMER message like the following

   case WM_TIMER:
theta += 1.0f;
PostMessage( hWnd, WM_PAINT, NULL, NULL );
break;

At last we do OpenGL rendering in case WM_PAINT, remove the original code under this case, and replace them with ours as the following:

    glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
glClear( GL_COLOR_BUFFER_BIT );
glPushMatrix();
glRotatef( theta, 0.0f, 0.0f, 1.0f );
glBegin( GL_TRIANGLES );
glColor3f( 1.0f, 0.0f, 0.0f );
glVertex2f( 0.0f, 1.0f );
glColor3f( 0.0f, 1.0f, 0.0f );
glVertex2f( 0.87f, -0.5f );
glColor3f( 0.0f, 0.0f, 1.0f );
glVertex2f( -0.87f, -0.5f );
glEnd();
glPopMatrix();
SwapBuffers( hDC );

it's almost done, but don't forget to define EnableOpenGL and DisableOpenGL

void EnableOpenGL(HWND hWnd, HDC * hDC, HGLRC * hRC)
{


PIXELFORMATDESCRIPTOR pfd;
int format;
// get the device context (DC)
*hDC = GetDC( hWnd ); // set the pixel format for the DC

ZeroMemory( &pfd, sizeof( pfd ) );
pfd.nSize = sizeof( pfd );
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;
format = ChoosePixelFormat( *hDC, &pfd );
SetPixelFormat( *hDC, format, &pfd );
// create and enable the render context (RC)

*hRC = wglCreateContext( *hDC );
wglMakeCurrent( *hDC, *hRC );
}


// Disable OpenGL

void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC)
{

wglMakeCurrent( NULL, NULL );
wglDeleteContext( hRC );
ReleaseDC( hWnd, hDC );

}

Done!!!

Build the Project

Nothing to say, just build it.

Test the plugin

Copy npbasic.dll to C:\Program Files\Mozilla Firefox\plugins\ or yourfolder\Mozilla Firefox\plugins\
From the folder yourroot\mozilla\modules\plugin\tools\sdk\samples\basic\ you will find test.html, double click, you would see a rotating triangle, corlorful...

Another way to test the plugin. If we open a file of the type a plugin registered then the plugin will be triggered. Open basic.rc with a text editor, find the string "FileExtents" and change the value to whatever you want. I changed it to hx3d. Next, create an empty file with the extension .hx3d, I created testbasic.hx3d under my folder. In firefox url box type c:\r.wang\testbasic.hx3d, you would also see the plugin triangle

Now, em....enjoy.
.
.
.
------