MakeHuman
0.95beta
|
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, ¶meterCount); 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, ¶meterCount); 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 }