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)
252 Ogre::String filename(veh.
name);
255 LOG(std::string(
"[RoR|Terrain] Vehicle ") + veh.
name +
" not found. ignoring.");
292 float yawfrom,
float yawto,
293 float scalefrom,
float scaleto,
294 char* ColorMap,
char* DensityMap,
char* treemesh,
char* treeCollmesh,
295 float gridspacing,
float highdens,
296 int minDist,
int maxDist,
int mapsizex,
int mapsizez)
301 LOG(
"tree ColorMap map zero!");
304 if (
strnlen(DensityMap, 3) == 0)
306 LOG(
"tree DensityMap zero!");
309 Forests::DensityMap *densityMap = Forests::DensityMap::load(DensityMap, Forests::CHANNEL_COLOR);
312 LOG(
"could not load densityMap: "+String(DensityMap));
315 densityMap->setFilter(Forests::MAPFILTER_BILINEAR);
318 PagedGeometry* geom =
new PagedGeometry();
321 geom->setPageSize(50);
323 Ogre::TRect<Ogre::Real> bounds = TBounds(0, 0, mapsizex, mapsizez);
324 geom->setBounds(bounds);
331 geom->addDetailLevel<BatchPage>(min, min / 2);
337 if (max / 10 > min / 2)
339 geom->addDetailLevel<ImpostorPage>(max, max / 10);
342 TreeLoader2D *treeLoader =
new TreeLoader2D(geom, TBounds(0, 0, mapsizex, mapsizez));
343 treeLoader->setMinimumScale(scalefrom);
344 treeLoader->setMaximumScale(scaleto);
345 geom->setPageLoader(treeLoader);
347 if (String(ColorMap) !=
"none")
349 treeLoader->setColorMap(ColorMap);
357 for (
float x=0;
x < mapsizex;
x += gridspacing)
359 for (
float z=0;
z < mapsizez;
z += gridspacing)
361 float density = densityMap->_getDensityAt_Unfiltered(
x,
z, bounds);
362 if (density < 0.8f)
continue;
363 float nx =
x + gridspacing * 0.5f;
364 float nz =
z + gridspacing * 0.5f;
365 float yaw = Math::RangeRandom(yawfrom, yawto);
366 float scale = Math::RangeRandom(scalefrom, scaleto);
367 Vector3 pos = Vector3(nx, 0, nz);
368 treeLoader->addTree(curTree, pos, Degree(yaw), (Ogre::Real)scale);
369 if (strlen(treeCollmesh))
381 if (gridspacing < 0 && gridspacing != 0)
383 gridsize = -gridspacing;
387 for (
float x=0;
x < mapsizex;
x += gridsize)
389 for (
float z=0;
z < mapsizez;
z += gridsize)
391 if (highdens < 0) hd = Math::RangeRandom(0, -highdens);
392 float density = densityMap->_getDensityAt_Unfiltered(
x,
z, bounds);
395 while(numTreesToPlace-->0)
397 nx = Math::RangeRandom(
x,
x + gridsize);
398 nz = Math::RangeRandom(
z,
z + gridsize);
399 float yaw = Math::RangeRandom(yawfrom, yawto);
400 float scale = Math::RangeRandom(scalefrom, scaleto);
401 Vector3 pos = Vector3(nx, 0, nz);
402 treeLoader->addTree(curTree, pos, Degree(yaw), (Ogre::Real)scale);
403 if (strlen(treeCollmesh))
412 m_paged_geometry.push_back(geom);
417 float SwaySpeed,
float SwayLength,
float SwayDistribution,
float Density,
418 float minx,
float miny,
float minH,
float maxx,
float maxy,
float maxH,
419 char* grassmat,
char* colorMapFilename,
char* densityMapFilename,
420 int growtechnique,
int techn,
int range,
421 int mapsizex,
int mapsizez)
433 GrassLoader *grassLoader =
new GrassLoader(grass);
434 grass->setPageLoader(grassLoader);
438 grassLoader->setRenderQueueGroup(RENDER_QUEUE_MAIN-1);
440 GrassLayer* grassLayer = grassLoader->addLayer(grassmat);
441 grassLayer->setHeightRange(minH, maxH);
442 grassLayer->setLightingEnabled(
true);
444 grassLayer->setAnimationEnabled((SwaySpeed>0));
445 grassLayer->setSwaySpeed(SwaySpeed);
446 grassLayer->setSwayLength(SwayLength);
447 grassLayer->setSwayDistribution(SwayDistribution);
451 grassLayer->setRenderTechnique(
static_cast<GrassTechnique
>(techn-10),
true);
453 grassLayer->setRenderTechnique(
static_cast<GrassTechnique
>(techn),
false);
455 grassLayer->setMapBounds(TBounds(0, 0, mapsizex, mapsizez));
457 if (strcmp(colorMapFilename,
"none") != 0)
459 grassLayer->setColorMap(colorMapFilename);
460 grassLayer->setColorMapFilter(MAPFILTER_BILINEAR);
463 if (strcmp(densityMapFilename,
"none") != 0)
465 grassLayer->setDensityMap(densityMapFilename);
466 grassLayer->setDensityMapFilter(MAPFILTER_BILINEAR);
469 grassLayer->setMinimumSize(minx, miny);
470 grassLayer->setMaximumSize(maxx, maxy);
473 if (growtechnique == 0)
474 grassLayer->setFadeTechnique(FADETECH_GROW);
475 else if (growtechnique == 1)
476 grassLayer->setFadeTechnique(FADETECH_ALPHAGROW);
477 else if (growtechnique == 2)
478 grassLayer->setFadeTechnique(FADETECH_ALPHA);
480 m_paged_geometry.push_back(grass);
484 LOG(
"error loading grass!");
493 LOG(instancename+
" not found!");
509 LOG(
"unable to unload object: " + instancename);
541 return search_res->second.get();
545 const std::string filename = odef_name +
".odef";
546 std::string group_name;
549 group_name = Ogre::ResourceGroupManager::getSingleton().findGroupContainingResource(filename);
553 LOG(
fmt::format(
"[ODEF] Could not find {} in any resource group", filename));
560 Ogre::DataStreamPtr ds = ResourceGroupManager::getSingleton().openResource(filename, group_name);
564 std::shared_ptr<ODefFile> odef = parser.
Finalize();
572 LOG(
fmt::format(
"[ODEF] An exception occurred when loading or parsing {}", filename));
577 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 )
582 for (
int x = 0;
x < 500;
x += 50)
584 for (
int z = 0;
z < 500;
z += 50)
586 const String notype =
"";
587 LoadTerrainObject(name, pos + Vector3(
x, 0.0f,
z), rot, name, notype, 0, enable_collisions, scripthandler, uniquifyMaterial);
593 const std::string odefname = name +
".odef";
616 mo->
getEntity()->setRenderingDistance(rendering_distance);
632 tenode->setPosition(pos);
633 Quaternion rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X) * Quaternion(Degree(rot.y), Vector3::UNIT_Y) * Quaternion(Degree(rot.z), Vector3::UNIT_Z);
634 tenode->rotate(rotation);
635 tenode->pitch(Degree(-90));
636 tenode->setVisible(
true);
647 object.instance_name = instancename;
649 object.position = pos;
650 object.rotation = rot;
651 object.initial_position = pos;
652 object.initial_rotation = rot;
653 object.node = tenode;
654 object.enable_collisions = enable_collisions;
655 object.script_handler = scripthandler;
658 if (mo && uniquifyMaterial && !instancename.empty())
660 for (
unsigned int i = 0; i < mo->
getEntity()->getNumSubEntities(); i++)
662 SubEntity* se = mo->
getEntity()->getSubEntity(i);
663 String matname = se->getMaterialName();
664 String newmatname = matname +
"/" + instancename;
665 se->getMaterial()->clone(newmatname);
666 se->setMaterialName(newmatname);
673 loc.
position = Vector3(pos.x, pos.y, pos.z);
681 tenode->pitch(Degree(90));
687 for (std::string& snd_name : odef->
sounds)
701 bool race_event = !
object.instance_name.compare(0, 10,
"checkpoint") ||
702 !
object.instance_name.compare(0, 4,
"race");
706 String type =
"checkpoint";
707 auto res = StringUtil::split(
object.instance_name,
"|");
708 if ((res.size() == 4 && res[2] ==
"0") || !
object.instance_name.compare(0, 4,
"race"))
712 int race_id = res.size() > 1 ? StringConverter::parseInt(res[1], -1) : -1;
715 else if (!
object.type.empty())
718 if (
object.type ==
"station" ||
object.type ==
"hotel" ||
object.type ==
"village" ||
719 object.type ==
"observatory" ||
object.type ==
"farm" ||
object.type ==
"ship" ||
object.type ==
"sign")
721 caption =
object.instance_name +
" " +
object.type;
732 LOG(
"[ODEF] Skipping collision mesh with empty name. Object: " + odefname);
739 cmesh.
mesh_name, pos, tenode->getOrientation(),
753 pParticleSys->setCastShadows(
false);
757 #ifdef USE_ANGELSCRIPT
758 unsigned short affCount = pParticleSys->getNumAffectors();
759 ParticleAffector* pAff;
760 for (
unsigned short i = 0; i < affCount; ++i)
762 pAff = pParticleSys->getAffector(i);
763 if (pAff->getType() ==
"ExtinguishableFire")
768 #endif // USE_ANGELSCRIPT
770 SceneNode* sn = tenode->createChildSceneNode();
771 sn->attachObject(pParticleSys);
772 sn->pitch(Degree(90));
785 Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create(odef->
mat_name_generate,
"generatedMaterialShaders");
786 Ogre::RTShader::ShaderGenerator::getSingleton().createShaderBasedTechnique(*mat, Ogre::MaterialManager::DEFAULT_SCHEME_NAME, Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME);
787 Ogre::RTShader::ShaderGenerator::getSingleton().invalidateMaterial(RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME, String(odef->
mat_name_generate));
794 AnimationStateSet *s = mo->
getEntity()->getAllAnimationStates();
795 String anim_name_str(anim.
name);
796 if (!s->hasAnimationState(anim_name_str))
798 LOG(
"[ODEF] animation '" + anim_name_str +
"' for mesh: '" + odef->
header.
mesh_name +
"' in odef file '" + name +
".odef' not found!");
817 LOG(
"[ODEF] animation '" + anim_name_str +
"' for mesh: '" + odef->
header.
mesh_name +
"' in odef file '" + name +
".odef' not found!");
820 ao.
anim->setEnabled(
true);
829 String matName = mo->
getEntity()->getSubEntity(0)->getMaterialName();
830 MaterialPtr m = MaterialManager::getSingleton().getByName(matName);
831 if (m.getPointer() == 0)
833 LOG(
"[ODEF] problem with drawTextOnMeshTexture command: mesh material not found: "+odefname+
" : "+matName);
836 String texName = m->getTechnique(0)->getPass(0)->getTextureUnitState(0)->getTextureName();
837 Texture* background = (Texture *)TextureManager::getSingleton().getByName(texName).getPointer();
840 LOG(
"[ODEF] problem with drawTextOnMeshTexture command: mesh texture not found: "+odefname+
" : "+texName);
844 static int textureNumber = 0;
846 char tmpTextName[256] =
"", tmpMatName[256] =
"";
847 sprintf(tmpTextName,
"TextOnTexture_%d_Texture", textureNumber);
848 sprintf(tmpMatName,
"TextOnTexture_%d_Material", textureNumber);
849 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);
850 if (texture.getPointer() == 0)
852 LOG(
"[ODEF] problem with drawTextOnMeshTexture command: could not create texture: "+odefname+
" : "+tmpTextName);
859 if (!strncmp(text_buf.
GetBuffer(),
"{{argument1}}", 13))
862 text_buf << instancename;
866 char *text_pointer = text_buf.
GetBuffer();
867 while (*text_pointer!=0) {
if (*text_pointer==
'_') *text_pointer=
' ';text_pointer++;};
869 String font_name_str(tex_print.
font_name);
870 Ogre::Font* font = (Ogre::Font *)FontManager::getSingleton().getByName(font_name_str).getPointer();
873 LOG(
"[ODEF] problem with drawTextOnMeshTexture command: font not found: "+odefname+
" : "+font_name_str);
878 texture->getBuffer()->blit(background->getBuffer());
880 float x = background->getWidth() * tex_print.
x;
881 float y = background->getHeight() * tex_print.
y;
882 float w = background->getWidth() * tex_print.
w;
883 float h = background->getHeight() * tex_print.
h;
885 ColourValue color(tex_print.
r, tex_print.
g, tex_print.
b, tex_print.
a);
886 Ogre::Box box = Ogre::Box((
size_t)
x, (
size_t)
y, (
size_t)(
x+
w), (
size_t)(
y+h));
892 m->clone(tmpMatName);
893 MaterialPtr mNew = MaterialManager::getSingleton().getByName(tmpMatName);
894 mNew->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(tmpTextName);
896 mo->
getEntity()->setMaterialName(String(tmpMatName));
903 spotLight->setType(Light::LT_SPOTLIGHT);
904 spotLight->setPosition(spotl.
pos);
905 spotLight->setDirection(spotl.
dir);
906 spotLight->setAttenuation(spotl.
range, 1.0, 0.3, 0.0);
907 spotLight->setDiffuseColour(spotl.
color);
908 spotLight->setSpecularColour(spotl.
color);
912 lflare->createBillboard(spotl.
pos, spotl.
color);
913 lflare->setMaterialName(
"tracks/flare");
916 float fsize = Math::Clamp(spotl.
range / 10, 0.2f, 2.0f);
917 lflare->setDefaultDimensions(fsize, fsize);
919 SceneNode *sn = tenode->createChildSceneNode();
920 sn->attachObject(spotLight);
921 sn->attachObject(lflare);
928 pointlight->setType(Light::LT_POINT);
929 pointlight->setPosition(plight.
pos);
930 pointlight->setDirection(plight.
dir);
931 pointlight->setAttenuation(plight.
range, 1.0, 0.3, 0.0);
932 pointlight->setDiffuseColour(plight.
color);
933 pointlight->setSpecularColour(plight.
color);
936 lflare->createBillboard(plight.
pos, plight.
color);
937 lflare->setMaterialName(
"tracks/flare");
940 float fsize = Math::Clamp(plight.
range / 10, 0.2f, 2.0f);
941 lflare->setDefaultDimensions(fsize, fsize);
943 SceneNode *sn = tenode->createChildSceneNode();
944 sn->attachObject(pointlight);
945 sn->attachObject(lflare);
967 std::vector<AnimatedObject>::iterator it;
971 if (it->anim && it->speedfactor != 0)
973 Real time = dt * it->speedfactor;
974 it->anim->addTime(time);
1012 for (
auto geom : m_paged_geometry)