static int SimulationThread(void *unused) { dAllocateODEDataForThread(dAllocateFlagCollisionData); if (SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH)) { //SDL_perror("SDL_SetThreadPriority"); } while (!Quit) { if (SDL_LockMutex(Mutex)) { SDL_perror("SDL_LockMutex"); break; } if (SDL_CondWait(Cond, Mutex)) { SDL_perror("SDL_CondWait"); break; } PushEvent(UPDATE); dSpaceCollide(Space, 0, &Near); dWorldStep(World, Step); dJointGroupEmpty(Group); SDL_UnlockMutex(Mutex); } dCleanupODEAllDataForThread(); return 0; }
signed ODE_Unlock() { if (SDL_UnlockMutex(Mutex)) { SDL_perror("SDL_UnlockMutex"); return -1; } return 0; }
static signed LoadCubeFace(int face, const char *path) { SDL_Surface *image = IMG_Load(path); if (!image) { SDL_perror("IMG_Load"); return -1; } signed error = LoadCubeMap(image, face, GL_RGB); SDL_FreeSurface(image); return error; }
static Uint32 SimulationTimer(Uint32 interval, void *unused) { if (SDL_LockMutex(Mutex)) { SDL_perror("SDL_LockMutex"); } else if (SDL_CondSignal(Cond)) { SDL_perror("SDL_CondSignal"); } else { SDL_UnlockMutex(Mutex); } double elapsed = interval; double approx = elapsed / 1000; double error = Step - approx; double step = Step + error; return Uint32(1000*step); }
signed ODE_Init() { Quit = SDL_FALSE; dInitODE2(dInitFlagManualThreadCleanup); dSetMessageHandler(Error); dSetDebugHandler(Error); dSetErrorHandler(Error); World = dWorldCreate(); Space = dHashSpaceCreate(0); Group = dJointGroupCreate(0); Step = 1.0/50.0; lua_getglobal(State, "World"); int table = lua_gettop(State); if (!lua_isnil(State, table)) { lua_pushnil(State); while (lua_next(State, table)) { const char *key = lua_tostring(State, -2); #define tointeger lua_tointeger(State, -1) #define toboolean lua_toboolean(State, -1) #define tonumber lua_tonumber(State, -1) if (!SDL_strcasecmp(key, "FPS")) { Step = 1.0/tonumber; } else if (!SDL_strcasecmp(key, "ERP")) { dWorldSetERP(World, tonumber); } else if (!SDL_strcasecmp(key, "CFM")) { dWorldSetCFM(World, tonumber); } else if (!SDL_strcasecmp(key, "LINEAR_DAMPING")) { dWorldSetLinearDamping(World, tonumber); } else if (!SDL_strcasecmp(key, "LINEAR_DAMPING_THRESHOLD")) { dWorldSetLinearDampingThreshold(World, tonumber); } else if (!SDL_strcasecmp(key, "ANGULAR_DAMPING")) { dWorldSetAngularDamping(World, tonumber); } else if (!SDL_strcasecmp(key, "ANGULAR_DAMPING_THRESHOLD")) { dWorldSetAngularDampingThreshold(World, tonumber); } else if (!SDL_strcasecmp(key, "MAX_ANGULAR_SPEED")) { dWorldSetMaxAngularSpeed(World, tonumber); } else if (!SDL_strcasecmp(key, "CONTACT_MAX_CORRECTING_VELOCITY")) { dWorldSetContactMaxCorrectingVel(World, tonumber); } else if (!SDL_strcasecmp(key, "CONTACT_SURFACE_LAYER")) { dWorldSetContactSurfaceLayer(World, tonumber); } else if (!SDL_strcasecmp(key, "AUTO_DISABLE")) { dWorldSetAutoDisableFlag(World, toboolean); } else if (!SDL_strcasecmp(key, "AUTO_DISABLE_LINEAR_THRESHOLD")) { dWorldSetAutoDisableLinearThreshold(World, tonumber); } else if (!SDL_strcasecmp(key, "AUTO_DISABLE_ANGULAR_THRESHOLD")) { dWorldSetAutoDisableAngularThreshold(World, tonumber); } else if (!SDL_strcasecmp(key, "AUTO_DISABLE_STEPS")) { dWorldSetAutoDisableSteps(World, tointeger); } else if (!SDL_strcasecmp(key, "AUTO_DISABLE_TIME")) { dWorldSetAutoDisableTime(World, tonumber); } else { SDL_Log("World: %s does not match", key); } lua_pop(State, 1); } } lua_pop(State, 1); Cond = SDL_CreateCond(); if (!Cond) { dWorldDestroy(World); dSpaceDestroy(Space); dJointGroupDestroy(Group); SDL_perror("SDL_CreateCond"); return SDL_SetError("cannot create simulation signal"); } Mutex = SDL_CreateMutex(); if (!Mutex) { dWorldDestroy(World); dSpaceDestroy(Space); dJointGroupDestroy(Group); SDL_DestroyCond(Cond); SDL_perror("SDL_CreateMutex"); return SDL_SetError("cannot create simulation mutex"); } Thread = SDL_CreateThread(SimulationThread, "ODE", NULL); if (!Thread) { dWorldDestroy(World); dSpaceDestroy(Space); dJointGroupDestroy(Group); SDL_DestroyCond(Cond); SDL_DestroyMutex(Mutex); SDL_perror("SDL_CreateThread"); return SDL_SetError("cannot create simulation thread"); } TimerID = SDL_AddTimer(Uint32(1000*Step), SimulationTimer, NULL); if (!TimerID) { dWorldDestroy(World); dSpaceDestroy(Space); dJointGroupDestroy(Group); SDL_DestroyCond(Cond); SDL_DestroyMutex(Mutex); SDL_perror("SDL_AddTimer"); return SDL_SetError("cannot create simulation timer"); } return 0; }