MakeHuman  0.95beta
glmodule.c
Go to the documentation of this file.
00001 
00031 #ifdef _DEBUG
00032 #undef _DEBUG
00033 #include <Python.h>
00034 #define _DEBUG
00035 #else
00036 #include <Python.h>
00037 #endif
00038 
00039 #include <assert.h>
00040 #include "glmodule.h"
00041 #include "core.h"
00042 
00043 #ifdef __WIN32__
00044 #include <windows.h>
00045 #include <SDL_syswm.h>
00046 #elif __APPLE__
00047 #include "SDL_image/SDL_image.h"
00048 #else
00049 #include <X11/Xlib.h>
00050 #include <X11/Xutil.h>
00051 #include <GL/glx.h>
00052 #endif
00053 #ifdef __APPLE__
00054 #include <Python/structmember.h>
00055 #else
00056 #include <structmember.h>
00057 #endif
00058 
00059 static int g_savedx=0; /*saved x mouse position*/
00060 static int g_savedy=0; /*saved y mouse position*/
00061 static int g_desktopWidth = 0;
00062 static int g_desktopHeight = 0;
00063 static int g_windowWidth = 800;
00064 static int g_windowHeight = 600;
00065 static SDL_Surface *g_screen = NULL;
00066 
00067 #ifndef __APPLE__
00068 typedef SDL_Surface *(*PFN_IMG_LOAD)(const char *);
00069 static void *g_sdlImageHandle = NULL;
00070 static PFN_IMG_LOAD IMG_Load = NULL;
00071 #endif
00072 
00073 typedef struct
00074 {
00075     PyObject_HEAD
00076 
00077     float fovAngle;
00078     float nearPlane;
00079     float farPlane;
00080 
00081     int projection;
00082 
00083     int stereoMode;
00084     float eyeSeparation;
00085 
00086     float eyeX;
00087     float eyeY;
00088     float eyeZ;
00089     float focusX;
00090     float focusY;
00091     float focusZ;
00092     float upX;
00093     float upY;
00094     float upZ;
00095 } Camera;
00096 
00097 void mhCameraPosition(Camera *camera, int eye);
00098 
00099 // Camera attributes directly accessed by Python
00100 static PyMemberDef Camera_members[] =
00101 {
00102     {"fovAngle", T_FLOAT, offsetof(Camera, fovAngle), 0, "The Field Of View angle."},
00103     {"nearPlane", T_FLOAT, offsetof(Camera, nearPlane), 0, "The Near Clipping Plane."},
00104     {"farPlane", T_FLOAT, offsetof(Camera, farPlane), 0, "The Far Clipping Plane."},
00105     {"projection", T_UINT, offsetof(Camera, projection), 0, "The projection type, 0 for orthogonal, 1 for perspective."},
00106     {"stereoMode", T_UINT, offsetof(Camera, stereoMode), 0, "The Stereo Mode, 0 for no stereo, 1 for toe-in, 2 for off-axis."},
00107     {"eyeSeparation", T_FLOAT, offsetof(Camera, eyeSeparation), 0, "The Eye Separation."},
00108     {"eyeX", T_FLOAT, offsetof(Camera, eyeX), 0, "The x position of the eye."},
00109     {"eyeY", T_FLOAT, offsetof(Camera, eyeY), 0, "The y position of the eye."},
00110     {"eyeZ", T_FLOAT, offsetof(Camera, eyeZ), 0, "The z position of the eye."},
00111     {"focusX", T_FLOAT, offsetof(Camera, focusX), 0, "The x position of the focus."},
00112     {"focusY", T_FLOAT, offsetof(Camera, focusY), 0, "The y position of the focus."},
00113     {"focusZ", T_FLOAT, offsetof(Camera, focusZ), 0, "The z position of the focus."},
00114     {"upX", T_FLOAT, offsetof(Camera, upX), 0, "The x of the up vector."},
00115     {"upY", T_FLOAT, offsetof(Camera, upY), 0, "The y of the up vector."},
00116     {"upZ", T_FLOAT, offsetof(Camera, upZ), 0, "The z of the up vector."},
00117     {NULL}  /* Sentinel */
00118 };
00119 
00120 PyObject *Camera_convertToScreen(Camera *camera, PyObject *args);
00121 PyObject *Camera_convertToWorld2D(Camera *camera, PyObject *args);
00122 PyObject *Camera_convertToWorld3D(Camera *camera, PyObject *args);
00123 
00124 // Camera Methods
00125 static PyMethodDef Camera_methods[] =
00126 {
00127     {"convertToScreen", (PyCFunction)Camera_convertToScreen, METH_VARARGS,
00128         "Converts world coordinates to screen coordinates."
00129     },
00130     {"convertToWorld2D", (PyCFunction)Camera_convertToWorld2D, METH_VARARGS,
00131      "Converts 2D screen coordinates to world coordinates."
00132     },
00133     {"convertToWorld3D", (PyCFunction)Camera_convertToWorld3D, METH_VARARGS,
00134      "Converts 3D screen coordinates to world coordinates."
00135     },
00136     {NULL}  /* Sentinel */
00137 };
00138 
00139 static PyObject *Camera_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
00140 static int Camera_init(Camera *self, PyObject *args, PyObject *kwds);
00141 
00142 // Camera type definition
00143 PyTypeObject CameraType =
00144 {
00145     PyObject_HEAD_INIT(NULL)
00146     0,                                        // ob_size
00147     "mh.Camera",                              // tp_name
00148     sizeof(Camera),                           // tp_basicsize
00149     0,                                        // tp_itemsize
00150     0,                                        // tp_dealloc
00151     0,                                        // tp_print
00152     0,                                        // tp_getattr
00153     0,                                        // tp_setattr
00154     0,                                        // tp_compare
00155     0,                                        // tp_repr
00156     0,                                        // tp_as_number
00157     0,                                        // tp_as_sequence
00158     0,                                        // tp_as_mapping
00159     0,                                        // tp_hash
00160     0,                                        // tp_call
00161     0,                                        // tp_str
00162     0,                                        // tp_getattro
00163     0,                                        // tp_setattro
00164     0,                                        // tp_as_buffer
00165     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
00166     "Camera object",                          // tp_doc
00167     0,                                        // tp_traverse
00168     0,                                        // tp_clear
00169     0,                                        // tp_richcompare
00170     0,                                        // tp_weaklistoffset
00171     0,                                        // tp_iter
00172     0,                                        // tp_iternext
00173     Camera_methods,                           // tp_methods
00174     Camera_members,                           // tp_members
00175     0,                                        // tp_getset
00176     0,                                        // tp_base
00177     0,                                        // tp_dict
00178     0,                                        // tp_descr_get
00179     0,                                        // tp_descr_set
00180     0,                                        // tp_dictoffset
00181     (initproc)Camera_init,                    // tp_init
00182     0,                                        // tp_alloc
00183     Camera_new,                               // tp_new
00184 };
00185 
00191 void RegisterCamera(PyObject *module)
00192 {
00193     if (PyType_Ready(&CameraType) < 0)
00194         return;
00195 
00196     Py_INCREF(&CameraType);
00197     PyModule_AddObject(module, "Camera", (PyObject*)&CameraType);
00198 }
00199 
00205 static PyObject *Camera_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
00206 {
00207     // Alloc Python data
00208     Camera *self = (Camera*)type->tp_alloc(type, 0);
00209 
00210     // Init our data
00211     if (self)
00212     {
00213         self->fovAngle = 25.0f;
00214         self->nearPlane = 0.1f;
00215         self->farPlane = 100.0f;
00216 
00217         self->projection = 1;
00218 
00219         self->stereoMode = 0;
00220         self->eyeSeparation = 1.0f;
00221 
00222         self->eyeX = 0.0f;
00223         self->eyeY = 0.0f;
00224         self->eyeZ = 60.0f;
00225         self->focusX = 0.0f;
00226         self->focusY = 0.0f;
00227         self->focusZ = 0.0f;
00228         self->upX = 0.0f;
00229         self->upY = 1.0f;
00230         self->upZ = 0.0f;
00231     }
00232 
00233     return (PyObject*)self;
00234 }
00235 
00242 static int Camera_init(Camera *self, PyObject *args, PyObject *kwds)
00243 {
00244     char *path = NULL;
00245 
00246     if (!PyArg_ParseTuple(args, "|s", &path))
00247         return -1;
00248 
00249     return 0;
00250 }
00251 
00252 typedef struct
00253 {
00254     PyObject_HEAD
00255     GLuint textureId;
00256     int width;
00257     int height;
00258 } Texture;
00259 
00260 // Texture attributes directly accessed by Python
00261 static PyMemberDef Texture_members[] =
00262 {
00263     {"textureId", T_UINT, offsetof(Texture, textureId), READONLY, "The id of the OpenGL texture."},
00264     {"width",     T_UINT, offsetof(Texture, width),     READONLY, "The width of the texture in pixels."},
00265     {"height",    T_UINT, offsetof(Texture, height),    READONLY, "The height of the texture in pixels."},
00266     {NULL}  /* Sentinel */
00267 };
00268 
00269 static PyObject *Texture_loadImage(Texture *texture, PyObject *path);
00270 
00271 // Texture Methods
00272 static PyMethodDef Texture_methods[] =
00273 {
00274     {"loadImage", (PyCFunction)Texture_loadImage, METH_O,
00275         "Loads the specified image from file"
00276     },
00277     {NULL}  /* Sentinel */
00278 };
00279 
00280 static void Texture_dealloc(Texture *self);
00281 static PyObject *Texture_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
00282 static int Texture_init(Texture *self, PyObject *args, PyObject *kwds);
00283 
00284 // Texture type definition
00285 PyTypeObject TextureType =
00286 {
00287     PyObject_HEAD_INIT(NULL)
00288     0,                                        // ob_size
00289     "mh.Texture",                             // tp_name
00290     sizeof(Texture),                          // tp_basicsize
00291     0,                                        // tp_itemsize
00292     (destructor)Texture_dealloc,              // tp_dealloc
00293     0,                                        // tp_print
00294     0,                                        // tp_getattr
00295     0,                                        // tp_setattr
00296     0,                                        // tp_compare
00297     0,                                        // tp_repr
00298     0,                                        // tp_as_number
00299     0,                                        // tp_as_sequence
00300     0,                                        // tp_as_mapping
00301     0,                                        // tp_hash
00302     0,                                        // tp_call
00303     0,                                        // tp_str
00304     0,                                        // tp_getattro
00305     0,                                        // tp_setattro
00306     0,                                        // tp_as_buffer
00307     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
00308     "Texture object",                         // tp_doc
00309     0,                                        // tp_traverse
00310     0,                                        // tp_clear
00311     0,                                        // tp_richcompare
00312     0,                                        // tp_weaklistoffset
00313     0,                                        // tp_iter
00314     0,                                        // tp_iternext
00315     Texture_methods,                          // tp_methods
00316     Texture_members,                          // tp_members
00317     0,                                        // tp_getset
00318     0,                                        // tp_base
00319     0,                                        // tp_dict
00320     0,                                        // tp_descr_get
00321     0,                                        // tp_descr_set
00322     0,                                        // tp_dictoffset
00323     (initproc)Texture_init,                   // tp_init
00324     0,                                        // tp_alloc
00325     Texture_new,                              // tp_new
00326 };
00327 
00333 void RegisterTexture(PyObject *module)
00334 {
00335     if (PyType_Ready(&TextureType) < 0)
00336         return;
00337 
00338     Py_INCREF(&TextureType);
00339     PyModule_AddObject(module, "Texture", (PyObject*)&TextureType);
00340 }
00341 
00347 static void Texture_dealloc(Texture *self)
00348 {
00349     // Free our data
00350     glDeleteTextures(1, &self->textureId);
00351 
00352     // Free Python data
00353     self->ob_type->tp_free((PyObject*)self);
00354 }
00355 
00361 static PyObject *Texture_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
00362 {
00363     // Alloc Python data
00364     Texture *self = (Texture*)type->tp_alloc(type, 0);
00365 
00366     // Init our data
00367     if (self)
00368     {
00369         glGenTextures(1, &self->textureId);
00370         self->width = 0;
00371         self->height = 0;
00372     }
00373 
00374     return (PyObject*)self;
00375 }
00376 
00383 static int Texture_init(Texture *self, PyObject *args, PyObject *kwds)
00384 {
00385     char *path = NULL;
00386 
00387     if (!PyArg_ParseTuple(args, "|s", &path))
00388         return -1;
00389 
00390     if (path && !mhLoadTexture(path, self->textureId, &self->width, &self->height))
00391         return -1;
00392 
00393     return 0;
00394 }
00395 
00396 static PyObject *Texture_loadImage(Texture *texture, PyObject *path)
00397 {
00398     if (PyString_Check(path))
00399     {
00400         if (!mhLoadTexture(PyString_AsString(path), texture->textureId, &texture->width, &texture->height))
00401             return NULL;
00402     }
00403     else if (PyUnicode_Check(path))
00404     {
00405         path = PyUnicode_AsUTF8String(path);
00406         if (!mhLoadTexture(PyString_AsString(path), texture->textureId, &texture->width, &texture->height))
00407         {
00408             Py_DECREF(path);
00409             return NULL;
00410         }
00411         Py_DECREF(path);
00412     }
00413     else
00414     {
00415         PyErr_SetString(PyExc_TypeError, "String or Unicode object expected");
00416         return NULL;
00417     }
00418 
00419     return Py_BuildValue("");
00420 }
00421 
00422 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00423 
00429 static uint32_t swapLong(uint32_t inValue)
00430 {
00431 #ifdef __GNUC__
00432 #   if defined(__ppc__)
00433         register uint32_t word;
00434         __asm__("lwbrx %0,%2,%1" : "=r" (word) : "r" (&inValue), "b" (0));
00435         return word;
00436 #   elif defined(__x86__) || defined(__i386__) || defined (__x86_64__)
00437         register uint32_t word;
00438         __asm__("bswap %0" : "=r" (word) : "0" (inValue));
00439         return word;
00440 #   endif
00441 #endif
00442     return (((inValue      ) & 0xff) << 24) |
00443            (((inValue >>  8) & 0xff) << 16) |
00444            (((inValue >> 16) & 0xff) <<  8) |
00445            (((inValue >> 24) & 0xff));
00446 }
00447 #endif // #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00448 
00461 static int longCopyEndianSafe(uint32_t *destPtr, const uint32_t *srcPtr, size_t inLongs)
00462 {
00463 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
00464     memcpy(destPtr, srcPtr, inLongs << 2);
00465 #else /* For Big Endian we'll need to swap all bytes within the long */
00466     int i;
00467     for (i=0; i<inLongs; ++i)
00468     {
00469         *(destPtr++) = swapLong(*(srcPtr++));
00470     }
00471 #endif
00472     return inLongs;
00473 }
00474 
00482 static void mhFlipSurface(SDL_Surface *surface)
00483 {
00484     unsigned char *line = (unsigned char*)malloc(surface->pitch);
00485     const size_t lineBytes = surface->pitch;
00486     const size_t lineLongs = lineBytes >> 2;
00487 
00488     unsigned char *pixelsA;
00489     unsigned char *pixelsB;
00490 
00491     int lineIndex;
00492 
00493     if (line)
00494     {
00495         if (SDL_MUSTLOCK(surface)) SDL_LockSurface(surface);
00496 
00497         pixelsA = (unsigned char*)surface->pixels;
00498         pixelsB = (unsigned char*)surface->pixels + (surface->h - 1) * lineBytes;
00499 
00500         for (lineIndex = 0; lineIndex < surface->h >> 1; lineIndex++)
00501         {
00502             memcpy((uint32_t*)line,    (const uint32_t*)pixelsA, lineBytes);
00503             longCopyEndianSafe((uint32_t*)pixelsA, (const uint32_t*)pixelsB, lineLongs);
00504             longCopyEndianSafe((uint32_t*)pixelsB, (const uint32_t*)line,    lineLongs);
00505 
00506             pixelsA += lineBytes;
00507             pixelsB -= lineBytes;
00508         }
00509         if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface);
00510         free(line);
00511     }
00512 }
00513 
00520 GLuint mhLoadTexture(const char *fname, GLuint texture, int *width, int *height)
00521 {
00522     int internalFormat, format;
00523     SDL_Surface *surface;
00524 
00525     //printf("Loading texture '%s'\n", fname);
00526 
00527     if (!texture)
00528         glGenTextures(1, &texture);
00529 
00530 #ifndef __APPLE__ // OS X utilizes the SDL_image framework for image loading!
00531     if (!g_sdlImageHandle)
00532     {
00533 #ifdef __WIN32__
00534         g_sdlImageHandle = SDL_LoadObject("SDL_image");
00535 #else
00536         g_sdlImageHandle = SDL_LoadObject("libSDL_image-1.2.so.0");
00537 #endif
00538 
00539         if (!g_sdlImageHandle)
00540         {
00541             PyErr_Format(PyExc_RuntimeError, "Could not load %s, SDL_image not found", fname);
00542             return 0;
00543         }
00544 
00545         IMG_Load = (PFN_IMG_LOAD)SDL_LoadFunction(g_sdlImageHandle, "IMG_Load");
00546     }
00547 
00548     if (!IMG_Load)
00549     {
00550         PyErr_Format(PyExc_RuntimeError, "Could not load %s, IMG_Load not found", fname);
00551         return 0;
00552     }
00553 #endif // ifndef __APPLE__
00554     surface = (SDL_Surface*)IMG_Load(fname);
00555 
00556     if (!surface)
00557     {
00558         PyErr_Format(PyExc_RuntimeError, "Could not load %s, %s", fname, SDL_GetError());
00559         return 0;
00560     }
00561 
00562     switch (surface->format->BytesPerPixel)
00563     {
00564     case 1:
00565         internalFormat = GL_ALPHA8;
00566         format = GL_ALPHA;
00567         break;
00568     case 3:
00569         internalFormat = 3;
00570         if (surface->format->Rshift) // If there is a shift on the red value, we need to tell that red and blue are switched
00571             format = GL_BGR;
00572         else
00573             format = GL_RGB;
00574         break;
00575     case 4:
00576         internalFormat = 4;
00577         if (surface->format->Rshift) // If there is a shift on the red value, we need to tell that red and blue are switched
00578             format = GL_BGRA;
00579         else
00580             format = GL_RGBA;
00581         break;
00582     default:
00583         SDL_FreeSurface(surface);
00584         PyErr_Format(PyExc_RuntimeError, "Could not load %s, unsupported pixel format", fname);
00585         return 0;
00586 
00587     }
00588 
00589     // For some reason we need to flip the surface vertically
00590     mhFlipSurface(surface);
00591 
00592     if (surface->h == 1)
00593     {
00594         glBindTexture(GL_TEXTURE_1D, texture);
00595         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE_EXT);
00596         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE_EXT);
00597         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00598         glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00599         gluBuild1DMipmaps(GL_TEXTURE_1D, internalFormat, surface->w, format, GL_UNSIGNED_BYTE, surface->pixels);
00600         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00601     }
00602     else
00603     {
00604         glBindTexture(GL_TEXTURE_2D, texture);
00605         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE_EXT);
00606         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE_EXT);
00607 
00608 // hdusel: Just a test for Mac OS X in order to prevent that the fonts look so ugly (blurry) on the Mac port. 
00609 // So try to permit MIPMAP Interpolation for fonts.
00610 #if defined(__APPLE__)
00611         const int isFont = (strstr(fname, "/fonts/") != NULL);
00612         if (isFont)
00613         {
00614             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00615             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00616         }
00617         else 
00618         {
00619     #if defined(__ppc__)
00620             // On PowerPC Macs just don't use mipmapping
00621             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00622             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00623     #else
00624             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00625             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00626     #endif
00627         }
00628 #else
00629         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00630         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00631 #endif
00632         gluBuild2DMipmaps(GL_TEXTURE_2D, internalFormat, surface->w, surface->h, format, GL_UNSIGNED_BYTE, surface->pixels);
00633 //        glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, surface->w, surface->h, 0, format, GL_UNSIGNED_BYTE, surface->pixels);
00634         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00635     }
00636 
00637     if (width)
00638         *width = surface->w;
00639     if (height)
00640         *height = surface->h;
00641 
00642     SDL_FreeSurface(surface);
00643 
00644     return texture;
00645 }
00646 
00647 GLuint mhCreateVertexShader(const char *source)
00648 {
00649     GLuint v;
00650     GLint status;
00651 
00652     if (GLEW_VERSION_2_0)
00653     {
00654       v = glCreateShader(GL_VERTEX_SHADER);
00655 
00656       glShaderSource(v, 1, &source, NULL);
00657 
00658       glCompileShader(v);
00659       glGetShaderiv(v, GL_COMPILE_STATUS, &status);
00660       if (status != GL_TRUE)
00661       {
00662           GLsizei logLength;
00663 
00664           glGetShaderiv(v, GL_INFO_LOG_LENGTH, &logLength);
00665 
00666           if (logLength > 0)
00667           {
00668               char *log;
00669               GLsizei charsWritten;
00670 
00671               log = (char*)malloc(logLength);
00672               glGetShaderInfoLog(v, logLength, &charsWritten, log);
00673               PyErr_Format(PyExc_RuntimeError, "Error compiling vertex shader: %s", log);
00674               free(log);
00675           }
00676           else
00677               PyErr_SetString(PyExc_RuntimeError, "Error compiling vertex shader");
00678 
00679           return 0;
00680       }
00681 
00682       return v;
00683     }
00684     else if (GLEW_ARB_shader_objects)
00685     {
00686       v = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
00687 
00688       glShaderSourceARB(v, 1, &source, NULL);
00689 
00690       glCompileShaderARB(v);
00691       glGetObjectParameterivARB(v, GL_OBJECT_COMPILE_STATUS_ARB, &status);
00692       if (status != GL_TRUE)
00693       {
00694         GLsizei logLength;
00695 
00696         glGetObjectParameterivARB(v, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logLength);
00697 
00698         if (logLength > 0)
00699         {
00700           char *log;
00701           GLsizei charsWritten;
00702 
00703           log = (char*)malloc(logLength);
00704           glGetInfoLogARB(v, logLength, &charsWritten, log);
00705           PyErr_Format(PyExc_RuntimeError, "Error compiling vertex shader: %s", log);
00706           free(log);
00707         }
00708         else
00709           PyErr_SetString(PyExc_RuntimeError, "Error compiling vertex shader");
00710 
00711         return 0;
00712       }
00713 
00714       return v;
00715     }
00716     else
00717     {
00718       PyErr_SetString(PyExc_RuntimeError, "No shader support detected");
00719       return 0;
00720     }
00721 }
00722 
00723 GLuint mhCreateFragmentShader(const char *source)
00724 {
00725     GLuint f;
00726     GLint status;
00727     
00728     if (GLEW_VERSION_2_0)
00729     {
00730       f = glCreateShader(GL_FRAGMENT_SHADER);
00731 
00732       glShaderSource(f, 1, &source, NULL);
00733 
00734       glCompileShader(f);
00735       glGetShaderiv(f, GL_COMPILE_STATUS, &status);
00736       if (status != GL_TRUE)
00737       {
00738         GLsizei logLength;
00739 
00740         glGetShaderiv(f, GL_INFO_LOG_LENGTH, &logLength);
00741 
00742         if (logLength > 0)
00743         {
00744           char *log;
00745           GLsizei charsWritten;
00746 
00747           log = (char*)malloc(logLength);
00748           glGetShaderInfoLog(f, logLength, &charsWritten, log);
00749           PyErr_Format(PyExc_RuntimeError, "Error compiling fragment shader: %s", log);
00750           free(log);
00751         }
00752         else
00753           PyErr_SetString(PyExc_RuntimeError, "Error compiling fragment shader");
00754 
00755         return 0;
00756       }
00757 
00758       return f;
00759     }
00760     else if (GLEW_ARB_shader_objects)
00761     {
00762       f = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
00763 
00764       glShaderSourceARB(f, 1, &source, NULL);
00765 
00766       glCompileShaderARB(f);
00767       glGetObjectParameterivARB(f, GL_OBJECT_COMPILE_STATUS_ARB, &status);
00768       if (status != GL_TRUE)
00769       {
00770         GLsizei logLength;
00771 
00772         glGetObjectParameterivARB(f, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logLength);
00773 
00774         if (logLength > 0)
00775         {
00776           char *log;
00777           GLsizei charsWritten;
00778 
00779           log = (char*)malloc(logLength);
00780           glGetInfoLogARB(f, logLength, &charsWritten, log);
00781           PyErr_Format(PyExc_RuntimeError, "Error compiling fragment shader: %s", log);
00782           free(log);
00783         }
00784         else
00785           PyErr_SetString(PyExc_RuntimeError, "Error compiling fragment shader");
00786 
00787         return 0;
00788       }
00789 
00790       return f;
00791     }
00792     else
00793     {
00794       PyErr_SetString(PyExc_RuntimeError, "No shader support detected");
00795       return 0;
00796     }
00797 }
00798 
00799 GLuint mhCreateShader(GLuint vertexShader, GLuint fragmentShader)
00800 {
00801     GLuint p;
00802     GLint status;
00803     
00804     if (GLEW_VERSION_2_0)
00805     {
00806       p = glCreateProgram();
00807 
00808       glAttachShader(p, vertexShader);
00809       glAttachShader(p, fragmentShader);
00810 
00811       glLinkProgram(p);
00812       glGetProgramiv(p, GL_LINK_STATUS, &status);
00813       if (status != GL_TRUE)
00814       {
00815         GLsizei logLength;
00816 
00817         glGetProgramiv(p, GL_INFO_LOG_LENGTH, &logLength);
00818 
00819         if (logLength > 0)
00820         {
00821           char *log;
00822           GLsizei charsWritten;
00823 
00824           log = (char*)malloc(logLength);
00825           glGetProgramInfoLog(p, logLength, &charsWritten, log);
00826           PyErr_Format(PyExc_RuntimeError, "Error linking shader: %s", log);
00827           free(log);
00828         }
00829         else
00830           PyErr_SetString(PyExc_RuntimeError, "Error linking shader");
00831 
00832         return 0;
00833       }
00834 
00835       return p;
00836     }
00837     else if (GLEW_ARB_shader_objects)
00838     {
00839       p = glCreateProgramObjectARB();
00840 
00841       glAttachObjectARB(p, vertexShader);
00842       glAttachObjectARB(p, fragmentShader);
00843 
00844       glLinkProgramARB(p);
00845       glGetObjectParameterivARB(p, GL_OBJECT_LINK_STATUS_ARB , &status);
00846       if (status != GL_TRUE)
00847       {
00848         GLsizei logLength;
00849 
00850         glGetObjectParameterivARB(p, GL_OBJECT_INFO_LOG_LENGTH_ARB, &logLength);
00851 
00852         if (logLength > 0)
00853         {
00854           char *log;
00855           GLsizei charsWritten;
00856 
00857           log = (char*)malloc(logLength);
00858           glGetInfoLogARB(p, logLength, &charsWritten, log);
00859           PyErr_Format(PyExc_RuntimeError, "Error linking shader: %s", log);
00860           free(log);
00861         }
00862         else
00863           PyErr_SetString(PyExc_RuntimeError, "Error linking shader");
00864 
00865         return 0;
00866       }
00867 
00868       return p;
00869     }
00870     else
00871     {
00872         PyErr_SetString(PyExc_RuntimeError, "No shader support detected");
00873         return 0;
00874     }
00875 }
00876 
00888 int mhGrabScreen(int x, int y, int width, int height, const char *filename)
00889 {
00890     GLint viewport[4];
00891     SDL_Surface *surface;
00892     GLenum format;
00893 
00894     if (width <= 0 || height <= 0)
00895     {
00896         PyErr_Format(PyExc_RuntimeError, "width or height is 0");
00897         return 0;
00898     }
00899 
00900     surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24, 0xFF, 0xFF00, 0xFF0000, 0);
00901     glGetIntegerv(GL_VIEWPORT, viewport);
00902 
00903     if (SDL_LockSurface(surface))
00904     {
00905         SDL_FreeSurface(surface);
00906         PyErr_Format(PyExc_RuntimeError, "Could not lock surface to grab region to file %s, %s", filename, SDL_GetError());
00907         return 0;
00908     }
00909 
00910     // Draw before grabbing, to make sure we grab a rendering and not a picking buffer
00911     mhDraw();
00912     glPixelStorei(GL_PACK_ALIGNMENT, 4);
00913 
00914     /* SDL interprets each pixel as a 32-bit number, so our masks must depend
00915        on the endianness (byte order) of the machine (PowerPC is big endian
00916        in contrast to i386 which is little endian!) */
00917 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00918     format = GL_BGR; /* For big endian Machines as based on PowerPC */
00919 #else
00920     format = GL_RGB; /* For little endian Machines as based on Intel x86 */
00921 #endif
00922     glReadPixels(x, viewport[3] - y - height, width, height, format, GL_UNSIGNED_BYTE, surface->pixels);
00923     mhFlipSurface(surface);
00924 
00925     SDL_UnlockSurface(surface);
00926 
00927     if (SDL_SaveBMP(surface, filename))
00928     {
00929         SDL_FreeSurface(surface);
00930         PyErr_Format(PyExc_RuntimeError, "Could not access file to grab region to file %s, %s", filename, SDL_GetError());
00931         return 0;
00932     }
00933 
00934     SDL_FreeSurface(surface);
00935     return 1;
00936 }
00937 
00948 void mhKeyDown(int key, unsigned short character, int modifiers)
00949 {
00950     callKeyDown(key, character, modifiers);
00951 }
00952 
00953 void mhKeyUp(int key, unsigned short character, int modifiers)
00954 {
00955     callKeyUp(key, character, modifiers);
00956 
00957     UpdatePickingBuffer();
00958 }
00959 
00977 unsigned int mhTimerFunc(unsigned int interval, void *param)
00978 {
00979     SDL_Event event;
00980 
00981     event.type = SDL_USEREVENT;
00982     event.user.code = 0;
00983     event.user.data1 = param;
00984     event.user.data2 = NULL;
00985 
00986     SDL_PushEvent(&event);
00987 
00988     /*reset the timer to recall the function again, after interval milliseconds*/
00989     return interval;
00990 }
00991 
01009 void mhMouseButtonDown(int b, int x, int y)
01010 {
01011     /* Since the mouse cursor doesn't move when a button is down, we
01012        save the mouse position and restore it later to avoid jumping.
01013        We also grab the input so we can move the (invisible) mouse outside the screen.
01014     */
01015     g_savedx=x;
01016     g_savedy=y;
01017 #ifdef __WIN32__
01018     SDL_WM_GrabInput(SDL_GRAB_ON);
01019 #endif
01020 
01021     // Check which object/group was hit
01022     if (b != 4 && b != 5)
01023         mhGetPickedColor(x, y);
01024 
01025     // Notify python
01026     callMouseButtonDown(b, x, y);
01027 
01028     // Update screen
01029     mhQueueUpdate();
01030 
01031     if (b != 4 && b != 5)
01032         UpdatePickingBuffer();
01033 }
01034 
01052 void mhMouseButtonUp(int b, int x, int y)
01053 {
01054     /* Since the mouse cursor doesn't move when a button is down, we
01055        save the mouse position and restore it later to avoid jumping.
01056        We also ungrab the previously grabbed input
01057     */
01058 #ifdef __WIN32__
01059     SDL_WM_GrabInput(SDL_GRAB_OFF);
01060 #endif
01061 
01062     // Check which object/group was hit
01063     if (b != 4 && b != 5)
01064     {
01065         mhGetPickedColor(x, y);
01066     }
01067 
01068     // Notify python
01069     callMouseButtonUp(b, x, y);
01070 
01071     // Update screen
01072     mhQueueUpdate();
01073 
01074     UpdatePickingBuffer();
01075 }
01076 
01096 void mhMouseMotion(int s, int x, int y, int xrel, int yrel)
01097 {
01098     // Check which object/group was hit
01099     if (!s)
01100         mhGetPickedColor(x, y);
01101 
01102     // Notify python
01103     callMouseMotion(s, x, y, xrel, yrel);
01104 
01105     // Update screen
01106     if (s)
01107         mhQueueUpdate();
01108 }
01109 
01110 static unsigned char *pickingBuffer = NULL;
01111 static int pickingBufferSize = 0;
01112 
01113 void UpdatePickingBuffer(void)
01114 {
01115     int i;
01116     // Get the viewport
01117     GLint viewport[4];
01118     GLint width;
01119     GLint height;
01120     glGetIntegerv(GL_VIEWPORT, viewport);
01121 
01122     width = viewport[2];
01123     height = viewport[3];
01124 
01125     // Resize the buffer in case the window size has changed
01126     if (pickingBufferSize != width * height * 3)
01127     {
01128         pickingBufferSize = width * height * 3;
01129         pickingBuffer = (unsigned char*)realloc(pickingBuffer, pickingBufferSize);
01130         assert(pickingBuffer != NULL);
01131     }
01132 
01133     // Turn off lighting
01134     glDisable(GL_LIGHTING);
01135 
01136     // Turn off antialiasing
01137     glDisable (GL_BLEND);
01138     glDisable(GL_MULTISAMPLE);
01139 
01140     // Clear screen
01141     glClearColor(0.0, 0.0, 0.0, 0.0);
01142     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01143 
01144     for (i = 0; i < PyList_Size(G.cameras); i++)
01145     {
01146         mhCameraPosition((Camera*)PyList_GetItem(G.cameras, i), 0);
01147         mhDrawMeshes(1, i);
01148     }
01149 
01150     // Make sure the data is 1 byte aligned
01151     glPixelStorei(GL_PACK_ALIGNMENT, 1);
01152     //glFlush();
01153     //glFinish();
01154     glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, pickingBuffer);
01155     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01156 
01157     // Turn on antialiasing
01158     glEnable (GL_BLEND);
01159     glEnable(GL_MULTISAMPLE);
01160 
01161     /* restore lighting */
01162     glEnable(GL_LIGHTING);
01163 
01164     /* hdusel: Bugfix for http://code.google.com/p/makehuman/issues/detail?id=16
01165      * "Red and black window - 'selection rendering'"
01166      *
01167      * This error happened for the OS X port only
01168      *
01169      * So I enforce a redraw whenever the picking buffer will be updated.
01170      * But I'm not certain weather we need this for OS X only? */
01171 #ifdef __APPLE__
01172     mhDraw();
01173 #endif
01174 }
01175 
01199 void mhGetPickedColor(int x, int y)
01200 {
01201     // Viewport declaration (required before other expressions)
01202     GLint viewport[4];
01203 
01204     glGetIntegerv(GL_VIEWPORT, viewport);
01205 
01206     y = viewport[3] - y;
01207 
01208     if (y < 0 || y >= viewport[3] || x < 0 || x >= viewport[2])
01209     {
01210         memset(G.color_picked, 0, 3);
01211         return;
01212     }
01213 
01214     if (!pickingBuffer)
01215         UpdatePickingBuffer();
01216 
01217     memcpy(G.color_picked, pickingBuffer + (y * viewport[2] + x) * 3, 3);
01218 }
01219 
01229 PyObject *Camera_convertToScreen(Camera *camera, PyObject *args)
01230 {
01231     GLint viewport[4];
01232     GLdouble modelview[16], projection[16];
01233     double world[3], screen[3];
01234 
01235     if (!PyArg_ParseTuple(args, "ddd", world, world + 1, world + 2))
01236         return NULL;
01237 
01238     mhCameraPosition(camera, 0);
01239 
01240     glGetIntegerv(GL_VIEWPORT, viewport);
01241     glGetDoublev(GL_PROJECTION_MATRIX, projection);
01242     glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
01243 
01244     gluProject(world[0], world[1], world[2], modelview, projection, viewport, screen, screen + 1, screen + 2);
01245     screen[1] = viewport[3] - screen[1];
01246 
01247     return Py_BuildValue("[d,d,d]", screen[0], screen[1], screen[2]);
01248 }
01249 
01259 PyObject *Camera_convertToWorld2D(Camera *camera, PyObject *args)
01260 {
01261     GLint viewport[4];
01262     GLdouble modelview[16], projection[16];
01263     GLdouble z;
01264     double screen[2], world[3];
01265 
01266     if (!PyArg_ParseTuple(args, "dd", screen, screen + 1))
01267         return NULL;
01268 
01269     mhCameraPosition(camera, 0);
01270 
01271     glGetIntegerv(GL_VIEWPORT, viewport);
01272     glGetDoublev(GL_PROJECTION_MATRIX, projection);
01273     glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
01274 
01275     glReadPixels((GLint)screen[0], (GLint)(viewport[3] - screen[1]), 1, 1, GL_DEPTH_COMPONENT, GL_DOUBLE, &z);
01276     gluUnProject(screen[0], viewport[3] - screen[1], z, modelview, projection, viewport, world, world + 1, world + 2);
01277 
01278     return Py_BuildValue("[d,d,d]", world[0], world[1], world[2]);
01279 }
01280 
01290 PyObject *Camera_convertToWorld3D(Camera *camera, PyObject *args)
01291 {
01292     GLint viewport[4];
01293     GLdouble modelview[16], projection[16];
01294     double screen[3], world[3];
01295 
01296     if (!PyArg_ParseTuple(args, "ddd", screen, screen + 1, screen + 2))
01297         return NULL;
01298 
01299     mhCameraPosition(camera, 0);
01300 
01301     glGetIntegerv(GL_VIEWPORT, viewport);
01302     glGetDoublev(GL_PROJECTION_MATRIX, projection);
01303     glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
01304 
01305     gluUnProject(screen[0], viewport[3] - screen[1], screen[2], modelview, projection, viewport, world, world + 1, world + 2);
01306 
01307     return Py_BuildValue("[d,d,d]", world[0], world[1], world[2]);
01308 }
01309 
01316 void mhReshape(int w, int h)
01317 {
01318     /*Prevent a division by zero when minimising the window*/
01319     if (h == 0)
01320         h = 1;
01321     /*Set the drawable region of the window*/
01322     glViewport(0, 0, w, h);
01323     // set up the projection matrix
01324     glMatrixMode(GL_PROJECTION);
01325     glLoadIdentity();
01326 
01327     // go back to modelview matrix so we can move the objects about
01328     glMatrixMode(GL_MODELVIEW);
01329     G.windowHeight = h;
01330     G.windowWidth = w;
01331 
01332     UpdatePickingBuffer();
01333 }
01334 
01340 void mhDrawBegin(void)
01341 {
01342     // clear the screen & depth buffer
01343     glClearColor(G.clearColor[0], G.clearColor[1], G.clearColor[2], G.clearColor[3]);
01344     glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
01345 }
01346 
01351 void mhDrawEnd(void)
01352 {
01353     SDL_GL_SwapBuffers();
01354 }
01355 
01360 void OnInit(void)
01361 {
01362     /*Lights and materials*/
01363     const float lightPos[] = { -10.99f, 20.0f, 20.0f, 1.0f};  /* Light Position */
01364     const float ambientLight[] = { 0.0f, 0.0f, 0.0f, 1.0f};   /* Ambient Light Values */
01365     const float diffuseLight[] = { 1.0f, 1.0f, 1.0f, 1.0f};   /* Diffuse Light Values */
01366     const float specularLight[] = {1.0f, 1.0f, 1.0f, 1.0f};   /* Specular Light Values */
01367     const float MatAmb[] = {0.11f, 0.11f, 0.11f, 1.0f};       /* Material - Ambient Values */
01368     const float MatDif[] = {1.0f, 1.0f, 1.0f, 1.0f};          /* Material - Diffuse Values */
01369     const float MatSpc[] = {0.2f, 0.2f, 0.2f, 1.0f};          /* Material - Specular Values */
01370     const float MatShn[] = {10.0f};                           /* Material - Shininess */
01371     //const float MatEms[] = {0.1f, 0.05f, 0.0f, 1.0f};       /* Material - emission Values */
01372 
01373     glewInit();
01374 
01375     glEnable(GL_DEPTH_TEST);                                  /* Hidden surface removal */
01376     //glEnable(GL_CULL_FACE);                                   /* Inside face removal */
01377     //glEnable(GL_ALPHA_TEST);
01378     //glAlphaFunc(GL_GREATER, 0.0f);
01379     glDisable(GL_DITHER);
01380     glEnable(GL_LIGHTING);                                    /* Enable lighting */
01381     glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
01382     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
01383     glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
01384     glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
01385     glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); // If we enable this, we have stronger specular highlights
01386     glMaterialfv(GL_FRONT, GL_AMBIENT, MatAmb);               /* Set Material Ambience */
01387     glMaterialfv(GL_FRONT, GL_DIFFUSE, MatDif);               /* Set Material Diffuse */
01388     glMaterialfv(GL_FRONT, GL_SPECULAR, MatSpc);              /* Set Material Specular */
01389     glMaterialfv(GL_FRONT, GL_SHININESS, MatShn);             /* Set Material Shininess */
01390     //glMaterialfv(GL_FRONT, GL_EMISSION, MatEms);              /* Set Material Emission */
01391     glEnable(GL_LIGHT0);
01392     glEnable(GL_COLOR_MATERIAL);
01393     glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
01394     //glEnable(GL_TEXTURE_2D);
01395     glEnable(GL_BLEND);
01396     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
01397     /*Activate and specify pointers to vertex and normal array*/
01398     glEnableClientState(GL_NORMAL_ARRAY);
01399     glEnableClientState(GL_COLOR_ARRAY);
01400     glEnableClientState(GL_VERTEX_ARRAY);
01401 }
01402 
01407 void OnExit(void)
01408 {
01409     /*Deactivate the pointers to vertex and normal array*/
01410     glDisableClientState(GL_VERTEX_ARRAY);
01411     glDisableClientState(GL_NORMAL_ARRAY);
01412     //glDisableClientState(GL_TEXTURE_COORD_ARRAY);
01413     glDisableClientState(GL_COLOR_ARRAY);
01414     printf("Exit from event loop\n");
01415 }
01416 
01424 void mhCameraPosition(Camera *camera, int eye)
01425 {
01426     int stereoMode = 0;
01427     if (eye)
01428         stereoMode = camera->stereoMode;
01429 
01430     switch (stereoMode)
01431     {
01432     case 0: // No stereo
01433     {
01434         glMatrixMode(GL_PROJECTION);
01435         glLoadIdentity();
01436 
01437         if (camera->projection)
01438             gluPerspective(camera->fovAngle, (float)G.windowWidth/G.windowHeight, camera->nearPlane, camera->farPlane);
01439         else
01440             glOrtho(0.0, G.windowWidth, G.windowHeight, 0.0, camera->nearPlane, camera->farPlane);
01441 
01442         glMatrixMode(GL_MODELVIEW);
01443         glLoadIdentity();
01444         gluLookAt(camera->eyeX, camera->eyeY, camera->eyeZ,       // Eye
01445                   camera->focusX, camera->focusY, camera->focusZ, // Focus
01446                   camera->upX, camera->upY, camera->upZ);         // Up
01447         break;
01448     }
01449     case 1: // Toe-in method, uses different eye positions, same focus point and projection
01450     {
01451         glMatrixMode(GL_PROJECTION);
01452         glLoadIdentity();
01453         gluPerspective(camera->fovAngle, (float)G.windowWidth/G.windowHeight, camera->nearPlane, camera->farPlane);
01454 
01455         glMatrixMode(GL_MODELVIEW);
01456         glLoadIdentity();
01457 
01458         if (eye == 1)
01459             gluLookAt(camera->eyeX - 0.5 * camera->eyeSeparation, camera->eyeY, camera->eyeZ, // Eye
01460                   camera->focusX, camera->focusY, camera->focusZ,                             // Focus
01461                   camera->upX, camera->upY, camera->upZ);                                     // Up
01462         else if (eye == 2)
01463             gluLookAt(camera->eyeX + 0.5 * camera->eyeSeparation, camera->eyeY, camera->eyeZ, // Eye
01464                   camera->focusX, camera->focusY, camera->focusZ,                             // Focus
01465                   camera->upX, camera->upY, camera->upZ);                                     // Up
01466 
01467         break;
01468     }
01469     case 2: // Off-axis method, uses different eye positions, focus points and projections
01470     {
01471         double aspectratio = G.windowWidth / (double)G.windowHeight;
01472         double widthdiv2 = tan(camera->fovAngle * 3.14159/360.0) * camera->nearPlane;
01473         double left  = - aspectratio * widthdiv2;
01474         double right = aspectratio * widthdiv2;
01475         double top = widthdiv2;
01476         double bottom = -widthdiv2;
01477         double eyePosition;
01478 
01479         if (eye == 1) // Left
01480             eyePosition = -0.5 * camera->eyeSeparation;
01481         else if (eye == 2) // Right
01482             eyePosition = 0.5 * camera->eyeSeparation;
01483         else
01484             eyePosition = 0.0;
01485 
01486         left -= eyePosition * camera->nearPlane / camera->eyeZ;
01487         right -= eyePosition * camera->nearPlane / camera->eyeZ;
01488 
01489         // Left frustum is moved right, right frustum moved left
01490         glMatrixMode(GL_PROJECTION);
01491         glLoadIdentity();
01492         glFrustum(left, right, bottom, top, camera->nearPlane, camera->farPlane);
01493 
01494         // Left camera is moved left, right camera moved right
01495         glMatrixMode(GL_MODELVIEW);
01496         glLoadIdentity();
01497         gluLookAt(camera->eyeX + eyePosition, camera->eyeY, camera->eyeZ,       // Eye
01498                   camera->focusX + eyePosition, camera->focusY, camera->focusZ, // Focus
01499                   camera->upX, camera->upY, camera->upZ);                       // Up
01500 
01501         break;
01502     }
01503     }
01504 }
01505 
01530 void mhDrawMeshes(int pickMode, int cameraType)
01531 {
01532     PyObject *iterator;
01533     Object3D *obj;
01534 
01535     if (!G.world)
01536     {
01537         return;
01538     }
01539 
01540     /*Draw all objects contained by G.world*/
01541     iterator = PyObject_GetIter(G.world);
01542 
01543     for (obj = (Object3D*)PyIter_Next(iterator); obj; obj = (Object3D*)PyIter_Next(iterator))
01544     {
01545         if (!PyObject_TypeCheck(obj, &Object3DType))
01546             continue;
01547 
01548         if (obj->inMovableCamera == cameraType)
01549         {
01550             if (obj->isVisible && (!pickMode || obj->isPickable))
01551             {
01552                 /*Transform the current object*/
01553                 glPushMatrix();
01554                 glTranslatef(obj->x, obj->y, obj->z);
01555                 glRotatef(obj->rx, 1, 0, 0);
01556                 glRotatef(obj->ry, 0, 1, 0);
01557                 glRotatef(obj->rz, 0, 0, 1);
01558                 glScalef(obj->sx, obj->sy, obj->sz);
01559 
01560                 if (obj->texture && !pickMode && obj->isSolid)
01561                 {
01562                     glEnable(GL_TEXTURE_2D);
01563                     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
01564                     glBindTexture(GL_TEXTURE_2D, obj->texture);
01565                     glTexCoordPointer(2, GL_FLOAT, 0, obj->UVs);
01566                 }
01567 
01568                 /*Fill the array pointers with object mesh data*/
01569                 glVertexPointer(3, GL_FLOAT, 0, obj->verts);
01570                 glNormalPointer(GL_FLOAT, 0, obj->norms);
01571 
01572                 /*Because the selection is based on color, the color array can have 2 values*/
01573                 if (pickMode)
01574                 {
01575                     /*Use color to pick i */
01576                     glColorPointer(3, GL_UNSIGNED_BYTE, 0, obj->colors);
01577                 }
01578                 else
01579                 {
01580                     /*Use color to draw i */
01581                     glColorPointer(4, GL_UNSIGNED_BYTE, 0, obj->colors2);
01582                 }
01583 
01584                 /*Disable lighting if the object is shadeless*/
01585                 if (obj->shadeless || pickMode)
01586                 {
01587                     glDisable(GL_LIGHTING);
01588                 }
01589 
01590                 // Enable the shader if the driver supports it and there is a shader assigned
01591                 if (!pickMode && obj->shader && obj->isSolid)
01592                 {
01593                   if (GLEW_VERSION_2_0)
01594                   {
01595                   
01596                     glUseProgram(obj->shader);
01597 
01598                     // This should be optimized, since we only need to do it when it's changed
01599                     // Validation should also only be done when it is set
01600                     if (obj->shaderParameters)
01601                     {
01602                         GLint parameterCount = 0;
01603                         int index;
01604                         int currentTextureSampler = 1;
01605 
01606                         glGetProgramiv(obj->shader, GL_ACTIVE_UNIFORMS, &parameterCount);
01607 
01608                         for (index = 0; index < parameterCount; index++)
01609                         {
01610                             GLsizei length;
01611                             GLint size;
01612                             GLenum type;
01613                             GLchar name[32];
01614                             PyObject *value;
01615 
01616                             glGetActiveUniform(obj->shader, index, sizeof(name), &length, &size, &type, name);
01617 
01618                             value = PyDict_GetItemString(obj->shaderParameters, name);
01619 
01620                             if (value)
01621                             {
01622                                 switch (type)
01623                                 {
01624                                 case GL_FLOAT:
01625                                 {
01626                                     glUniform1f(index, PyFloat_AsDouble(value));
01627                                     break;
01628                                 }
01629                                 case GL_FLOAT_VEC2:
01630                                 {
01631                                     if (!PyList_Check(value) || PyList_Size(value) != 2)
01632                                         break;
01633                                     glUniform2f(index, PyFloat_AsDouble(PyList_GetItem(value, 0)), PyFloat_AsDouble(PyList_GetItem(value, 1)));
01634                                     break;
01635                                 }
01636                                 case GL_FLOAT_VEC3:
01637                                 {
01638                                     if (!PyList_Check(value) || PyList_Size(value) != 3)
01639                                         break;
01640                                     glUniform3f(index, PyFloat_AsDouble(PyList_GetItem(value, 0)), PyFloat_AsDouble(PyList_GetItem(value, 1)),
01641                                                 PyFloat_AsDouble(PyList_GetItem(value, 2)));
01642                                     break;
01643                                 }
01644                                 case GL_FLOAT_VEC4:
01645                                 {
01646                                     if (!PyList_Check(value) || PyList_Size(value) != 4)
01647                                         break;
01648                                     glUniform4f(index, PyFloat_AsDouble(PyList_GetItem(value, 0)), PyFloat_AsDouble(PyList_GetItem(value, 1)),
01649                                                 PyFloat_AsDouble(PyList_GetItem(value, 2)), PyFloat_AsDouble(PyList_GetItem(value, 3)));
01650                                     break;
01651                                 }
01652                                 case GL_SAMPLER_1D:
01653                                 {
01654                                     glActiveTexture(GL_TEXTURE0 + currentTextureSampler);
01655                                     glBindTexture(GL_TEXTURE_1D, PyInt_AsLong(value));
01656                                     glUniform1i(index, currentTextureSampler++);
01657                                     break;
01658                                 }
01659                                 case GL_SAMPLER_2D:
01660                                 {
01661                                     glActiveTexture(GL_TEXTURE0 + currentTextureSampler);
01662                                     glBindTexture(GL_TEXTURE_2D, PyInt_AsLong(value));
01663                                     glUniform1i(index, currentTextureSampler++);
01664                                     break;
01665                                 }
01666                                 }
01667                             }
01668                         }
01669                     }
01670                   }
01671                   else if (GLEW_ARB_shader_objects)
01672                   {
01673                     glUseProgramObjectARB(obj->shader);
01674 
01675                     // This should be optimized, since we only need to do it when it's changed
01676                     // Validation should also only be done when it is set
01677                     if (obj->shaderParameters)
01678                     {
01679                       GLint parameterCount = 0;
01680                       int index;
01681                       int currentTextureSampler = 1;
01682 
01683                       glGetObjectParameterivARB(obj->shader, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &parameterCount);
01684 
01685                       for (index = 0; index < parameterCount; index++)
01686                       {
01687                         GLsizei length;
01688                         GLint size;
01689                         GLenum type;
01690                         GLchar name[32];
01691                         PyObject *value;
01692 
01693                         glGetActiveUniformARB(obj->shader, index, sizeof(name), &length, &size, &type, name);
01694 
01695                         value = PyDict_GetItemString(obj->shaderParameters, name);
01696 
01697                         if (value)
01698                         {
01699                           switch (type)
01700                           {
01701                           case GL_FLOAT:
01702                             {
01703                               glUniform1fARB(index, PyFloat_AsDouble(value));
01704                               break;
01705                             }
01706                           case GL_FLOAT_VEC2:
01707                             {
01708                               if (!PyList_Check(value) || PyList_Size(value) != 2)
01709                                 break;
01710                               glUniform2fARB(index, PyFloat_AsDouble(PyList_GetItem(value, 0)), PyFloat_AsDouble(PyList_GetItem(value, 1)));
01711                               break;
01712                             }
01713                           case GL_FLOAT_VEC3:
01714                             {
01715                               if (!PyList_Check(value) || PyList_Size(value) != 3)
01716                                 break;
01717                               glUniform3fARB(index, PyFloat_AsDouble(PyList_GetItem(value, 0)), PyFloat_AsDouble(PyList_GetItem(value, 1)),
01718                                 PyFloat_AsDouble(PyList_GetItem(value, 2)));
01719                               break;
01720                             }
01721                           case GL_FLOAT_VEC4:
01722                             {
01723                               if (!PyList_Check(value) || PyList_Size(value) != 4)
01724                                 break;
01725                               glUniform4fARB(index, PyFloat_AsDouble(PyList_GetItem(value, 0)), PyFloat_AsDouble(PyList_GetItem(value, 1)),
01726                                 PyFloat_AsDouble(PyList_GetItem(value, 2)), PyFloat_AsDouble(PyList_GetItem(value, 3)));
01727                               break;
01728                             }
01729                           case GL_SAMPLER_1D:
01730                             {
01731                               glActiveTexture(GL_TEXTURE0 + currentTextureSampler);
01732                               glBindTexture(GL_TEXTURE_1D, PyInt_AsLong(value));
01733                               glUniform1iARB(index, currentTextureSampler++);
01734                               break;
01735                             }
01736                           case GL_SAMPLER_2D:
01737                             {
01738                               glActiveTexture(GL_TEXTURE0 + currentTextureSampler);
01739                               glBindTexture(GL_TEXTURE_2D, PyInt_AsLong(value));
01740                               glUniform1iARB(index, currentTextureSampler++);
01741                               break;
01742                             }
01743                           }
01744                         }
01745                       }
01746                     }
01747                   }
01748                 }
01749 
01750                 /*draw the mesh*/
01751                 if (!obj->isSolid && !pickMode)
01752                 {
01753                   glDisableClientState(GL_COLOR_ARRAY);
01754                   glColor3f(0.0f, 0.0f, 0.0f);
01755                   glPolygonMode(GL_FRONT_AND_BACK , GL_LINE);
01756                   glDrawElements(GL_QUADS, obj->nQuads * 4, GL_UNSIGNED_INT, obj->quads);
01757                   glEnableClientState(GL_COLOR_ARRAY);
01758                   glPolygonMode(GL_FRONT_AND_BACK , GL_FILL);
01759                   glEnable(GL_POLYGON_OFFSET_FILL);
01760                   glPolygonOffset(1.0, 1.0);
01761                   glDrawElements(GL_QUADS, obj->nQuads * 4, GL_UNSIGNED_INT, obj->quads);
01762                   glDisable(GL_POLYGON_OFFSET_FILL);
01763                 }
01764                 else
01765                   glDrawElements(GL_QUADS, obj->nQuads * 4, GL_UNSIGNED_INT, obj->quads);
01766 
01767                 // Disable the shader if the driver supports it and there is a shader assigned
01768                 if (!pickMode && obj->shader && obj->isSolid)
01769                 {
01770                     if (GLEW_VERSION_2_0)
01771                       glUseProgram(0);
01772                     else if (GLEW_ARB_shader_objects)
01773                       glUseProgramObjectARB(0);
01774                     glActiveTexture(GL_TEXTURE0);
01775                 }
01776 
01777                 /*Enable lighting if the object was shadeless*/
01778                 if (obj->shadeless || pickMode)
01779                 {
01780                     glEnable(GL_LIGHTING);
01781                 }
01782 
01783                 if (obj->texture && !pickMode && obj->isSolid)
01784                 {
01785                     glDisable(GL_TEXTURE_2D);
01786                     glDisableClientState(GL_TEXTURE_COORD_ARRAY);
01787                 }
01788 
01789                 glPopMatrix();
01790             }
01791         }
01792 
01793         Py_DECREF((PyObject*)obj);
01794     }
01795 
01796     Py_DECREF(iterator);
01797 }
01798 
01805 void mhDraw(void)
01806 {
01807     int i;
01808     mhDrawBegin();
01809 
01810     for (i = 0; i < PyList_Size(G.cameras); i++)
01811     {
01812         Camera *camera = (Camera*)PyList_GetItem(G.cameras, i);
01813 
01814         // draw the objects in dynamic camera
01815         if (camera->stereoMode)
01816         {
01817             glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE); // Red
01818             mhCameraPosition(camera, 1);
01819             mhDrawMeshes(0, i);
01820             glClear(GL_DEPTH_BUFFER_BIT);
01821             glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE); // Cyan
01822             mhCameraPosition(camera, 2);
01823             mhDrawMeshes(0, i);
01824             // To prevent the GUI from overwritting the red model, we need to render it again in the z-buffer
01825             glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // None, only z-buffer
01826             mhCameraPosition(camera, 1);
01827             mhDrawMeshes(0, i);
01828             glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // All
01829         }
01830         else
01831         {
01832             mhCameraPosition(camera, 0);
01833             mhDrawMeshes(0, i);
01834         }
01835     }
01836 
01837     mhDrawEnd();
01838 }
01839 
01847 void mhShutDown(void)
01848 {
01849     G.loop = 0;
01850 }
01851 
01858 void mhQueueUpdate(void)
01859 {
01860     SDL_Event ev;
01861 
01862     if (G.pendingUpdate)
01863     {
01864         return;
01865     }
01866 
01867     G.pendingUpdate = 1;
01868 
01869     ev.type = SDL_VIDEOEXPOSE;
01870     SDL_PushEvent(&ev);
01871 }
01872 
01881 void mhSetFullscreen(int fullscreen)
01882 {
01883     if (G.fullscreen == fullscreen)
01884     {
01885         return;
01886     }
01887 
01888     G.fullscreen = fullscreen;
01889 
01890     if (fullscreen)
01891     {
01892         G.windowWidth  = g_desktopWidth;
01893         G.windowHeight = g_desktopHeight;
01894     }
01895     else
01896     {
01897         G.windowWidth  = g_windowWidth;
01898         G.windowHeight = g_windowHeight;
01899     }
01900 
01901     if (!g_screen)
01902     {
01903         return;
01904     }
01905 
01906     g_screen = SDL_SetVideoMode(G.windowWidth, G.windowHeight, 24, SDL_OPENGL | (G.fullscreen ? SDL_FULLSCREEN : 0) | SDL_RESIZABLE);
01907     OnInit();
01908     mhReshape(G.windowWidth, G.windowHeight);
01909     callResize(G.windowWidth, G.windowHeight, G.fullscreen);
01910     mhDraw();
01911 }
01912 
01920 void mhCreateWindow(int useTimer)
01921 {
01922     unsigned int colorkey;
01923     SDL_Surface *image;
01924     const SDL_VideoInfo *info;
01925 
01926     atexit(SDL_Quit);
01927 
01928     if (SDL_Init(SDL_INIT_VIDEO) < 0)
01929     {
01930         printf("Unable to init SDL: %s\n", SDL_GetError());
01931         exit(1);
01932     }
01933 
01934     SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
01935     SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
01936     SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
01937     SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
01938     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
01939     SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); // This fixes flickering in compiz
01940     SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
01941     SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
01942 
01943     info = SDL_GetVideoInfo();
01944     g_desktopWidth = info->current_w;
01945     g_desktopHeight = info->current_h;
01946 
01947     // Load and set window icon
01948     image = SDL_LoadBMP("mh_icon.bmp");
01949     if (image)
01950     {
01951         colorkey = SDL_MapRGB(image->format, 255, 255, 255);
01952         SDL_SetColorKey(image, SDL_SRCCOLORKEY, colorkey);
01953         SDL_WM_SetIcon(image, NULL);
01954     }
01955 
01956     if (G.fullscreen)
01957     {
01958         G.windowWidth = g_desktopWidth;
01959         G.windowHeight = g_desktopHeight;
01960     }
01961     else
01962     {
01963         G.windowWidth = g_windowWidth;
01964         G.windowHeight = g_windowHeight;
01965     }
01966 
01967     g_screen = SDL_SetVideoMode(G.windowWidth, G.windowHeight, 24, SDL_OPENGL | (G.fullscreen ? SDL_FULLSCREEN : 0) | SDL_RESIZABLE);
01968     if (g_screen == NULL)
01969     {
01970         printf("No antialiasing available, turning off antialiasing.\n");
01971         SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
01972         SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
01973         g_screen = SDL_SetVideoMode(G.windowWidth, G.windowHeight, 24, SDL_OPENGL | (G.fullscreen ? SDL_FULLSCREEN : 0) | SDL_RESIZABLE);
01974         if (g_screen == NULL)
01975         {
01976             printf("No 24 bit z buffer available, switching to 16 bit.\n");
01977             SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
01978             g_screen = SDL_SetVideoMode(G.windowWidth, G.windowHeight, 24, SDL_OPENGL | (G.fullscreen ? SDL_FULLSCREEN : 0) | SDL_RESIZABLE);
01979             if (g_screen == NULL)
01980             {
01981                 printf("No 16 bit z buffer available, exiting.\n");
01982                 exit(1);
01983             }
01984         }
01985     }
01986 
01987     SDL_WM_SetCaption("MakeHuman", "");
01988     SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
01989 
01990 #ifdef __WIN32__
01991     SDL_EnableUNICODE(1);
01992 
01993 #endif
01994 
01995     if (useTimer == 1)
01996     {
01997         SDL_InitSubSystem(SDL_INIT_TIMER);
01998     }
01999 
02000     OnInit();
02001     mhReshape(G.windowWidth, G.windowHeight);
02002     mhDraw();
02003 }
02004 
02005 
02011 void mhEventLoop(void)
02012 {
02013     //SDL_ShowCursor(SDL_DISABLE);
02014 
02015     while (G.loop)
02016     {
02017         SDL_Event event;
02018 
02019         Py_BEGIN_ALLOW_THREADS
02020         SDL_WaitEvent(&event);
02021         Py_END_ALLOW_THREADS
02022 
02023         /* On OS-X SDL continuously posts events even when a native dialog or
02024          * Window is opened. So if the ActiveWindow (focused Window) is not
02025          * the main window then cancel the SDL Event.
02026          */
02027 #ifdef __APPLE__
02028         extern int isMainWindowActive(); // Defined in SDLMain.mm
02029 
02030         // Consider this event only if the main window is active.
02031         if (!isMainWindowActive())
02032             continue;
02033 #endif /* __APPLE__ */
02034 
02035         switch (event.type)
02036         {
02037         case SDL_ACTIVEEVENT:
02038             if (event.active.state & SDL_APPINPUTFOCUS)
02039             {
02040                 if (event.active.gain)
02041                 {
02042                     //SDL_ShowCursor(SDL_DISABLE);
02043                 }
02044                 else
02045                 {
02046                     //SDL_ShowCursor(SDL_ENABLE);
02047 #ifdef __WIN32__
02048                     SDL_WM_GrabInput(SDL_GRAB_OFF);
02049 #endif
02050                 }
02051             }
02052             break;
02053         case SDL_KEYDOWN:
02054             mhKeyDown(event.key.keysym.sym, event.key.keysym.unicode, event.key.keysym.mod);
02055             break;
02056         case SDL_KEYUP:
02057             if (event.key.keysym.sym == SDLK_F11 || (event.key.keysym.sym == SDLK_RETURN && event.key.keysym.mod & KMOD_ALT))
02058                 mhSetFullscreen(!G.fullscreen); // Switch fullscreen
02059             else
02060                 mhKeyUp(event.key.keysym.sym, event.key.keysym.unicode, event.key.keysym.mod);
02061             break;
02062         case SDL_MOUSEMOTION:
02063         {
02064 #if defined(WIN32) || defined(__APPLE__)
02065             mhMouseMotion(event.motion.state, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
02066 #else
02067             int x, y;
02068             SDL_GetMouseState(&x, &y);
02069             if (x == event.motion.x && y == event.motion.y)
02070                 mhMouseMotion(event.motion.state, event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel);
02071 #endif
02072             break;
02073         }
02074         case SDL_MOUSEBUTTONDOWN:
02075             mhMouseButtonDown(event.button.button, event.button.x, event.button.y);
02076             break;
02077         case SDL_MOUSEBUTTONUP:
02078             mhMouseButtonUp(event.button.button, event.button.x, event.button.y);
02079             break;
02080         case SDL_USEREVENT:
02081             switch (event.user.code)
02082             {
02083             case 0:
02084               if (!PyObject_CallFunction((PyObject*)event.user.data1, ""))
02085                   PyErr_Print();
02086               break;
02087             case 1:
02088               if (!PyObject_CallFunction((PyObject*)event.user.data1, ""))
02089                 PyErr_Print();
02090               Py_DECREF((PyObject*)event.user.data1);
02091               break;
02092             }
02093             break;
02094         case SDL_VIDEORESIZE:
02095             G.windowWidth = g_windowWidth = event.resize.w;
02096             G.windowHeight = g_windowHeight = event.resize.h;
02097             g_screen = SDL_SetVideoMode(G.windowWidth, G.windowHeight, 24, SDL_OPENGL | (G.fullscreen ? SDL_FULLSCREEN : 0) | SDL_RESIZABLE);
02098             OnInit();
02099             mhReshape(event.resize.w, event.resize.h);
02100             callResize(event.resize.w, event.resize.h, G.fullscreen);
02101             mhDraw();
02102             break;
02103         case SDL_VIDEOEXPOSE:
02104             mhDraw();
02105             G.pendingUpdate = 0;
02106             break;
02107         case SDL_QUIT:
02108             mhShutDown();
02109             break;
02110         }
02111     }
02112 
02113     OnExit();
02114 }
 All Data Structures Files Functions Variables Typedefs Defines