48 #include <RTShaderSystem/OgreRTShaderSystem.h>
49 #include <Overlay/OgreFontManager.h>
51 #ifdef USE_ANGELSCRIPT
53 #endif // USE_ANGELSCRIPT
67 TerrainObjectManager::TerrainObjectManager(
Terrain* terrainManager) :
68 terrainManager(terrainManager)
83 for (
auto geom : m_paged_geometry)
85 delete geom->getPageLoader();
97 Ogre::ColourValue background_color(Ogre::ColourValue::White);
98 Ogre::ColourValue grid_color(0.2f, 0.2f, 0.2f, 1.0f);
100 Ogre::ManualObject* mo =
new Ogre::ManualObject(
"ReferenceGrid");
102 mo->begin(
"BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST);
104 const float step = 1.0f;
105 const size_t count = 50;
106 unsigned int halfCount = count / 2;
107 const float half = (step * count) / 2;
110 for (
size_t i=0; i < count+1; i++)
113 c = Ogre::ColourValue(1.f, 0.f, 0.f, 1.f);
117 mo->position(-half,
y, -half+(step*i));
118 mo->colour(background_color);
119 mo->position(0,
y, -half+(step*i));
121 mo->position(0,
y, -half+(step*i));
123 mo->position(half,
y, -half+(step*i));
124 mo->colour(background_color);
127 c = Ogre::ColourValue(0,0,1,1.0f);
131 mo->position(-half+(step*i),
y, -half);
132 mo->colour(background_color);
133 mo->position(-half+(step*i),
y, 0);
135 mo->position(-half+(step*i),
y, 0);
137 mo->position(-half+(step*i),
y, half);
138 mo->colour(background_color);
142 mo->setCastShadows(
false);
144 n->setPosition(position);
155 std::shared_ptr<TObjFile> tobj;
158 DataStreamPtr stream_ptr = ResourceGroupManager::getSingleton().openResource(
165 catch (Ogre::Exception& e)
167 LOG(
"[RoR|Terrain] Error reading TObj file: " + tobj_name +
"\nMessage" + e.getFullDescription());
170 catch (std::exception& e)
172 LOG(
"[RoR|Terrain] Error reading TObj file: " + tobj_name +
"\nMessage" + e.what());
183 if (tobj->grid_enabled)
286 float yawfrom,
float yawto,
287 float scalefrom,
float scaleto,
288 char* ColorMap,
char* DensityMap,
char* treemesh,
char* treeCollmesh,
289 float gridspacing,
float highdens,
290 int minDist,
int maxDist,
int mapsizex,
int mapsizez)
295 LOG(
"tree ColorMap map zero!");
298 if (
strnlen(DensityMap, 3) == 0)
300 LOG(
"tree DensityMap zero!");
303 Forests::DensityMap *densityMap = Forests::DensityMap::load(DensityMap, Forests::CHANNEL_COLOR);
306 LOG(
"could not load densityMap: "+String(DensityMap));
309 densityMap->setFilter(Forests::MAPFILTER_BILINEAR);
312 PagedGeometry* geom =
new PagedGeometry();
315 geom->setPageSize(50);
317 Ogre::TRect<Ogre::Real> bounds = TBounds(0, 0, mapsizex, mapsizez);
318 geom->setBounds(bounds);
325 geom->addDetailLevel<BatchPage>(min, min / 2);
331 if (max / 10 > min / 2)
333 geom->addDetailLevel<ImpostorPage>(max, max / 10);
336 TreeLoader2D *treeLoader =
new TreeLoader2D(geom, TBounds(0, 0, mapsizex, mapsizez));
337 treeLoader->setMinimumScale(scalefrom);
338 treeLoader->setMaximumScale(scaleto);
339 geom->setPageLoader(treeLoader);
341 if (String(ColorMap) !=
"none")
343 treeLoader->setColorMap(ColorMap);
351 for (
float x=0;
x < mapsizex;
x += gridspacing)
353 for (
float z=0;
z < mapsizez;
z += gridspacing)
355 float density = densityMap->_getDensityAt_Unfiltered(
x,
z, bounds);
356 if (density < 0.8f)
continue;
357 float nx =
x + gridspacing * 0.5f;
358 float nz =
z + gridspacing * 0.5f;
359 float yaw = Math::RangeRandom(yawfrom, yawto);
360 float scale = Math::RangeRandom(scalefrom, scaleto);
361 Vector3 pos = Vector3(nx, 0, nz);
362 treeLoader->addTree(curTree, pos, Degree(yaw), (Ogre::Real)scale);
363 if (strlen(treeCollmesh))
375 if (gridspacing < 0 && gridspacing != 0)
377 gridsize = -gridspacing;
381 for (
float x=0;
x < mapsizex;
x += gridsize)
383 for (
float z=0;
z < mapsizez;
z += gridsize)
385 if (highdens < 0) hd = Math::RangeRandom(0, -highdens);
386 float density = densityMap->_getDensityAt_Unfiltered(
x,
z, bounds);
389 while(numTreesToPlace-->0)
391 nx = Math::RangeRandom(
x,
x + gridsize);
392 nz = Math::RangeRandom(
z,
z + gridsize);
393 float yaw = Math::RangeRandom(yawfrom, yawto);
394 float scale = Math::RangeRandom(scalefrom, scaleto);
395 Vector3 pos = Vector3(nx, 0, nz);
396 treeLoader->addTree(curTree, pos, Degree(yaw), (Ogre::Real)scale);
397 if (strlen(treeCollmesh))
406 m_paged_geometry.push_back(geom);
411 float SwaySpeed,
float SwayLength,
float SwayDistribution,
float Density,
412 float minx,
float miny,
float minH,
float maxx,
float maxy,
float maxH,
413 char* grassmat,
char* colorMapFilename,
char* densityMapFilename,
414 int growtechnique,
int techn,
int range,
415 int mapsizex,
int mapsizez)
427 GrassLoader *grassLoader =
new GrassLoader(grass);
428 grass->setPageLoader(grassLoader);
432 grassLoader->setRenderQueueGroup(RENDER_QUEUE_MAIN-1);
434 GrassLayer* grassLayer = grassLoader->addLayer(grassmat);
435 grassLayer->setHeightRange(minH, maxH);
436 grassLayer->setLightingEnabled(
true);
438 grassLayer->setAnimationEnabled((SwaySpeed>0));
439 grassLayer->setSwaySpeed(SwaySpeed);
440 grassLayer->setSwayLength(SwayLength);
441 grassLayer->setSwayDistribution(SwayDistribution);
445 grassLayer->setRenderTechnique(
static_cast<GrassTechnique
>(techn-10),
true);
447 grassLayer->setRenderTechnique(
static_cast<GrassTechnique
>(techn),
false);
449 grassLayer->setMapBounds(TBounds(0, 0, mapsizex, mapsizez));
451 if (strcmp(colorMapFilename,
"none") != 0)
453 grassLayer->setColorMap(colorMapFilename);
454 grassLayer->setColorMapFilter(MAPFILTER_BILINEAR);
457 if (strcmp(densityMapFilename,
"none") != 0)
459 grassLayer->setDensityMap(densityMapFilename);
460 grassLayer->setDensityMapFilter(MAPFILTER_BILINEAR);
463 grassLayer->setMinimumSize(minx, miny);
464 grassLayer->setMaximumSize(maxx, maxy);
467 if (growtechnique == 0)
468 grassLayer->setFadeTechnique(FADETECH_GROW);
469 else if (growtechnique == 1)
470 grassLayer->setFadeTechnique(FADETECH_ALPHAGROW);
471 else if (growtechnique == 2)
472 grassLayer->setFadeTechnique(FADETECH_ALPHA);
474 m_paged_geometry.push_back(grass);
478 LOG(
"error loading grass!");
487 LOG(instancename+
" not found!");
503 LOG(
"unable to unload object: " + instancename);
535 return search_res->second.get();
539 const std::string filename = odef_name +
".odef";
540 std::string group_name;
543 group_name = Ogre::ResourceGroupManager::getSingleton().findGroupContainingResource(filename);
547 LOG(
fmt::format(
"[ODEF] Could not find {} in any resource group", filename));
554 Ogre::DataStreamPtr ds = ResourceGroupManager::getSingleton().openResource(filename, group_name);
558 std::shared_ptr<ODefFile> odef = parser.
Finalize();
566 LOG(
fmt::format(
"[ODEF] An exception occurred when loading or parsing {}", filename));
571 bool TerrainObjectManager::LoadTerrainObject(
const Ogre::String& name,
const Ogre::Vector3& pos,
const Ogre::Vector3& rot,
const Ogre::String& instancename,
const Ogre::String& type,
float rendering_distance ,
bool enable_collisions ,
int scripthandler ,
bool uniquifyMaterial )
576 for (
int x = 0;
x < 500;
x += 50)
578 for (
int z = 0;
z < 500;
z += 50)
580 const String notype =
"";
581 LoadTerrainObject(name, pos + Vector3(
x, 0.0f,
z), rot, name, notype, 0, enable_collisions, scripthandler, uniquifyMaterial);
587 const std::string odefname = name +
".odef";
610 mo->
getEntity()->setRenderingDistance(rendering_distance);
626 tenode->setPosition(pos);
627 Quaternion rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z);
628 tenode->rotate(rotation);
629 tenode->pitch(Degree(-90));
630 tenode->setVisible(
true);
641 object.instance_name = instancename;
643 object.position = pos;
644 object.rotation = rot;
645 object.initial_position = pos;
646 object.initial_rotation = rot;
647 object.node = tenode;
648 object.enable_collisions = enable_collisions;
649 object.script_handler = scripthandler;
652 if (mo && uniquifyMaterial && !instancename.empty())
654 for (
unsigned int i = 0; i < mo->
getEntity()->getNumSubEntities(); i++)
656 SubEntity* se = mo->
getEntity()->getSubEntity(i);
657 String matname = se->getMaterialName();
658 String newmatname = matname +
"/" + instancename;
659 se->getMaterial()->clone(newmatname);
660 se->setMaterialName(newmatname);
667 loc.
position = Vector3(pos.x, pos.y, pos.z);
675 tenode->pitch(Degree(90));
681 for (std::string& snd_name : odef->
sounds)
695 bool race_event = !
object.instance_name.compare(0, 10,
"checkpoint") ||
696 !
object.instance_name.compare(0, 4,
"race");
700 String type =
"checkpoint";
701 auto res = StringUtil::split(
object.instance_name,
"|");
702 if ((res.size() == 4 && res[2] ==
"0") || !
object.instance_name.compare(0, 4,
"race"))
706 int race_id = res.size() > 1 ? StringConverter::parseInt(res[1], -1) : -1;
709 else if (!
object.type.empty())
712 if (
object.type ==
"station" ||
object.type ==
"hotel" ||
object.type ==
"village" ||
713 object.type ==
"observatory" ||
object.type ==
"farm" ||
object.type ==
"ship" ||
object.type ==
"sign")
715 caption =
object.instance_name +
" " +
object.type;
726 LOG(
"[ODEF] Skipping collision mesh with empty name. Object: " + odefname);
733 cmesh.
mesh_name, pos, tenode->getOrientation(),
747 pParticleSys->setCastShadows(
false);
751 #ifdef USE_ANGELSCRIPT
752 unsigned short affCount = pParticleSys->getNumAffectors();
753 ParticleAffector* pAff;
754 for (
unsigned short i = 0; i < affCount; ++i)
756 pAff = pParticleSys->getAffector(i);
757 if (pAff->getType() ==
"ExtinguishableFire")
762 #endif // USE_ANGELSCRIPT
764 SceneNode* sn = tenode->createChildSceneNode();
765 sn->attachObject(pParticleSys);
766 sn->pitch(Degree(90));
779 Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create(odef->
mat_name_generate,
"generatedMaterialShaders");
780 Ogre::RTShader::ShaderGenerator::getSingleton().createShaderBasedTechnique(*mat, Ogre::MaterialManager::DEFAULT_SCHEME_NAME, Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME);
781 Ogre::RTShader::ShaderGenerator::getSingleton().invalidateMaterial(RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME, String(odef->
mat_name_generate));
788 AnimationStateSet *s = mo->
getEntity()->getAllAnimationStates();
789 String anim_name_str(anim.
name);
790 if (!s->hasAnimationState(anim_name_str))
792 LOG(
"[ODEF] animation '" + anim_name_str +
"' for mesh: '" + odef->
header.
mesh_name +
"' in odef file '" + name +
".odef' not found!");
811 LOG(
"[ODEF] animation '" + anim_name_str +
"' for mesh: '" + odef->
header.
mesh_name +
"' in odef file '" + name +
".odef' not found!");
814 ao.
anim->setEnabled(
true);
823 String matName = mo->
getEntity()->getSubEntity(0)->getMaterialName();
824 MaterialPtr m = MaterialManager::getSingleton().getByName(matName);
825 if (m.getPointer() == 0)
827 LOG(
"[ODEF] problem with drawTextOnMeshTexture command: mesh material not found: "+odefname+
" : "+matName);
830 String texName = m->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureName();
831 Texture* background = (Texture *)TextureManager::getSingleton().getByName(texName).getPointer();
834 LOG(
"[ODEF] problem with drawTextOnMeshTexture command: mesh texture not found: "+odefname+
" : "+texName);
838 static int textureNumber = 0;
840 char tmpTextName[256] =
"", tmpMatName[256] =
"";
841 sprintf(tmpTextName,
"TextOnTexture_%d_Texture", textureNumber);
842 sprintf(tmpMatName,
"TextOnTexture_%d_Material", textureNumber);
843 TexturePtr texture = TextureManager::getSingleton().createManual(tmpTextName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, (Ogre::uint)background->getWidth(), (Ogre::uint)background->getHeight(), MIP_UNLIMITED, PF_X8R8G8B8, Ogre::TU_STATIC | Ogre::TU_AUTOMIPMAP);
844 if (texture.getPointer() == 0)
846 LOG(
"[ODEF] problem with drawTextOnMeshTexture command: could not create texture: "+odefname+
" : "+tmpTextName);
853 if (!strncmp(text_buf.
GetBuffer(),
"{{argument1}}", 13))
856 text_buf << instancename;
860 char *text_pointer = text_buf.
GetBuffer();
861 while (*text_pointer!=0) {
if (*text_pointer==
'_') *text_pointer=
' ';text_pointer++;};
863 String font_name_str(tex_print.
font_name);
864 Ogre::Font* font = (Ogre::Font *)FontManager::getSingleton().getByName(font_name_str).getPointer();
867 LOG(
"[ODEF] problem with drawTextOnMeshTexture command: font not found: "+odefname+
" : "+font_name_str);
872 texture->getBuffer()->blit(background->getBuffer());
874 float x = background->getWidth() * tex_print.
x;
875 float y = background->getHeight() * tex_print.
y;
876 float w = background->getWidth() * tex_print.
w;
877 float h = background->getHeight() * tex_print.
h;
879 ColourValue color(tex_print.
r, tex_print.
g, tex_print.
b, tex_print.
a);
880 Ogre::Box box = Ogre::Box((
size_t)
x, (
size_t)
y, (
size_t)(
x+
w), (
size_t)(
y+h));
886 m->clone(tmpMatName);
887 MaterialPtr mNew = MaterialManager::getSingleton().getByName(tmpMatName);
888 mNew->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(tmpTextName);
890 mo->
getEntity()->setMaterialName(String(tmpMatName));
897 spotLight->setType(Light::LT_SPOTLIGHT);
898 spotLight->setPosition(spotl.
pos);
899 spotLight->setDirection(spotl.
dir);
900 spotLight->setAttenuation(spotl.
range, 1.0, 0.3, 0.0);
901 spotLight->setDiffuseColour(spotl.
color);
902 spotLight->setSpecularColour(spotl.
color);
906 lflare->createBillboard(spotl.
pos, spotl.
color);
907 lflare->setMaterialName(
"tracks/flare");
910 float fsize = Math::Clamp(spotl.
range / 10, 0.2f, 2.0f);
911 lflare->setDefaultDimensions(fsize, fsize);
913 SceneNode *sn = tenode->createChildSceneNode();
914 sn->attachObject(spotLight);
915 sn->attachObject(lflare);
922 pointlight->setType(Light::LT_POINT);
923 pointlight->setPosition(plight.
pos);
924 pointlight->setDirection(plight.
dir);
925 pointlight->setAttenuation(plight.
range, 1.0, 0.3, 0.0);
926 pointlight->setDiffuseColour(plight.
color);
927 pointlight->setSpecularColour(plight.
color);
930 lflare->createBillboard(plight.
pos, plight.
color);
931 lflare->setMaterialName(
"tracks/flare");
934 float fsize = Math::Clamp(plight.
range / 10, 0.2f, 2.0f);
935 lflare->setDefaultDimensions(fsize, fsize);
937 SceneNode *sn = tenode->createChildSceneNode();
938 sn->attachObject(pointlight);
939 sn->attachObject(lflare);
961 std::vector<AnimatedObject>::iterator it;
965 if (it->anim && it->speedfactor != 0)
967 Real time = dt * it->speedfactor;
968 it->anim->addTime(time);
1006 for (
auto geom : m_paged_geometry)