41 #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
42 #pragma GCC diagnostic ignored "-Wfloat-equal"
43 #endif //OGRE_PLATFORM_LINUX
49 0xF53E1837, 0x5F14C86B, 0x9EE3964C, 0xFA796D53,
50 0x32223FC3, 0x4D82BC98, 0xA0C7FA62, 0x63E2C982,
51 0x24994A5B, 0x1ECE7BEE, 0x292B38EF, 0xD5CD4E56,
52 0x514F4303, 0x7BE12B83, 0x7192F195, 0x82DC7300,
53 0x084380B4, 0x480B55D3, 0x5F430471, 0x13F75991,
54 0x3F9CF22C, 0x2FE0907A, 0xFD8E1E69, 0x7B1D5DE8,
55 0xD575A85C, 0xAD01C50A, 0x7EE00737, 0x3CE981E8,
56 0x0E447EFA, 0x23089DD6, 0xB59F149F, 0x13600EC7,
57 0xE802C8E6, 0x670921E4, 0x7207EFF0, 0xE74761B0,
58 0x69035234, 0xBFA40F19, 0xF63651A0, 0x29E64C26,
59 0x1F98CCA7, 0xD957007E, 0xE71DDC75, 0x3E729595,
60 0x7580B7CC, 0xD7FAF60B, 0x92484323, 0xA44113EB,
61 0xE4CBDE08, 0x346827C9, 0x3CF32AFA, 0x0B29BCF1,
62 0x6E29F7DF, 0xB01E71CB, 0x3BFBC0D1, 0x62EDC5B8,
63 0xB7DE789A, 0xA4748EC9, 0xE17A4C4F, 0x67E5BD03,
64 0xF3B33D1A, 0x97D8D3E9, 0x09121BC0, 0x347B2D2C,
65 0x79A1913C, 0x504172DE, 0x7F1F8483, 0x13AC3CF6,
66 0x7A2094DB, 0xC778FA12, 0xADF7469F, 0x21786B7B,
67 0x71A445D0, 0xA8896C1B, 0x656F62FB, 0x83A059B3,
68 0x972DFE6E, 0x4122000C, 0x97D9DA19, 0x17D5947B,
69 0xB1AFFD0C, 0x6EF83B97, 0xAF7F780B, 0x4613138A,
70 0x7C3E73A6, 0xCF15E03D, 0x41576322, 0x672DF292,
71 0xB658588D, 0x33EBEFA9, 0x938CBF06, 0x06B67381,
72 0x07F192C6, 0x2BDA5855, 0x348EE0E8, 0x19DBB6E3,
73 0x3222184B, 0xB69D5DBA, 0x7E760B88, 0xAF4D8154,
74 0x007A51AD, 0x35112500, 0xC9CD2D7D, 0x4F4FB761,
75 0x694772E3, 0x694C8351, 0x4A7E3AF5, 0x67D65CE1,
76 0x9287DE92, 0x2518DB3C, 0x8CB4EC06, 0xD154D38F,
77 0xE19A26BB, 0x295EE439, 0xC50A1104, 0x2153C6A7,
78 0x82366656, 0x0713BC2F, 0x6462215A, 0x21D9BFCE,
79 0xBA8EACE6, 0xAE2DF4C1, 0x2A8D5E80, 0x3F7E52D1,
80 0x29359399, 0xFEA1D19C, 0x18879313, 0x455AFA81,
81 0xFADFE838, 0x62609838, 0xD1028839, 0x0736E92F,
82 0x3BCA22A3, 0x1485B08A, 0x2DA7900B, 0x852C156D,
83 0xE8F24803, 0x00078472, 0x13F0D332, 0x2ACFD0CF,
84 0x5F747F5C, 0x87BB1E2F, 0xA7EFCB63, 0x23F432F0,
85 0xE6CE7C5C, 0x1F954EF6, 0xB609C91B, 0x3B4571BF,
86 0xEED17DC0, 0xE556CDA0, 0xA7846A8D, 0xFF105F94,
87 0x52B7CCDE, 0x0E33E801, 0x664455EA, 0xF2C70414,
88 0x73E7B486, 0x8F830661, 0x8B59E826, 0xBB8AEDCA,
89 0xF3D70AB9, 0xD739F2B9, 0x4A04C34A, 0x88D0F089,
90 0xE02191A2, 0xD89D9C78, 0x192C2749, 0xFC43A78F,
91 0x0AAC88CB, 0x9438D42D, 0x9E280F7A, 0x36063802,
92 0x38E8D018, 0x1C42A9CB, 0x92AAFF6C, 0xA24820C5,
93 0x007F077F, 0xCE5BC543, 0x69668D58, 0x10D6FF74,
94 0xBE00F621, 0x21300BBE, 0x2E9E8F46, 0x5ACEA629,
95 0xFA1F86C7, 0x52F206B8, 0x3EDF1A75, 0x6DA8D843,
96 0xCF719928, 0x73E3891F, 0xB4B95DD6, 0xB2A42D27,
97 0xEDA20BBF, 0x1A58DBDF, 0xA449AD03, 0x6DDEF22B,
98 0x900531E6, 0x3D3BFF35, 0x5B24ABA2, 0x472B3E4C,
99 0x387F2D75, 0x4D8DBA36, 0x71CB5641, 0xE3473F3F,
100 0xF6CD4B7F, 0xBF7D1428, 0x344B64D0, 0xC5CDFCB6,
101 0xFE2E0182, 0x2C37A673, 0xDE4EB7A3, 0x63FDC933,
102 0x01DC4063, 0x611F3571, 0xD167BFAF, 0x4496596F,
103 0x3DEE0689, 0xD8704910, 0x7052A114, 0x068C9EC5,
104 0x75D0E766, 0x4D54CC20, 0xB44ECDE2, 0x4ABC653E,
105 0x2C550A21, 0x1A52C0DB, 0xCFED03D0, 0x119BAFE2,
106 0x876A6133, 0xBC232088, 0x435BA1B2, 0xAE99BBFA,
107 0xBB4F08E4, 0xA62B5F49, 0x1DA4B695, 0x336B84DE,
108 0xDC813D31, 0x00C134FB, 0x397A98E6, 0x151F0E64,
109 0xD9EB3E69, 0xD3C7DF60, 0xD2F2C336, 0x2DDD067B,
110 0xBD122835, 0xB0B3BD3A, 0xB0D54E46, 0x8641F1E4,
111 0xA0B38F96, 0x51D39199, 0x37A6AD75, 0xDF84EE41,
112 0x3C034CBA, 0xACDA62FC, 0x11923B8B, 0x45EF170A,
115 using namespace Ogre;
120 , free_eventsource(0)
123 , m_terrain_size(terrn_size)
124 , collision_version(0)
125 , forcecampos(
Ogre::Vector3::ZERO)
155 group = ResourceGroupManager::getSingleton().findGroupContainingResource(filename);
162 Ogre::ConfigFile cfg;
167 cfg.loadDirect(filename);
169 cfg.loadFromResourceSystem(filename, group,
"\x09:=",
true);
171 catch (Ogre::Exception& e)
181 std::map<Ogre::String, ground_model_t>::iterator it;
184 if (!strlen(it->second.basename))
continue;
185 String bname = String(it->second.basename);
192 strncpy(thisgm->
name, it->first.c_str(), 255);
199 ErrorUtils::ShowError(
_L(
"Configuration error"),
_L(
"Your ground configuration is too old, please copy skeleton/config/ground_models.cfg to My Documents/Rigs of Rods/config"));
208 Ogre::ConfigFile::SectionIterator seci = cfg->getSectionIterator();
210 Ogre::String secName, kname, kvalue;
211 while (seci.hasMoreElements())
213 secName = seci.peekNextKey();
214 Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
216 if (!groundModel.empty() && secName != groundModel)
continue;
218 Ogre::ConfigFile::SettingsMultiMap::iterator i;
219 for (i = settings->begin(); i != settings->end(); ++i)
224 if (secName ==
"general" || secName ==
"config")
227 if (kname ==
"version") this->
collision_version = StringConverter::parseInt(kvalue);
252 if (kname ==
"adhesion velocity")
ground_models[secName].va = StringConverter::parseReal(kvalue);
253 else if (kname ==
"static friction coefficient")
ground_models[secName].ms = StringConverter::parseReal(kvalue);
254 else if (kname ==
"sliding friction coefficient")
ground_models[secName].mc = StringConverter::parseReal(kvalue);
255 else if (kname ==
"hydrodynamic friction")
ground_models[secName].t2 = StringConverter::parseReal(kvalue);
256 else if (kname ==
"stribeck velocity")
ground_models[secName].vs = StringConverter::parseReal(kvalue);
257 else if (kname ==
"alpha")
ground_models[secName].alpha = StringConverter::parseReal(kvalue);
258 else if (kname ==
"strength")
ground_models[secName].strength = StringConverter::parseReal(kvalue);
259 else if (kname ==
"base") strncpy(
ground_models[secName].basename, kvalue.c_str(), 255);
260 else if (kname ==
"fx_type")
262 if (kvalue ==
"PARTICLE")
264 else if (kvalue ==
"HARD")
266 else if (kvalue ==
"DUSTY")
268 else if (kvalue ==
"CLUMPY")
271 else if (kname ==
"fx_particle_name") strncpy(
ground_models[secName].particle_name, kvalue.c_str(), 255);
272 else if (kname ==
"fx_colour")
ground_models[secName].fx_colour = StringConverter::parseColourValue(kvalue);
273 else if (kname ==
"fx_particle_amount")
ground_models[secName].fx_particle_amount = StringConverter::parseInt(kvalue);
274 else if (kname ==
"fx_particle_min_velo")
ground_models[secName].fx_particle_min_velo = StringConverter::parseReal(kvalue);
275 else if (kname ==
"fx_particle_max_velo")
ground_models[secName].fx_particle_max_velo = StringConverter::parseReal(kvalue);
276 else if (kname ==
"fx_particle_fade")
ground_models[secName].fx_particle_fade = StringConverter::parseReal(kvalue);
277 else if (kname ==
"fx_particle_timedelta")
ground_models[secName].fx_particle_timedelta = StringConverter::parseReal(kvalue);
278 else if (kname ==
"fx_particle_velo_factor")
ground_models[secName].fx_particle_velo_factor = StringConverter::parseReal(kvalue);
279 else if (kname ==
"fx_particle_ttl")
ground_models[secName].fx_particle_ttl = StringConverter::parseReal(kvalue);
282 else if (kname ==
"fluid density")
ground_models[secName].fluid_density = StringConverter::parseReal(kvalue);
283 else if (kname ==
"flow consistency index")
ground_models[secName].flow_consistency_index = StringConverter::parseReal(kvalue);
284 else if (kname ==
"flow behavior index")
ground_models[secName].flow_behavior_index = StringConverter::parseReal(kvalue);
285 else if (kname ==
"solid ground level")
ground_models[secName].solid_ground_level = StringConverter::parseReal(kvalue);
286 else if (kname ==
"drag anisotropy")
ground_models[secName].drag_anisotropy = StringConverter::parseReal(kvalue);
291 if (!groundModel.empty())
break;
297 Ogre::Real min = pos.x - lo.x;
298 Ogre::Vector3 newPos = Ogre::Vector3(lo.x, pos.y, pos.z);
300 Ogre::Real t = pos.y - lo.y;
303 newPos = Ogre::Vector3(pos.x, lo.y, pos.z);
309 newPos = Ogre::Vector3(pos.x, pos.y, lo.z);
315 newPos = Ogre::Vector3(hi.x, pos.y, pos.z);
321 newPos = Ogre::Vector3(pos.x, hi.y, pos.z);
327 newPos = Ogre::Vector3(pos.x, pos.y, hi.z);
339 LOG(
"RoR was not compiled with PagedGeometry support. You cannot use Landuse maps with it.");
375 unsigned int hash = 0;
376 for (
int i=0; i < 4; i++)
378 hash ^=
sbox[((
unsigned char*)&cellid)[i]];
386 unsigned int cell_id = (cell_x << 16) + cell_z;
387 unsigned int pos =
hashfunc(cell_id);
389 hashtable[pos].emplace_back(cell_id, value);
395 unsigned int cellid = (cell_x << 16) + cell_z;
396 unsigned int pos =
hashfunc(cellid);
398 return static_cast<int>(pos);
401 int Collisions::addCollisionBox(
bool rotating,
bool virt, Vector3 pos, Ogre::Vector3 rot, Ogre::Vector3 l, Ogre::Vector3 h, Ogre::Vector3 sr,
const Ogre::String &eventname,
const Ogre::String &instancename,
const Ogre::String& reverb_preset_name,
bool forcecam, Ogre::Vector3 campos, Ogre::Vector3 sc , Ogre::Vector3 dr ,
CollisionEventFilter event_filter ,
int scripthandler )
403 Quaternion rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z);
404 Quaternion direction = Quaternion(Degree(dr.x), Vector3::UNIT_X) * Quaternion(Degree(dr.y), Vector3::UNIT_Y) * Quaternion(Degree(dr.z), Vector3::UNIT_Z);
411 coll_box.
relo = l*sc;
412 coll_box.
rehi = h*sc;
421 coll_box.
virt = virt;
432 if (!reverb_preset_name.empty())
442 coll_box.
selfrot = Quaternion(Degree(sr.x), Vector3::UNIT_X) * Quaternion(Degree(sr.y), Vector3::UNIT_Y) * Quaternion(Degree(sr.z), Vector3::UNIT_Z);
451 if (!eventname.empty())
466 if (fabs(rot.x) < 0.0001f && fabs(rot.y) < 0.0001f && fabs(rot.z) < 0.0001f)
475 coll_box.
rot = rotation;
476 coll_box.
unrot = rotation.Inverse();
483 coll_box.
debug_verts[0] = Ogre::Vector3(l.x, l.y, l.z) * sc;
484 coll_box.
debug_verts[1] = Ogre::Vector3(h.x, l.y, l.z) * sc;
485 coll_box.
debug_verts[2] = Ogre::Vector3(l.x, h.y, l.z) * sc;
486 coll_box.
debug_verts[3] = Ogre::Vector3(h.x, h.y, l.z) * sc;
487 coll_box.
debug_verts[4] = Ogre::Vector3(l.x, l.y, h.z) * sc;
488 coll_box.
debug_verts[5] = Ogre::Vector3(h.x, l.y, h.z) * sc;
489 coll_box.
debug_verts[6] = Ogre::Vector3(l.x, h.y, h.z) * sc;
490 coll_box.
debug_verts[7] = Ogre::Vector3(h.x, h.y, h.z) * sc;
494 for (
int i=0; i < 8; i++)
502 for (
int i=0; i < 8; i++)
510 for (
int i=1; i < 8; i++)
521 coll_box.
lo = pos + coll_box.
relo;
522 coll_box.
hi = pos + coll_box.
rehi;
523 Vector3 d = (coll_box.
rehi - coll_box.
relo);
535 Vector3 ilo = Ogre::Vector3(coll_box.
lo / Ogre::Real(
CELL_SIZE));
536 Vector3 ihi = Ogre::Vector3(coll_box.
hi / Ogre::Real(
CELL_SIZE));
539 ilo.makeCeil(Ogre::Vector3(0.0f));
541 ihi.makeCeil(Ogre::Vector3(0.0f));
544 for (
int i = ilo.x; i <= ihi.x; i++)
546 for (
int j = ilo.z; j <= ihi.z; j++)
554 return coll_box_index;
570 Vector3 bz=bx.crossProduct(
by);
573 new_tri.
reverse.SetColumn(0, bx);
575 new_tri.
reverse.SetColumn(2, bz);
579 new_tri.
aab.merge(p1);
580 new_tri.
aab.merge(p2);
581 new_tri.
aab.merge(p3);
582 new_tri.
aab.setMinimum(new_tri.
aab.getMinimum() - 0.1f);
583 new_tri.
aab.setMaximum(new_tri.
aab.getMaximum() + 0.1f);
586 Ogre::Vector3 ilo(new_tri.
aab.getMinimum() / Ogre::Real(
CELL_SIZE));
587 Ogre::Vector3 ihi(new_tri.
aab.getMaximum() / Ogre::Real(
CELL_SIZE));
590 ilo.makeCeil(Ogre::Vector3(0.0f));
592 ihi.makeCeil(Ogre::Vector3(0.0f));
595 for (
int i = ilo.x; i <= ihi.x; i++)
597 for (
int j = ilo.z; j<=ihi.z; j++)
605 return new_tri_index;
610 #ifdef USE_ANGELSCRIPT
631 #endif //USE_ANGELSCRIPT
636 int steps = ray.getDirection().length() / (float)
CELL_SIZE;
640 for (
int i = 0; i <= steps; i++)
642 Vector3 pos = ray.getPoint((
float)i / (float)steps);
645 int refx = (int)(pos.x / (
float)
CELL_SIZE);
646 int refz = (int)(pos.z / (
float)
CELL_SIZE);
654 size_t num_elements =
hashtable[hash].size();
655 for (
size_t k = 0; k < num_elements; k++)
665 auto result = Ogre::Math::intersects(ray, ctri->
a, ctri->
b, ctri->
c);
666 if (result.first && result.second < 1.0f)
674 return std::make_pair(
false, 0.0f);
679 const Ogre::Real raydir_length = ray.getDirection().length();
680 const Ogre::Real step_size = Ogre::Real(0.1);
686 ray.setDirection(ray.getDirection().normalisedCopy());
688 for (Ogre::Real distance = Ogre::Real(0); distance <= raydir_length; distance += step_size)
690 Ogre::Vector3 position = ray.getPoint(distance);
693 if (terrain_height > position.y)
695 Ogre::Real distance_in_raydir_units = distance / raydir_length;
697 return std::make_pair(
true, distance_in_raydir_units);
701 return std::make_pair(
false, Ogre::Real(0));
719 Ray ray(origin, -Vector3::UNIT_Y);
721 size_t num_elements =
hashtable[hash].size();
722 for (
size_t k = 0; k < num_elements; k++)
731 if (!cbox->
virt && surface_height < cbox->hi.y)
733 if (
x > cbox->
lo.x &&
z > cbox->
lo.z && x < cbox->hi.x && z < cbox->hi.z)
735 Vector3 pos = origin - cbox->
center;
736 Vector3 dir = -Vector3::UNIT_Y;
739 pos = cbox->
unrot * pos;
740 dir = cbox->
unrot * dir;
749 auto result = Ogre::Math::intersects(Ray(pos, dir), AxisAlignedBox(cbox->
relo, cbox->
rehi));
752 Vector3 hit = pos + dir * result.second;
759 hit = cbox->
rot * hit;
764 surface_height = std::max(surface_height, hit.y);
778 auto lo = ctri->
aab.getMinimum();
779 auto hi = ctri->
aab.getMaximum();
780 if (surface_height >= hi.y)
782 if (
x < lo.x || z < lo.z || x > hi.x ||
z > hi.z)
785 auto result = Ogre::Math::intersects(ray, ctri->
a, ctri->
b, ctri->
c);
788 if (origin.y - result.second < height)
790 surface_height = std::max(surface_height, origin.y - result.second);
796 return surface_height;
802 int refx = (int)(refpos->x / (
float)
CELL_SIZE);
803 int refz = (int)(refpos->z / (
float)
CELL_SIZE);
810 float minctridist = 100.0f;
811 Vector3 minctripoint;
813 bool contacted =
false;
814 bool isScriptCallbackEnvoked =
false;
816 size_t num_elements =
hashtable[hash].size();
817 for (
size_t k = 0; k < num_elements; k++)
825 if (!(*refpos > cbox->
lo && *refpos < cbox->hi))
831 Vector3 Pos = *refpos - cbox->
center;
834 Pos = cbox->
unrot * Pos;
843 if (Pos > cbox->
relo && Pos < cbox->rehi)
848 isScriptCallbackEnvoked =
true;
872 Pos = cbox->
rot * Pos;
874 *refpos = Pos + cbox->
center;
883 isScriptCallbackEnvoked =
true;
905 if (!ctri->
aab.contains(*refpos))
909 Vector3 point = ctri->
forward * (*refpos-ctri->
a);
911 if (point.x >= 0 && point.y >= 0 && (point.x + point.y) <= 1.0 && point.z < 0 && point.z > -0.1)
913 if (-point.z < minctridist)
916 minctridist = -point.z;
917 minctripoint = point;
923 if (envokeScriptCallbacks && !isScriptCallbackEnvoked)
934 *refpos = (minctri->
reverse * minctripoint) + minctri->
a;
965 unsigned int cell_id = (refx << 16) + refz;
971 float minctridist = 100.0;
972 Vector3 minctripoint;
974 bool contacted =
false;
975 bool isScriptCallbackEnvoked =
false;
977 size_t num_elements =
hashtable[hash].size();
978 for (
size_t k=0; k < num_elements; k++)
980 if (
hashtable[hash][k].cell_id != cell_id)
984 else if (
hashtable[hash][k].IsCollisionBox())
999 Pos = cbox->
unrot * Pos;
1008 if (Pos > cbox->
relo && Pos < cbox->rehi)
1021 float t = cbox->
rehi.z - Pos.z;
1022 float min = Pos.z - cbox->
relo.z;
1023 Vector3 normal = Vector3(0, 0, -1);
1024 if (t < min) { min = t; normal = Vector3(0,0,1);};
1025 t = Pos.x - cbox->
relo.x;
1026 if (t < min) { min = t; normal = Vector3(-1,0,0);};
1027 t = cbox->
rehi.x - Pos.x;
1028 if (t < min) { min = t; normal = Vector3(1,0,0);};
1029 t = Pos.y - cbox->
relo.y;
1030 if (t < min) { min = t; normal = Vector3(0,-1,0);};
1031 t = cbox->
rehi.y - Pos.y;
1032 if (t < min) { min = t; normal = Vector3(0,1,0);};
1036 if (cbox->
refined) normal = cbox->
rot * normal;
1057 Vector3 normal = Vector3(0, 0, -1);
1058 if (t < min) {min = t; normal = Vector3(0,0,1);};
1060 if (t < min) {min = t; normal = Vector3(-1,0,0);};
1062 if (t < min) {min = t; normal = Vector3(1,0,0);};
1064 if (t < min) {min = t; normal = Vector3(0,-1,0);};
1066 if (t < min) {min = t; normal = Vector3(0,1,0);};
1070 if (cbox->
refined) normal = cbox->
rot * normal;
1094 if (point.x >= 0 && point.y >= 0 && (point.x + point.y) <= 1.0 && point.z < 0 && point.z > -0.1)
1096 if (-point.z < minctridist)
1099 minctridist = -point.z;
1100 minctripoint = point;
1113 Vector3 normal = minctri->
reverse * Vector3::UNIT_Z;
1128 const int cell_lo_x = (int)(aabb.getMinimum().x / (float)
CELL_SIZE);
1129 const int cell_lo_z = (int)(aabb.getMinimum().z / (float)
CELL_SIZE);
1130 const int cell_hi_x = (int)(aabb.getMaximum().x / (float)
CELL_SIZE);
1131 const int cell_hi_z = (int)(aabb.getMaximum().z / (float)
CELL_SIZE);
1134 for (
int refx = cell_lo_x; refx <= cell_hi_x; refx++)
1136 for (
int refz = cell_lo_z; refz <= cell_hi_z; refz++)
1139 const int hash = this->
hash_find(refx, refz);
1140 const unsigned int cell_id = (refx << 16) + refz;
1143 for (
size_t k = 0; k <
hashtable[hash].size(); k++)
1145 if (
hashtable[hash][k].cell_id != cell_id)
1149 else if (
hashtable[hash][k].IsCollisionBox())
1158 out_boxes.push_back(cbox);
1175 return Vector3::ZERO;
1187 return Quaternion::ZERO;
1206 return isInside(pos, cbox, border);
1211 if (!cbox)
return false;
1213 if (pos + border > cbox->
lo
1214 && pos - border < cbox->hi)
1219 Vector3 rpos = pos - cbox->
center;
1222 rpos = cbox->
unrot * rpos;
1232 if (rpos > cbox->
relo
1233 && rpos < cbox->rehi)
1263 Vector3 force = Vector3::ZERO;
1264 float Vnormal = velocity.dotProduct(normal);
1265 float Fnormal = node->
Forces.dotProduct(normal);
1270 float Vsquared = velocity.squaredLength();
1282 if (Vsquared > gm->
va * gm->
va)
1285 da_factor = Vsquared / (gm->
va * gm->
va);
1286 Fdrag += (Vnormal * m * (1.0f - gm->
drag_anisotropy) * da_factor) * normal;
1296 if (Fnormal < 0 && Fboyancy>-Fnormal)
1298 Fboyancy = -Fnormal;
1301 force += Fboyancy * normal;
1308 float Freaction = -Fnormal;
1313 Freaction -= (0.8f * Vnormal + 0.2f * penetration_depth / dt) * mass / dt;
1317 Vector3 slipf = node->
Forces - Fnormal * normal;
1318 Vector3 slip = velocity - Vnormal * normal;
1319 float slipv = slip.normalise();
1325 float msGreaction = gm->
ms * Greaction;
1326 if (slipv < gm->va && Greaction > 0.0f && slipf.squaredLength() <= msGreaction * msGreaction)
1329 float ff = -msGreaction * (1.0f -
approx_exp(-slipv / gm->
va));
1330 force += Freaction * normal + ff * slip - slipf;
1335 float ff = -(g + std::min(gm->
t2 * slipv, 5.0f)) * Greaction;
1336 force += Freaction * normal + ff * slip;
1349 LOG(
"COLL: Creating collision debug visualization ...");
1358 if (!area_limit.contains(Ogre::Vector3(
x, 0.f,
z)))
1363 const int hash =
hash_find(cellx, cellz);
1366 return c.
cell_id == (cellx << 16) + cellz;
1371 float groundheight = -9999;
1377 groundheight = std::max(groundheight,
App::GetGameContext()->GetTerrain()->getHeightAt(x2,
z));
1378 groundheight = std::max(groundheight,
App::GetGameContext()->GetTerrain()->getHeightAt(
x, z2));
1379 groundheight = std::max(groundheight,
App::GetGameContext()->GetTerrain()->getHeightAt(x2, z2));
1380 groundheight += 0.1;
1383 if (percentd > 1) percentd = 1;
1386 String matName =
"mat-coll-dbg-"+
TOSTRING((
int)(percentd*100));
1390 SceneNode *mo_node = root_node->createChildSceneNode(
"collisionDebugVisualization_node"+cell_name);
1392 mo->begin(matName, Ogre::RenderOperation::OT_TRIANGLE_LIST);
1396 mo->textureCoord(0,0);
1399 mo->textureCoord(1,1);
1402 mo->textureCoord(1,0);
1406 mo->textureCoord(0,1);
1409 mo->textureCoord(1,1);
1412 mo->textureCoord(0,0);
1416 mo->setRenderingDistance(200.f);
1417 mo_node->attachObject(mo);
1421 String labelName =
"label_"+cell_name;
1429 mo_node->attachObject(mt);
1432 mo_node->setVisible(
true);
1435 out_nodes.push_back(mo_node);
1444 ent->setMaterialName(
"tracks/debug/collision/mesh");
1452 size_t vertex_count,index_count;
1456 getMeshInformation(ent->getMesh().get(),vertex_count,vertices,index_count,indices, pos, q, scale);
1460 for (
int i=0; i<(int)index_count/3; i++)
1462 int triID =
addCollisionTri(vertices[indices[i*3]], vertices[indices[i*3+1]], vertices[indices[i*3+2]], gm);
1464 collTris->push_back(triID);
1503 size_t &index_count,
unsigned* &indices,
const Ogre::Vector3 &position,
1504 const Ogre::Quaternion &orient,
const Ogre::Vector3 &scale)
1506 vertex_count = index_count = 0;
1508 bool added_shared =
false;
1509 size_t current_offset = vertex_count;
1510 size_t shared_offset = vertex_count;
1511 size_t next_offset = vertex_count;
1512 size_t index_offset = index_count;
1517 for (
int i = 0;i < mesh->getNumSubMeshes();i++)
1519 SubMesh* submesh = mesh->getSubMesh(i);
1522 if (submesh->useSharedVertices)
1526 VertexData* vertex_data = mesh->sharedVertexData;
1527 vertex_count += vertex_data->vertexCount;
1528 added_shared =
true;
1532 VertexData* vertex_data = submesh->vertexData;
1533 vertex_count += vertex_data->vertexCount;
1537 Ogre::IndexData* index_data = submesh->indexData;
1538 index_count += index_data->indexCount;
1542 vertices =
new Vector3[vertex_count];
1543 indices =
new unsigned[index_count];
1545 added_shared =
false;
1548 for (
int i = 0;i < mesh->getNumSubMeshes();i++)
1550 SubMesh* submesh = mesh->getSubMesh(i);
1552 Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;
1553 if ((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared))
1555 if (submesh->useSharedVertices)
1557 added_shared =
true;
1558 shared_offset = current_offset;
1561 const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
1562 Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());
1563 unsigned char* vertex =
static_cast<unsigned char*
>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
1566 for (
size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
1568 posElem->baseVertexPointerToElement(vertex, &pReal);
1576 pt = (orient * (pt * scale)) + position;
1578 vertices[current_offset + j].x = pt.x;
1579 vertices[current_offset + j].y = pt.y;
1580 vertices[current_offset + j].z = pt.z;
1583 next_offset += vertex_data->vertexCount;
1586 Ogre::IndexData* index_data = submesh->indexData;
1588 size_t numTris = index_data->indexCount / 3;
1589 unsigned short* pShort = 0;
1590 unsigned int* pInt = 0;
1591 Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer;
1593 bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
1595 if (use32bitindexes)
1596 pInt =
static_cast<unsigned int*
>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
1598 pShort =
static_cast<unsigned short*
>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
1600 for (
size_t k = 0; k < numTris; ++k)
1602 size_t offset = (submesh->useSharedVertices)?shared_offset:current_offset;
1604 unsigned int vindex = use32bitindexes? *pInt++ : *pShort++;
1605 indices[index_offset + 0] = vindex + (
unsigned int)offset;
1606 vindex = use32bitindexes? *pInt++ : *pShort++;
1607 indices[index_offset + 1] = vindex + (
unsigned int)offset;
1608 vindex = use32bitindexes? *pInt++ : *pShort++;
1609 indices[index_offset + 2] = vindex + (
unsigned int)offset;
1614 current_offset = next_offset;