--- data/skins/simple/menus/AssignControl Mon Jan 19 23:26:36 1970 +++ data/skins/simple/menus/AssignControl Mon Jan 19 23:26:36 1970 @@ -46,7 +46,7 @@ image = white.png color = 0.172, 0.161, 0.169 alpha = 0.7 -left = 0.2 -right = 0.2 +left = 0.1 +right = 0.1 top = 0.48 height = 0.04 --- data/skins/simple/menus/GuiControls Mon Jan 19 23:26:36 1970 +++ data/skins/simple/menus/GuiControls Mon Jan 19 23:26:36 1970 @@ -82,7 +82,7 @@ onselect = controledit.string:gui_select:0 onmoveleft = widget-01d onmoveright = widget-01c -onmoveup = widget-13b +onmoveup = widget-08b onmovedown = widget-02b onfocus = widget-01b.sat:0.56 onblur = widget-01b.sat:0.0 @@ -101,7 +101,7 @@ onselect = controledit.string:gui_select:1 onmoveleft = widget-01b onmoveright = widget-01d -onmoveup = widget-13b +onmoveup = widget-08b onmovedown = widget-02c onfocus = widget-01c.sat:0.56 onblur = widget-01c.sat:0.0 @@ -120,7 +120,7 @@ onselect = controledit.string:gui_select:2 onmoveleft = widget-01c onmoveright = widget-01b -onmoveup = widget-13b +onmoveup = widget-08b onmovedown = widget-02d onfocus = widget-01d.sat:0.56 onblur = widget-01d.sat:0.0 --- data/skins/simple/menus/InGameMain Mon Jan 19 23:26:36 1970 +++ data/skins/simple/menus/InGameMain Mon Jan 19 23:26:36 1970 @@ -44,10 +44,10 @@ [ widget-01 ] -text = Return to Game +text = Continue fontsize = 0.035 align = left -tip = Leave the menu and unpause the game. +tip = Leave the menu and continue the game. onselect = ReturnToGame onmoveup = widget-05 onmovedown = widget-02 @@ -72,7 +72,7 @@ [ widget-02 ] -text = Restart Game +text = Restart fontsize = 0.035 align = left tip = Restart this game using the same car and track settings. @@ -100,7 +100,7 @@ [ widget-03 ] -text = Leave Game +text = Abort fontsize = 0.035 align = left tip = Leave game and return to the Main menu. --- data/skins/simple/menus/InputDevice Mon Jan 19 23:26:36 1970 +++ data/skins/simple/menus/InputDevice Mon Jan 19 23:26:36 1970 @@ -82,7 +82,7 @@ onselect = joystick.type.prev onmoveleft = joystick.type.prev onmoveright = joystick.type.next -onmoveup = widget-13b +onmoveup = widget-11b onmovedown = widget-02b onfocus = widget-01b.alpha:1 widget-01c.alpha:1 widget-01d.sat:0.56 onblur = widget-01b.alpha:0 widget-01c.alpha:0 widget-01d.sat:0.0 @@ -102,7 +102,7 @@ onselect = joystick.type.next onmoveleft = joystick.type.prev onmoveright = joystick.type.next -onmoveup = widget-13b +onmoveup = widget-11b onmovedown = widget-02b onfocus = widget-01b.alpha:1 widget-01c.alpha:1 widget-01d.sat:0.56 onblur = widget-01b.alpha:0 widget-01c.alpha:0 widget-01d.sat:0.0 --- data/skins/simple/menus/SingleRace Mon Jan 19 23:26:36 1970 +++ data/skins/simple/menus/SingleRace Mon Jan 19 23:26:36 1970 @@ -860,7 +860,7 @@ onmoveleft = game.vehicle_damage.prev onmoveright = game.vehicle_damage.next onmoveup = widget-14b -onmovedown = widget-16 +onmovedown = widget-16b onfocus = widget-15b.alpha:1 widget-15c.alpha:1 widget-15d.sat:0.56 onblur = widget-15b.alpha:0 widget-15c.alpha:0 widget-15d.sat:0.0 focus = false --- src/camera.h Mon Jan 19 23:26:36 1970 +++ src/camera.h Mon Jan 19 23:26:36 1970 @@ -16,7 +16,7 @@ const std::string & GetName() const { return name; } - void SetFOV(float value) { fov = std::max(40.0f, std::min(160.0f, value)); } + void SetFOV(float value) { fov = std::max(0.0f, std::min(120.0f, value)); } float GetFOV() const { return fov; } --- src/carcontrolmap_local.cpp Mon Jan 19 23:26:36 1970 +++ src/carcontrolmap_local.cpp Mon Jan 19 23:26:36 1970 @@ -830,16 +830,6 @@ keycodes["y"] = SDLK_y; keycodes["z"] = SDLK_z; keycodes["DELETE"] = SDLK_DELETE; - keycodes["KP0"] = SDLK_KP_0; - keycodes["KP1"] = SDLK_KP_1; - keycodes["KP2"] = SDLK_KP_2; - keycodes["KP3"] = SDLK_KP_3; - keycodes["KP4"] = SDLK_KP_4; - keycodes["KP5"] = SDLK_KP_5; - keycodes["KP6"] = SDLK_KP_6; - keycodes["KP7"] = SDLK_KP_7; - keycodes["KP8"] = SDLK_KP_8; - keycodes["KP9"] = SDLK_KP_9; keycodes["KP_PERIOD"] = SDLK_KP_PERIOD; keycodes["KP_DIVIDE"] = SDLK_KP_DIVIDE; keycodes["KP_MULTIPLY"] = SDLK_KP_MULTIPLY; @@ -872,20 +862,50 @@ keycodes["F14"] = SDLK_F14; keycodes["F15"] = SDLK_F15; keycodes["MENU"] = SDLK_MENU; - keycodes["APPLICATION"] = SDLK_APPLICATION; - keycodes["NUMLOCK"] = SDLK_NUMLOCKCLEAR; keycodes["CAPSLOCK"] = SDLK_CAPSLOCK; - keycodes["SCROLLLOCK"] = SDLK_SCROLLLOCK; keycodes["RSHIFT"] = SDLK_RSHIFT; keycodes["LSHIFT"] = SDLK_LSHIFT; keycodes["RCTRL"] = SDLK_RCTRL; keycodes["LCTRL"] = SDLK_LCTRL; keycodes["RALT"] = SDLK_RALT; keycodes["LALT"] = SDLK_LALT; +#if SDL_VERSION_ATLEAST(2,0,0) + keycodes["KP0"] = SDLK_KP_0; + keycodes["KP1"] = SDLK_KP_1; + keycodes["KP2"] = SDLK_KP_2; + keycodes["KP3"] = SDLK_KP_3; + keycodes["KP4"] = SDLK_KP_4; + keycodes["KP5"] = SDLK_KP_5; + keycodes["KP6"] = SDLK_KP_6; + keycodes["KP7"] = SDLK_KP_7; + keycodes["KP8"] = SDLK_KP_8; + keycodes["KP9"] = SDLK_KP_9; + keycodes["COMPOSE"] = SDLK_APPLICATION; + keycodes["NUMLOCK"] = SDLK_NUMLOCKCLEAR; + keycodes["SCROLLLOCK"] = SDLK_SCROLLLOCK; keycodes["RMETA"] = SDLK_RGUI; keycodes["LMETA"] = SDLK_LGUI; keycodes["LSUPER"] = SDLK_LGUI; keycodes["RSUPER"] = SDLK_RGUI; +#else + keycodes["KP0"] = SDLK_KP0; + keycodes["KP1"] = SDLK_KP1; + keycodes["KP2"] = SDLK_KP2; + keycodes["KP3"] = SDLK_KP3; + keycodes["KP4"] = SDLK_KP4; + keycodes["KP5"] = SDLK_KP5; + keycodes["KP6"] = SDLK_KP6; + keycodes["KP7"] = SDLK_KP7; + keycodes["KP8"] = SDLK_KP8; + keycodes["KP9"] = SDLK_KP9; + keycodes["COMPOSE"] = SDLK_COMPOSE; + keycodes["NUMLOCK"] = SDLK_NUMLOCK; + keycodes["SCROLLLOCK"] = SDLK_SCROLLOCK; + keycodes["LMETA"] = SDLK_LMETA; + keycodes["RMETA"] = SDLK_RMETA; + keycodes["LSUPER"] = SDLK_LSUPER; + keycodes["RSUPER"] = SDLK_RSUPER; +#endif return keycodes; } --- src/game.cpp Mon Jan 19 23:26:36 1970 +++ src/game.cpp Mon Jan 19 23:26:36 1970 @@ -324,10 +324,6 @@ info_output << "Shutting down..." << std::endl; - // Stop the sound thread. - if (sound.Enabled()) - sound.Pause(true); - LeaveGame(); // Save settings first incase later deinits cause crashes. @@ -499,16 +495,7 @@ } // Connect game actions to gui options - set_car_name.connect(gui.GetOption("game.car").signal_val); - set_car_paint.connect(gui.GetOption("game.car_paint").signal_val); - set_car_color_hue.connect(gui.GetOption("game.car_color_hue").signal_val); - set_car_color_sat.connect(gui.GetOption("game.car_color_sat").signal_val); - set_car_color_val.connect(gui.GetOption("game.car_color_val").signal_val); - set_car_ai_type.connect(gui.GetOption("game.ai_type").signal_val); - set_car_ai_level.connect(gui.GetOption("game.ai_level").signal_val); - set_cars_num.connect(gui.GetOption("game.cars_num").signal_val); - set_track_image.connect(gui.GetOption("game.track").signal_val); - set_control.connect(gui.GetOption("controledit.string").signal_val); + BindActionsToGUI(); // Set options from game settings. std::map optionmap; @@ -531,7 +518,6 @@ if (sound.Init(2048, info_output, error_output)) { sound.SetVolume(settings.GetSoundVolume()); - //sound.Pause(false); content.setSound(sound.GetDeviceInfo()); } else @@ -932,22 +918,18 @@ if (sound.Enabled()) { bool pause_sound = pause || gui.Active(); - sound.Pause(pause_sound); - if (!pause_sound) - { - PROFILER.beginBlock("sound"); - MATHVECTOR pos; - QUATERNION rot; - if (active_camera) - { - pos = active_camera->GetPosition(); - rot = active_camera->GetOrientation(); - } - sound.SetListenerPosition(pos[0], pos[1], pos[2]); - sound.SetListenerRotation(rot[0], rot[1], rot[2], rot[3]); - sound.Update(); - PROFILER.endBlock("sound"); - } + PROFILER.beginBlock("sound"); + MATHVECTOR pos; + QUATERNION rot; + if (active_camera) + { + pos = active_camera->GetPosition(); + rot = active_camera->GetOrientation(); + } + sound.SetListenerPosition(pos[0], pos[1], pos[2]); + sound.SetListenerRotation(rot[0], rot[1], rot[2], rot[3]); + sound.Update(pause_sound); + PROFILER.endBlock("sound"); } //PROFILER.beginBlock("force-feedback"); @@ -1798,9 +1780,12 @@ // get car start position marker for camera setup MATHVECTOR car_pos = track.GetStart(0).first; - // car setup + // clear previous car cars.clear(); + // remove previous car sounds + sound.Update(true); + if (LoadCar( cars_name[car_edit_id], cars_paint[car_edit_id], @@ -1808,14 +1793,13 @@ car_pos, track.GetStart(0).second, true, false)) { - // update car + // set car CAR & car = cars.back(); dynamics.update(timestep); car.Update(timestep); - // process car sound sources - // should they be loaded for garage car in the first place? - sound.Update(); + // add car sounds + sound.Update(true); // use car shape center for camera setup car_pos = car.GetPosition(); @@ -1958,7 +1942,7 @@ } if (numreplays == 0) - replaylist.push_back(std::make_pair("", "None")); + replaylist.push_back(std::make_pair("none", "None")); settings.SetSelectedReplay(replaylist.begin()->first); } @@ -2411,6 +2395,7 @@ track.Clear(); cars.clear(); + sound.Update(true); hud.SetVisible(false); inputgraph.Hide(); trackmap.Unload(); @@ -2419,7 +2404,6 @@ pause = false; race_laps = 0; tire_smoke.Clear(); - sound.Update(); } void GAME::StartPractice() @@ -2473,7 +2457,7 @@ void GAME::StartReplay() { - if (!settings.GetSelectedReplay().empty() && !NewGame(true)) + if (settings.GetSelectedReplay() != "none" && !NewGame(true)) { gui.ActivatePage("ReplayStartError", 0.25, error_output); } @@ -2855,6 +2839,19 @@ EditControl(); } +void GAME::BindActionsToGUI() +{ + set_car_name.connect(gui.GetOption("game.car").signal_val); + set_car_paint.connect(gui.GetOption("game.car_paint").signal_val); + set_car_color_hue.connect(gui.GetOption("game.car_color_hue").signal_val); + set_car_color_sat.connect(gui.GetOption("game.car_color_sat").signal_val); + set_car_color_val.connect(gui.GetOption("game.car_color_val").signal_val); + set_car_ai_type.connect(gui.GetOption("game.ai_type").signal_val); + set_car_ai_level.connect(gui.GetOption("game.ai_level").signal_val); + set_cars_num.connect(gui.GetOption("game.cars_num").signal_val); + set_track_image.connect(gui.GetOption("game.track").signal_val); + set_control.connect(gui.GetOption("controledit.string").signal_val); +} void GAME::RegisterActions() { --- src/game.h Mon Jan 19 23:26:36 1970 +++ src/game.h Mon Jan 19 23:26:36 1970 @@ -201,6 +201,7 @@ void SetTrackImage(const std::string & value); void SetControl(const std::string & value); + void BindActionsToGUI(); void RegisterActions(); void InitActionMap(std::map & actionmap); --- src/sound.cpp Mon Jan 19 23:26:36 1970 +++ src/sound.cpp Mon Jan 19 23:26:36 1970 @@ -30,17 +30,20 @@ } SOUND::SOUND() : + log_error(0), deviceinfo(0, 0, 0, 0), + sound_volume(0), initdone(false), disable(false), - paused(true), sampler_lock(0), source_lock(0), + set_pause(true), max_active_sources(64), sources_num(0), - samplers_num(0) + sources_pause(true), + samplers_num(0), + samplers_pause(true) { - volume_filter.SetFilterOrder0(1.0); sources.reserve(64); samplers.reserve(64); } @@ -115,11 +118,13 @@ } deviceinfo = SOUNDINFO(samples, frequency, channels, bytespersample); - + log_error = &error_output; initdone = true; - SetVolume(1.0); + // enable sound, run callback + SDL_PauseAudio(false); + return true; } @@ -138,46 +143,21 @@ disable = true; } -void SOUND::Pause(bool value) -{ - if (paused != value) - { - SDL_PauseAudio(value); - paused = value; - } -} - -void SOUND::Update() +void SOUND::Update(bool pause) { if (disable) return; + set_pause = pause; + GetSourceChanges(); ProcessSourceStop(); - ProcessSourceRemove(); - ProcessSources(); - SetSamplerChanges(); - - // short circuit if paused(sound thread blocked) - if (paused) - { - GetSamplerChanges(); - - ProcessSamplerAdd(); - - ProcessSamplerRemove(); - - SetSourceChanges(); - - GetSourceChanges(); - - ProcessSourceStop(); + ProcessSourceRemove(); - ProcessSourceRemove(); - } + SetSamplerChanges(); } void SOUND::SetMaxActiveSources(size_t value) @@ -192,18 +172,24 @@ size_t id = item_num; if (id < items.size()) { + // reuse free slot size_t idn = items[id].id; if (idn != id) { - // swap back redirected item + // free slot is redirecting to other item assert(idn < id); + + // swap redirected item back items[id] = items[idn]; + + // use now free slot id = idn; } items[id] = item; } else { + // add item to new slot items.push_back(item); } items[id].id = id; @@ -217,9 +203,14 @@ inline void RemoveItem(size_t id, std::vector & items, size_t & item_num) { assert(id < items.size()); + + // get item true id size_t idn = items[id].id; assert(idn < item_num); + + // pop last item --item_num; + // swap last item with current size_t idl = items[item_num].id; if (idl != item_num) @@ -270,14 +261,13 @@ ns.id = -1; sampler_add.getFirst().push_back(ns); - //std::cout << "Add sound source: " << id << " " << buffer->GetName() << std::endl; + //*log_error << "Add sound source: " << id << " " << buffer->GetName() << std::endl; return id; } void SOUND::RemoveSource(size_t id) { - // notify sound thread, it will notify main thread to remove the source - //std::cout << "To be removed source: " << id << " " << sources[sources[id].id].buffer->GetName() << std::endl; + // notify sound and main thread to remove the source/sampler sampler_remove.getFirst().push_back(id); } @@ -343,14 +333,13 @@ void SOUND::SetVolume(float value) { - volume_filter.SetFilterOrder0(clamp(value, 0.f, 1.f)); + sound_volume = value; } void SOUND::GetSourceChanges() { Lock(source_lock); source_stop.swapFirst(); - source_remove.swapFirst(); Unlock(source_lock); } @@ -368,17 +357,18 @@ void SOUND::ProcessSourceRemove() { - std::vector & sremove = source_remove.getFirst(); + std::vector & sremove = sampler_remove.getFirst(); for (size_t i = 0; i < sremove.size(); ++i) { size_t id = sremove[i]; assert(id < sources.size()); + size_t idn = sources[id].id; assert(idn < sources_num); - //std::cout << "Remove sound source: " << id << " " << sources[idn].buffer->GetName() << std::endl; + //*log_error << "Remove sound source: " << id << " " << sources[idn].buffer->GetName() << std::endl; + RemoveItem(id, sources, sources_num); } - sremove.clear(); } void SOUND::ProcessSources() @@ -436,8 +426,11 @@ } } - supdate[i].gain1 = gain1 * Sampler::denom; - supdate[i].gain2 = gain2 * Sampler::denom; + // fade sound volume + float volume = set_pause ? 0 : sound_volume; + + supdate[i].gain1 = volume * gain1 * Sampler::denom; + supdate[i].gain2 = volume * gain2 * Sampler::denom; supdate[i].pitch = src.pitch * Sampler::denom; } @@ -471,6 +464,7 @@ if (sampler_update.getFirst().size()) sampler_update.swapFirst(); if (sampler_add.getFirst().size()) sampler_add.swapFirst(); if (sampler_remove.getFirst().size()) sampler_remove.swapFirst(); + sources_pause = set_pause; Unlock(sampler_lock); } @@ -478,33 +472,41 @@ { Lock(sampler_lock); sampler_update.swapLast(); - sampler_remove.swapLast(); sampler_add.swapLast(); + sampler_remove.swapLast(); + samplers_fade = samplers_pause != sources_pause; + samplers_pause = sources_pause; Unlock(sampler_lock); } void SOUND::ProcessSamplerUpdate() { std::vector & supdate = sampler_update.getLast(); - if (samplers_num == supdate.size()) + if (supdate.empty()) return; + + assert(samplers_num == supdate.size()); + for (size_t i = 0; i < samplers_num; ++i) { - for (size_t i = 0; i < samplers_num; ++i) - { - samplers[i].gain1 = supdate[i].gain1; - samplers[i].gain2 = supdate[i].gain2; - samplers[i].pitch = supdate[i].pitch; - } + samplers[i].gain1 = supdate[i].gain1; + samplers[i].gain2 = supdate[i].gain2; + samplers[i].pitch = supdate[i].pitch; } supdate.clear(); } void SOUND::ProcessSamplers(unsigned char *stream, int len) { - // set buffers and clear stream + // clear stream + memset(stream, 0, len); + + // pause sampling + if (samplers_pause && !samplers_fade) + return; + + // init sampling buffers int len4 = len / 4; buffer1.resize(len4); buffer2.resize(len4); - memset(stream, 0, len); // run samplers short * sstream = (short*)stream; @@ -519,13 +521,17 @@ { SampleAndAdvanceWithPitch16bit(smp, &buffer1[0], &buffer2[0], len4); - volume_filter.Filter(&buffer1[0], &buffer2[0], len4); - for (int n = 0; n < len4; ++n) { int pos = n * 2; - sstream[pos] = clamp(sstream[pos] + buffer1[n], -32768, 32767); - sstream[pos + 1] = clamp(sstream[pos + 1] + buffer2[n], -32768, 32767); + int val1 = sstream[pos] + buffer1[n]; + int val2 = sstream[pos + 1] + buffer2[n]; + + val1 = clamp(val1, -32768, 32767); + val2 = clamp(val2, -32768, 32767); + + sstream[pos] = val1; + sstream[pos + 1] = val2; } } else @@ -541,17 +547,13 @@ void SOUND::ProcessSamplerRemove() { std::vector & sremove = sampler_remove.getLast(); - if (!sremove.empty()) + for (size_t i = 0; i < sremove.size(); ++i) { - for (size_t i = 0; i < sremove.size(); ++i) - { - size_t id = sremove[i]; - assert(id < samplers.size()); - RemoveItem(id, samplers, samplers_num); - } - source_remove.getLast() = sremove; - sremove.clear(); + size_t id = sremove[i]; + assert(id < samplers.size()); + RemoveItem(id, samplers, samplers_num); } + sremove.clear(); } void SOUND::ProcessSamplerAdd() @@ -589,7 +591,6 @@ { Lock(source_lock); if (source_stop.getLast().size()) source_stop.swapLast(); - if (source_remove.getLast().size()) source_remove.swapLast(); Unlock(source_lock); } @@ -600,12 +601,12 @@ GetSamplerChanges(); + ProcessSamplerAdd(); + ProcessSamplerUpdate(); ProcessSamplers(stream, len); - ProcessSamplerAdd(); - ProcessSamplerRemove(); SetSourceChanges(); @@ -622,9 +623,10 @@ assert(len > 0); assert(sampler.buffer); - // if not playing, fill output buffers with silence, should not happen + // if not playing, fill output buffers with silence if (!sampler.playing) { + // should be dealt with before getting here assert(0); for (int i = 0; i < len; ++i) { --- src/sound.h Mon Jan 19 23:26:36 1970 +++ src/sound.h Mon Jan 19 23:26:36 1970 @@ -33,11 +33,8 @@ // disable sound void Disable(); - // pause sound - void Pause(bool value); - // commit state changes - void Update(); + void Update(bool pause); // active sources limit can be adjusted at runtime void SetMaxActiveSources(size_t value); @@ -69,14 +66,14 @@ void SetVolume(float value); private: + std::ostream * log_error; SOUNDINFO deviceinfo; - SOUNDFILTER volume_filter; MATHVECTOR listener_pos; MATHVECTOR listener_vel; QUATERNION listener_rot; + float sound_volume; bool initdone; bool disable; - bool paused; // state structs struct Source @@ -95,8 +92,8 @@ struct Sampler { - static const int denom = 1 << 15; - static const int max_gain_delta = (denom * 100) / 44100; + static const int denom = 32768; + static const int max_gain_delta = (denom * 173) / 44100; // 256 samples from min to max gain const SOUNDBUFFER * buffer; int samples_per_channel; int sample_pos; @@ -135,21 +132,24 @@ TrippleBuffer sampler_update; TrippleBuffer sampler_add; TrippleBuffer sampler_remove; - TrippleBuffer source_remove; TrippleBuffer source_stop; SDL_mutex * sampler_lock; SDL_mutex * source_lock; + bool set_pause; // sound sources state std::vector sources_active; std::vector sources; size_t max_active_sources; size_t sources_num; + bool sources_pause; // sound thread state std::vector buffer1, buffer2; std::vector samplers; size_t samplers_num; + bool samplers_pause; + bool samplers_fade; // main thread methods void GetSourceChanges(); --- src/texture.cpp Mon Jan 19 23:26:36 1970 +++ src/texture.cpp Mon Jan 19 23:26:36 1970 @@ -179,6 +179,7 @@ else { error << "Error loading texture file: " + path << std::endl; + error << IMG_GetError(); return false; } @@ -303,6 +304,7 @@ else { error << "Error loading texture file: " + path + " (" + cubefiles[i] + ")" << std::endl; + error << IMG_GetError(); return false; } @@ -477,6 +479,7 @@ if (!orig_surface) { error << "Error loading texture file: " << path << std::endl; + error << IMG_GetError(); return false; } } --- src/cardynamics.cpp Mon Jan 19 23:26:36 1970 +++ src/cardynamics.cpp Mon Jan 19 23:26:36 1970 @@ -1791,23 +1791,29 @@ bool CARDYNAMICS::WheelContactCallback( btManifoldPoint& cp, - const btCollisionObject* colObj0, - int partId0, + const btCollisionObjectWrapper* col0, + int part0, int index0, - const btCollisionObject* colObj1, - int partId1, + const btCollisionObjectWrapper* col1, + int part1, int index1) { - // cars are fracture bodies, wheel is a cylinder shape - const btCollisionShape* shape = colObj0->getCollisionShape(); - if ((colObj0->getInternalType() & CO_FRACTURE_TYPE) && +#if (BT_BULLET_VERSION < 281) + const btCollisionObject* obj = col0; + const btCollisionShape* shape = obj->getCollisionShape(); + const btCollisionShape* rootshape = obj->getRootCollisionShape(); +#else + const btCollisionObject* obj = col0->getCollisionObject(); + const btCollisionShape* shape = col0->getCollisionShape(); + const btCollisionShape* rootshape = obj->getCollisionShape(); +#endif + if ((obj->getInternalType() & CO_FRACTURE_TYPE) && (shape->getShapeType() == CYLINDER_SHAPE_PROXYTYPE)) { - // is contact within contact patch? - const btCompoundShape* car = static_cast(colObj0->getRootCollisionShape()); - const btCylinderShapeX* wheel = static_cast(shape); - btVector3 contactPoint = cp.m_localPointA - car->getChildTransform(cp.m_index0).getOrigin(); - if (-direction::up.dot(contactPoint) > 0.5 * wheel->getRadius()) + const btCompoundShape* carshape = static_cast(rootshape); + const btCylinderShapeX* wheelshape = static_cast(shape); + btVector3 contactPoint = cp.m_localPointA - carshape->getChildTransform(cp.m_index0).getOrigin(); + if (-direction::up.dot(contactPoint) > 0.5 * wheelshape->getRadius()) { // break contact (hack) cp.m_normalWorldOnB = btVector3(0, 0, 0); --- src/cardynamics.h Mon Jan 19 23:26:36 1970 +++ src/cardynamics.h Mon Jan 19 23:26:36 1970 @@ -25,6 +25,12 @@ class FractureBody; class PTree; +#if (BT_BULLET_VERSION < 281) +#define btCollisionObjectWrapper btCollisionObject +#else +struct btCollisionObjectWrapper; +#endif + class CARDYNAMICS : public btActionInterface { friend class PERFORMANCE_TESTING; @@ -151,11 +157,11 @@ static bool WheelContactCallback( btManifoldPoint& cp, - const btCollisionObject* colObj0, - int partId0, + const btCollisionObjectWrapper* col0, + int part0, int index0, - const btCollisionObject* colObj1, - int partId1, + const btCollisionObjectWrapper* col1, + int part1, int index1); protected: --- src/dynamicsworld.cpp Mon Jan 19 23:26:36 1970 +++ src/dynamicsworld.cpp Mon Jan 19 23:26:36 1970 @@ -105,7 +105,7 @@ int patch_id = -1; const BEZIER * b = 0; const TRACKSURFACE * s = TRACKSURFACE::None(); - btCollisionObject * c = 0; + const btCollisionObject * c = 0; MyRayResultCallback ray(origin, p, caster); rayTest(origin, p, ray); @@ -221,6 +221,7 @@ void DynamicsWorld::fractureCallback() { +#if (BT_BULLET_VERSION < 281) m_activeConnections.resize(0); int numManifolds = getDispatcher()->getNumManifolds(); @@ -268,4 +269,5 @@ btRigidBody* child = body->updateConnection(con_id); if (child) addRigidBody(child); } +#endif }