Ogre::String GameBuildingSystem::BuildBuildings( Ogre::SceneManager *sceneMan, GameRoadGraphAreaTreeNode *roadRoot ) { Ogre::ManualObject *manObject = NULL; Ogre::String manObjectName = "Buildings"; manObject = sceneMan->createManualObject( manObjectName ); manObject->setDynamic( false ); BuildToArea( roadRoot, manObject ); manObject->setCastShadows( true ); sceneMan->getRootSceneNode()->createChildSceneNode()->attachObject( manObject ); return manObjectName; }
int DecalManager::addTerrainDecal(Ogre::Vector3 position, Ogre::Vector2 size, Ogre::Vector2 numSeg, Ogre::Real rotation, Ogre::String materialname, Ogre::String normalname) { #if 0 Ogre::ManualObject *mo = gEnv->ogreSceneManager->createManualObject(); String oname = mo->getName(); SceneNode *mo_node = terrain_decals_snode->createChildSceneNode(); mo->begin(materialname, Ogre::RenderOperation::OT_TRIANGLE_LIST); AxisAlignedBox *aab=new AxisAlignedBox(); float uTile = 1, vTile = 1; Vector3 normal = Vector3(0,1,0); // UP int offset = 0; float ground_dist = 0.001f; Ogre::Vector3 vX = normal.perpendicular(); Ogre::Vector3 vY = normal.crossProduct(vX); Ogre::Vector3 delta1 = size.x / numSeg.x * vX; Ogre::Vector3 delta2 = size.y / numSeg.y * vY; // build one corner of the square Ogre::Vector3 orig = -0.5*size.x*vX - 0.5*size.y*vY; for (int i1 = 0; i1<=numSeg.x; i1++) for (int i2 = 0; i2<=numSeg.y; i2++) { Vector3 pos = orig+i1*delta1+i2*delta2 + position; pos.y = hfinder->getHeightAt(pos.x, pos.z) + ground_dist; mo->position(pos); aab->merge(pos); mo->textureCoord(i1/(Ogre::Real)numSeg.x*uTile, i2/(Ogre::Real)numSeg.y*vTile); mo->normal(normal); } bool reverse = false; if (delta1.crossProduct(delta2).dotProduct(normal)>0) reverse= true; for (int n1 = 0; n1<numSeg.x; n1++) { for (int n2 = 0; n2<numSeg.y; n2++) { if (reverse) { mo->index(offset+0); mo->index(offset+(numSeg.y+1)); mo->index(offset+1); mo->index(offset+1); mo->index(offset+(numSeg.y+1)); mo->index(offset+(numSeg.y+1)+1); } else { mo->index(offset+0); mo->index(offset+1); mo->index(offset+(numSeg.y+1)); mo->index(offset+1); mo->index(offset+(numSeg.y+1)+1); mo->index(offset+(numSeg.y+1)); } offset++; } offset++; } offset+=numSeg.y+1; mo->end(); mo->setBoundingBox(*aab); // some optimizations mo->setCastShadows(false); mo->setDynamic(false); delete(aab); MeshPtr mesh = mo->convertToMesh(oname+"_mesh"); // build edgelist mesh->buildEdgeList(); // remove the manualobject again, since we dont need it anymore gEnv->ogreSceneManager->destroyManualObject(mo); unsigned short src, dest; if (!mesh->suggestTangentVectorBuildParams(VES_TANGENT, src, dest)) { mesh->buildTangentVectors(VES_TANGENT, src, dest); } Entity *ent = gEnv->ogreSceneManager->createEntity(oname+"_ent", oname+"_mesh"); mo_node->attachObject(ent); mo_node->setVisible(true); //mo_node->showBoundingBox(true); mo_node->setPosition(Vector3::ZERO); //(position.x, 0, position.z)); // RTSS //Ogre::RTShader::ShaderGenerator::getSingleton().createShaderBasedTechnique(materialname, Ogre::MaterialManager::DEFAULT_SCHEME_NAME, Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME); //Ogre::RTShader::ShaderGenerator::getSingleton().invalidateMaterial(RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME, materialname); RTSSgenerateShadersForMaterial(materialname, normalname); #endif return 0; }
int DecalManager::addTerrainSplineDecal(Ogre::SimpleSpline *spline, float width, Ogre::Vector2 numSeg, Ogre::Vector2 uvSeg, Ogre::String materialname, float ground_offset, Ogre::String export_fn, bool debug) { #if 0 Ogre::ManualObject *mo = gEnv->ogreSceneManager->createManualObject(); String oname = mo->getName(); SceneNode *mo_node = terrain_decals_snode->createChildSceneNode(); mo->begin(materialname, Ogre::RenderOperation::OT_TRIANGLE_LIST); AxisAlignedBox *aab=new AxisAlignedBox(); int offset = 0; // how width is the road? float delta_width = width / numSeg.x; float steps_len = 1.0f / numSeg.x; for (int l = 0; l<=numSeg.x; l++) { // get current position on that spline Vector3 pos_cur = spline->interpolate(steps_len * (float)l); Vector3 pos_next = spline->interpolate(steps_len * (float)(l + 1)); Ogre::Vector3 direction = (pos_next - pos_cur); if (l == numSeg.x) { // last segment uses previous position pos_next = spline->interpolate(steps_len * (float)(l - 1)); direction = (pos_cur - pos_next); } for (int w = 0; w<=numSeg.y; w++) { // build vector for the width Vector3 wn = direction.normalisedCopy().crossProduct(Vector3::UNIT_Y); // calculate the offset, spline in the middle Vector3 offset = (-0.5 * wn * width) + (w/numSeg.y) * wn * width; // push everything together Ogre::Vector3 pos = pos_cur + offset; // get ground height there pos.y = hfinder->getHeightAt(pos.x, pos.z) + ground_offset; // add the position to the mesh mo->position(pos); aab->merge(pos); mo->textureCoord(l/(Ogre::Real)numSeg.x*uvSeg.x, w/(Ogre::Real)numSeg.y*uvSeg.y); mo->normal(Vector3::UNIT_Y); } } bool reverse = false; for (int n1 = 0; n1<numSeg.x; n1++) { for (int n2 = 0; n2<numSeg.y; n2++) { if (reverse) { mo->index(offset+0); mo->index(offset+(numSeg.y+1)); mo->index(offset+1); mo->index(offset+1); mo->index(offset+(numSeg.y+1)); mo->index(offset+(numSeg.y+1)+1); } else { mo->index(offset+0); mo->index(offset+1); mo->index(offset+(numSeg.y+1)); mo->index(offset+1); mo->index(offset+(numSeg.y+1)+1); mo->index(offset+(numSeg.y+1)); } offset++; } offset++; } offset+=numSeg.y+1; mo->end(); mo->setBoundingBox(*aab); // some optimizations mo->setCastShadows(false); mo->setDynamic(false); delete(aab); MeshPtr mesh = mo->convertToMesh(oname+"_mesh"); // build edgelist mesh->buildEdgeList(); // remove the manualobject again, since we dont need it anymore gEnv->ogreSceneManager->destroyManualObject(mo); unsigned short src, dest; if (!mesh->suggestTangentVectorBuildParams(VES_TANGENT, src, dest)) { mesh->buildTangentVectors(VES_TANGENT, src, dest); } Entity *ent = gEnv->ogreSceneManager->createEntity(oname+"_ent", oname+"_mesh"); mo_node->attachObject(ent); mo_node->setVisible(true); //mo_node->showBoundingBox(true); mo_node->setPosition(Vector3::ZERO); //(position.x, 0, position.z)); if (!export_fn.empty()) { MeshSerializer *ms = new MeshSerializer(); ms->exportMesh(mesh.get(), export_fn); LOG("spline mesh exported as " + export_fn); delete(ms); } // TBD: RTSS //Ogre::RTShader::ShaderGenerator::getSingleton().createShaderBasedTechnique(materialname, Ogre::MaterialManager::DEFAULT_SCHEME_NAME, Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME); //Ogre::RTShader::ShaderGenerator::getSingleton().invalidateMaterial(RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME, materialname); RTSSgenerateShadersForMaterial(materialname, ""); #endif return 0; }
void Map::generateMeshObstacles(std::string materialName) { Ogre::ManualObject* obstacles = new Ogre::ManualObject("obstacles"); obstacles->estimateIndexCount(m_length * m_width * 8); obstacles->estimateVertexCount(m_length * m_width * 8); obstacles->clear(); obstacles->begin(materialName); Ogre::Vector3 pos = Ogre::Vector3(0, 0, 0); Ogre::Quaternion quat; Ogre::Quaternion quatNext; unsigned long planeNum = 0; m_obstaclePositions.clear(); for (unsigned int i = 0; i < m_length; i++) { quat = m_rotationalSpline.getPoint(i); quatNext = m_rotationalSpline.getPoint(i + 1); for (int x = -100 * (m_width / (double) 2), j = 0; (unsigned) j < m_width; j++, x += 100) { int back = -100; int left = x; int right = x + 100; int up = 100; Ogre::Vector3 nextPos = pos + quat * Ogre::Vector3(0, 0, back); Ogre::Vector3 posMinus50 = pos + quat * Ogre::Vector3(left, 0, 0); Ogre::Vector3 posPlus50 = pos + quat * Ogre::Vector3(right, 0, 0); Ogre::Vector3 nextPosMinus50 = nextPos + quatNext * Ogre::Vector3(left, 0, 0); Ogre::Vector3 nextPosPlus50 = nextPos + quatNext * Ogre::Vector3(right, 0, 0); //TODO: fix normals obstacles->position(posMinus50); obstacles->normal((quat * Vector3(0, 1, 0)).normalisedCopy()); obstacles->textureCoord(1, 1); obstacles->position(nextPosMinus50); obstacles->normal((quat * Vector3(0, 1, 0)).normalisedCopy()); obstacles->textureCoord(1, 0); obstacles->position(posPlus50); obstacles->normal((quat * Vector3(0, 1, 0)).normalisedCopy()); obstacles->textureCoord(0, 1); obstacles->position(nextPosPlus50); obstacles->normal((quat * Vector3(0, 1, 0)).normalisedCopy()); obstacles->textureCoord(0, 0); Ogre::Vector3 nextPosUp = nextPos + quat * Ogre::Vector3(0, up, 0); Ogre::Vector3 posMinus50Up = posMinus50 + quat * Ogre::Vector3(0, up, 0); Ogre::Vector3 posPlus50Up = posPlus50 + quat * Ogre::Vector3(0, up, 0); Ogre::Vector3 nextPosMinus50Up = nextPosMinus50 + quatNext * Ogre::Vector3(0, up, 0); Ogre::Vector3 nextPosPlus50Up = nextPosPlus50 + quatNext * Ogre::Vector3(0, up, 0); //TODO: fix normals obstacles->position(posMinus50Up); obstacles->normal((quat * Vector3(-1, 1, 1)).normalisedCopy()); obstacles->textureCoord(0, 0); obstacles->position(nextPosMinus50Up); obstacles->normal((quat * Vector3(-1, 1, -1)).normalisedCopy()); obstacles->textureCoord(0, 1); obstacles->position(posPlus50Up); obstacles->normal((quat * Vector3(1, 1, 1)).normalisedCopy()); obstacles->textureCoord(1, 0); obstacles->position(nextPosPlus50Up); obstacles->normal((quat * Vector3(1, 1, -1)).normalisedCopy()); obstacles->textureCoord(1, 1); if (m_cubes[planeNum / (double) m_width][planeNum % m_width] == OBSTACLE) { //TODO: check if this hack works.. m_obstaclePositions.push_back(posMinus50); //top obstacles->triangle(4 + planeNum * 8, 5 + planeNum * 8, 6 + planeNum * 8); obstacles->triangle(6 + planeNum * 8, 5 + planeNum * 8, 4 + planeNum * 8); obstacles->triangle(5 + planeNum * 8, 7 + planeNum * 8, 6 + planeNum * 8); obstacles->triangle(6 + planeNum * 8, 7 + planeNum * 8, 5 + planeNum * 8); if (planeNum % m_width == 0 || m_cubes[planeNum / (double) m_width][(planeNum - 1) % m_width] != OBSTACLE) { //left obstacles->triangle(0 + planeNum * 8, 4 + planeNum * 8, 5 + planeNum * 8); obstacles->triangle(5 + planeNum * 8, 4 + planeNum * 8, 0 + planeNum * 8); obstacles->triangle(0 + planeNum * 8, 1 + planeNum * 8, 5 + planeNum * 8); obstacles->triangle(5 + planeNum * 8, 1 + planeNum * 8, 0 + planeNum * 8); } if (planeNum % m_width == m_width - 1 || m_cubes[planeNum / (double) m_width][(planeNum + 1) % m_width] != OBSTACLE) { //right obstacles->triangle(2 + planeNum * 8, 6 + planeNum * 8, 7 + planeNum * 8); obstacles->triangle(7 + planeNum * 8, 6 + planeNum * 8, 2 + planeNum * 8); obstacles->triangle(2 + planeNum * 8, 3 + planeNum * 8, 7 + planeNum * 8); obstacles->triangle(7 + planeNum * 8, 3 + planeNum * 8, 2 + planeNum * 8); } if (planeNum / (double) m_width >= m_length - 1 || m_cubes[(planeNum + m_width) / (double) m_width][planeNum % m_width] != OBSTACLE) { //back obstacles->triangle(5 + planeNum * 8, 7 + planeNum * 8, 1 + planeNum * 8); obstacles->triangle(1 + planeNum * 8, 7 + planeNum * 8, 5 + planeNum * 8); obstacles->triangle(1 + planeNum * 8, 3 + planeNum * 8, 7 + planeNum * 8); obstacles->triangle(7 + planeNum * 8, 3 + planeNum * 8, 1 + planeNum * 8); } if (planeNum / (double) m_width <= m_width || m_cubes[(planeNum - m_width) / (double) m_width][planeNum % m_width] != OBSTACLE) { //front obstacles->triangle(2 + planeNum * 8, 6 + planeNum * 8, 4 + planeNum * 8); obstacles->triangle(4 + planeNum * 8, 6 + planeNum * 8, 2 + planeNum * 8); obstacles->triangle(0 + planeNum * 8, 4 + planeNum * 8, 2 + planeNum * 8); obstacles->triangle(2 + planeNum * 8, 4 + planeNum * 8, 0 + planeNum * 8); } } planeNum++; } pos = pos + quat * Ogre::Vector3(0, 0, -100); } obstacles->end(); obstacles->setCastShadows(true); //TODO: fix graphics bug when no obstacles /*if (m_obstaclePositions.size() <= 0) { return; }*/ m_mapMainNode->attachObject(obstacles); MeshPtr ptr = obstacles->convertToMesh("obstaclesMesh"); Entity* obstaclesEntity = m_pSceneMgr->createEntity("obstaclesEntity", "obstaclesMesh"); }
void Map::generateMesh(std::string materialName) { Ogre::ManualObject* plane = new Ogre::ManualObject("plane"); plane->estimateIndexCount(m_length * m_width * 8); plane->estimateVertexCount(m_length * m_width * 8); plane->clear(); plane->begin(materialName); Ogre::Vector3 pos = Ogre::Vector3(0, 0, 0); Ogre::Quaternion quat; Ogre::Quaternion quatNext; unsigned long planeNum = 0; for (unsigned int i = 0; i < m_length; i++) { quat = m_rotationalSpline.getPoint(i); quatNext = m_rotationalSpline.getPoint(i + 1); for (int x = -100 * (m_width / (double) 2), j = 0; (unsigned) j < m_width; j++, x += 100) { int back = -100; int left = x; int right = x + 100; int down = -20 ; Ogre::Vector3 nextPos = pos + quat * Ogre::Vector3(0, 0, back); Ogre::Vector3 posMinus50 = pos + quat * Ogre::Vector3(left, 0, 0); Ogre::Vector3 posPlus50 = pos + quat * Ogre::Vector3(right, 0, 0); Ogre::Vector3 nextPosMinus50 = nextPos + quatNext * Ogre::Vector3(left, 0, 0); Ogre::Vector3 nextPosPlus50 = nextPos + quatNext * Ogre::Vector3(right, 0, 0); //TODO: fix normals? plane->position(posMinus50); plane->normal((quat * Vector3(0, 1, 0)).normalisedCopy()); plane->textureCoord(1, 1); plane->position(nextPosMinus50); plane->normal((quat * Vector3(0, 1, 0)).normalisedCopy()); plane->textureCoord(1, 0); plane->position(posPlus50); plane->normal((quat * Vector3(0, 1, 0)).normalisedCopy()); plane->textureCoord(0, 1); plane->position(nextPosPlus50); plane->normal((quat * Vector3(0, 1, 0)).normalisedCopy()); plane->textureCoord(0, 0); Ogre::Vector3 nextPosDown = nextPos + quat * Ogre::Vector3(0, down, 0); Ogre::Vector3 posMinus50Down = posMinus50 + quat * Ogre::Vector3(0, down, 0); Ogre::Vector3 posPlus50Down = posPlus50 + quat * Ogre::Vector3(0, down, 0); Ogre::Vector3 nextPosMinus50Down = nextPosMinus50 + quatNext * Ogre::Vector3(0, down, 0); Ogre::Vector3 nextPosPlus50Down = nextPosPlus50 + quatNext * Ogre::Vector3(0, down, 0); //TODO: fix normals? plane->position(posMinus50Down); plane->normal((quat * Vector3(-1, -1, 1)).normalisedCopy()); plane->textureCoord(0, 0); plane->position(nextPosMinus50Down); plane->normal((quat * Vector3(-1, -1, -1)).normalisedCopy()); plane->textureCoord(0, 1); plane->position(posPlus50Down); plane->normal((quat * Vector3(1, -1, 1)).normalisedCopy()); plane->textureCoord(1, 0); plane->position(nextPosPlus50Down); plane->normal((quat * Vector3(1, -1, -1)).normalisedCopy()); plane->textureCoord(1, 1); if (m_cubes[planeNum / (double) m_width][planeNum % m_width] != HOLE) { //if (m_cubes[planeNum / (double) m_width][planeNum % m_width] == NORMAL) //{ //top plane->triangle(0 + planeNum * 8, 1 + planeNum * 8, 2 + planeNum * 8); plane->triangle(2 + planeNum * 8, 1 + planeNum * 8, 0 + planeNum * 8); plane->triangle(1 + planeNum * 8, 3 + planeNum * 8, 2 + planeNum * 8); plane->triangle(2 + planeNum * 8, 3 + planeNum * 8, 1 + planeNum * 8); //} //bottom plane->triangle(4 + planeNum * 8, 5 + planeNum * 8, 6 + planeNum * 8); plane->triangle(6 + planeNum * 8, 5 + planeNum * 8, 4 + planeNum * 8); plane->triangle(5 + planeNum * 8, 7 + planeNum * 8, 6 + planeNum * 8); plane->triangle(6 + planeNum * 8, 7 + planeNum * 8, 5 + planeNum * 8); if (planeNum % m_width == 0 || m_cubes[planeNum / (double) m_width][(planeNum - 1) % m_width] == HOLE) { //left plane->triangle(0 + planeNum * 8, 4 + planeNum * 8, 5 + planeNum * 8); plane->triangle(5 + planeNum * 8, 4 + planeNum * 8, 0 + planeNum * 8); plane->triangle(0 + planeNum * 8, 1 + planeNum * 8, 5 + planeNum * 8); plane->triangle(5 + planeNum * 8, 1 + planeNum * 8, 0 + planeNum * 8); } if (planeNum % m_width == m_width - 1 || m_cubes[planeNum / (double) m_width][(planeNum + 1) % m_width] == HOLE) { //right plane->triangle(2 + planeNum * 8, 6 + planeNum * 8, 7 + planeNum * 8); plane->triangle(7 + planeNum * 8, 6 + planeNum * 8, 2 + planeNum * 8); plane->triangle(2 + planeNum * 8, 3 + planeNum * 8, 7 + planeNum * 8); plane->triangle(7 + planeNum * 8, 3 + planeNum * 8, 2 + planeNum * 8); } if (planeNum / (double) m_width >= m_length - 1 || m_cubes[(planeNum + m_width) / (double) m_width][planeNum % m_width] == HOLE) { //back plane->triangle(5 + planeNum * 8, 7 + planeNum * 8, 1 + planeNum * 8); plane->triangle(1 + planeNum * 8, 7 + planeNum * 8, 5 + planeNum * 8); plane->triangle(1 + planeNum * 8, 3 + planeNum * 8, 7 + planeNum * 8); plane->triangle(7 + planeNum * 8, 3 + planeNum * 8, 1 + planeNum * 8); } if (planeNum / (double) m_width <= m_width || m_cubes[(planeNum - m_width) / (double) m_width][planeNum % m_width] == HOLE) { //front plane->triangle(2 + planeNum * 8, 6 + planeNum * 8, 4 + planeNum * 8); plane->triangle(4 + planeNum * 8, 6 + planeNum * 8, 2 + planeNum * 8); plane->triangle(0 + planeNum * 8, 4 + planeNum * 8, 2 + planeNum * 8); plane->triangle(2 + planeNum * 8, 4 + planeNum * 8, 0 + planeNum * 8); } } planeNum++; } pos = pos + quat * Ogre::Vector3(0, 0, -100); } plane->end(); plane->setCastShadows(false); m_mapMainNode->attachObject(plane); MeshPtr ptr = plane->convertToMesh("planeMesh"); Entity* planeEntity = m_pSceneMgr->createEntity("planeEntity", "planeMesh"); }
// Given a scene node for a terrain, find the manual object on that scene node and // update the manual object with the heightmap passed. If there is no manual object on // the scene node, remove all it's attachments and add the manual object. // The heightmap is passed in a 1D array ordered by width rows (for(width) {for(length) {hm[w,l]}}) // This must be called between frames since it touches the scene graph // BETWEEN FRAME OPERATION void Region::UpdateTerrain(const int hmWidth, const int hmLength, const float* hm) { Ogre::SceneNode* node = this->TerrainSceneNode; LG::Log("Region::UpdateTerrain: updating terrain for region %s", this->Name.c_str()); if (node == NULL) { LG::Log("Region::UpdateTerrain: terrain scene node doesn't exist. Not updating terrain."); return; } // Find the movable object attached to the scene node. If not found remove all. if (node->numAttachedObjects() > 0) { Ogre::MovableObject* attached = node->getAttachedObject(0); if (attached->getMovableType() != "ManualObject") { // don't know why this would ever happen but clean out the odd stuff LG::Log("Found extra stuff on terrain scene node"); node->detachAllObjects(); } } // if there is not a manual object on the node, create a new one if (node->numAttachedObjects() == 0) { LG::Log("Region::UpdateTerrain: creating terrain ManualObject for region %s", this->Name.c_str()); // if no attached objects, we add our dynamic ManualObject Ogre::ManualObject* mob = LG::RendererOgre::Instance()->m_sceneMgr->createManualObject("ManualObject/" + node->getName()); mob->addQueryFlags(Ogre::SceneManager::WORLD_GEOMETRY_TYPE_MASK); mob->setDynamic(true); mob->setCastShadows(true); mob->setVisible(true); node->attachObject(mob); // m_visCalc->RecalculateVisibility(); } Ogre::ManualObject* mo = (Ogre::ManualObject*)node->getAttachedObject(0); // stuff our heightmap information into the dynamic manual object mo->estimateVertexCount(hmWidth * hmLength); mo->estimateIndexCount(hmWidth * hmLength * 6); if (mo->getNumSections() == 0) { // if first time mo->begin(LG::GetParameter("Renderer.Ogre.DefaultTerrainMaterial")); } else { mo->beginUpdate(0); // we've been here before } int loc = 0; for (int xx = 0; xx < hmWidth; xx++) { for (int yy = 0; yy < hmLength; yy++) { mo->position((Ogre::Real)xx, (Ogre::Real)yy, hm[loc++]); mo->textureCoord((float)xx / (float)hmWidth, (float)yy / (float)hmLength); mo->normal(0.0, 1.0, 0.0); // always up (for the moment) } } for (int px = 0; px < hmLength-1; px++) { for (int py = 0; py < hmWidth-1; py++) { mo->quad(px + py * hmWidth, px + (py + 1) * hmWidth, (px + 1) + (py + 1) * hmWidth, (px + 1) + py * hmWidth ); } } mo->end(); return; }
void TerrainObjectManager::loadObjectConfigFile(Ogre::String odefname) { proceduralManager = new ProceduralManager(); objcounter = 0; free_localizer = 0; ProceduralObject po; po.loadingState = -1; int r2oldmode = 0; int lastprogress = -1; bool proroad = false; DataStreamPtr ds; try { ds = ResourceGroupManager::getSingleton().openResource(odefname, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); } catch(...) { LOG("Error opening object configuration: " + odefname); return; } int mapsizex = terrainManager->getGeometryManager()->getMaxTerrainSize().x; int mapsizez = terrainManager->getGeometryManager()->getMaxTerrainSize().z; Vector3 r2lastpos=Vector3::ZERO; Quaternion r2lastrot=Quaternion::IDENTITY; int r2counter=0; //long line = 0; char line[4096] = ""; while (!ds->eof()) { int progress = ((float)(ds->tell()) / (float)(ds->size())) * 100.0f; if (progress-lastprogress > 20) { #ifdef USE_MYGUI LoadingWindow::getSingleton().setProgress(progress, _L("Loading Terrain Objects")); #endif //MYGUI lastprogress = progress; } char oname[1024] = {}; char type[256] = {}; char name[256] = {}; Vector3 pos(Vector3::ZERO); Vector3 rot(Vector3::ZERO); size_t ll = ds->readLine(line, 1023); if (line[0]=='/' || line[0]==';' || ll==0) continue; //comments if (!strcmp("end",line)) break; if (!strncmp(line,"collision-tris", 14)) { long amount = Collisions::MAX_COLLISION_TRIS; sscanf(line, "collision-tris %ld", &amount); gEnv->collisions->resizeMemory(amount); } if (!strncmp(line,"grid", 4)) { sscanf(line, "grid %f, %f, %f", &pos.x, &pos.y, &pos.z); Ogre::ColourValue BackgroundColour = Ogre::ColourValue::White;//Ogre::ColourValue(0.1337f, 0.1337f, 0.1337f, 1.0f); Ogre::ColourValue GridColour = Ogre::ColourValue(0.2f, 0.2f, 0.2f, 1.0f); Ogre::ManualObject *mReferenceObject = new Ogre::ManualObject("ReferenceGrid"); mReferenceObject->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_LINE_LIST); Ogre::Real step = 1.0f; unsigned int count = 50; unsigned int halfCount = count / 2; Ogre::Real full = (step * count); Ogre::Real half = full / 2; Ogre::Real y = 0; Ogre::ColourValue c; for (unsigned i=0;i < count+1;i++) { if (i == halfCount) c = Ogre::ColourValue(1,0,0,1.0f); else c = GridColour; mReferenceObject->position(-half,y,-half+(step*i)); mReferenceObject->colour(BackgroundColour); mReferenceObject->position(0,y,-half+(step*i)); mReferenceObject->colour(c); mReferenceObject->position(0,y,-half+(step*i)); mReferenceObject->colour(c); mReferenceObject->position(half,y,-half+(step*i)); mReferenceObject->colour(BackgroundColour); if (i == halfCount) c = Ogre::ColourValue(0,0,1,1.0f); else c = GridColour; mReferenceObject->position(-half+(step*i),y,-half); mReferenceObject->colour(BackgroundColour); mReferenceObject->position(-half+(step*i),y,0); mReferenceObject->colour(c); mReferenceObject->position(-half+(step*i),y,0); mReferenceObject->colour(c); mReferenceObject->position(-half+(step*i),y, half); mReferenceObject->colour(BackgroundColour); } mReferenceObject->end(); mReferenceObject->setCastShadows(false); SceneNode *n = gEnv->sceneManager->getRootSceneNode()->createChildSceneNode(); n->setPosition(pos); n->attachObject(mReferenceObject); n->setVisible(true); } #ifdef USE_PAGED //ugly stuff to parse trees :) if (!strncmp("trees", line, 5)) { if (terrainManager->getPagedMode() == 0) continue; char ColorMap[256] = {}; char DensityMap[256] = {}; char treemesh[256] = {}; char treeCollmesh[256] = {}; float gridspacing = 0.0f; float yawfrom = 0.0f, yawto = 0.0f; float scalefrom = 0.0f, scaleto = 0.0f; float highdens = 1.0f; int minDist = 90, maxDist = 700; sscanf(line, "trees %f, %f, %f, %f, %f, %d, %d, %s %s %s %f %s", &yawfrom, &yawto, &scalefrom, &scaleto, &highdens, &minDist, &maxDist, treemesh, ColorMap, DensityMap, &gridspacing, treeCollmesh); if (strnlen(ColorMap, 3) == 0) { LOG("tree ColorMap map zero!"); continue; } if (strnlen(DensityMap, 3) == 0) { LOG("tree DensityMap zero!"); continue; } Forests::DensityMap *densityMap = Forests::DensityMap::load(DensityMap, Forests::CHANNEL_COLOR); if (!densityMap) { LOG("could not load densityMap: "+String(DensityMap)); continue; } densityMap->setFilter(Forests::MAPFILTER_BILINEAR); //densityMap->setMapBounds(TRect(0, 0, mapsizex, mapsizez)); paged_geometry_t paged; paged.geom = new PagedGeometry(); paged.geom->setTempDir(SSETTING("User Path", "") + "cache" + SSETTING("dirsep", "\\")); paged.geom->setCamera(gEnv->mainCamera); paged.geom->setPageSize(50); paged.geom->setInfinite(); Ogre::TRect<Ogre::Real> bounds = TBounds(0, 0, mapsizex, mapsizez); paged.geom->setBounds(bounds); //Set up LODs //trees->addDetailLevel<EntityPage>(50); float min = minDist * terrainManager->getPagedDetailFactor(); if (min<10) min = 10; paged.geom->addDetailLevel<BatchPage>(min, min/2); float max = maxDist * terrainManager->getPagedDetailFactor(); if (max<10) max = 10; paged.geom->addDetailLevel<ImpostorPage>(max, max/10); TreeLoader2D *treeLoader = new TreeLoader2D(paged.geom, TBounds(0, 0, mapsizex, mapsizez)); paged.geom->setPageLoader(treeLoader); treeLoader->setHeightFunction(&getTerrainHeight); if (String(ColorMap) != "none") { treeLoader->setColorMap(ColorMap); } Entity *curTree = gEnv->sceneManager->createEntity(String("paged_")+treemesh+TOSTRING(pagedGeometry.size()), treemesh); if (gridspacing > 0) { // grid style for (float x=0; x < mapsizex; x += gridspacing) { for (float z=0; z < mapsizez; z += gridspacing) { float density = densityMap->_getDensityAt_Unfiltered(x, z, bounds); if (density < 0.8f) continue; float nx = x + gridspacing * 0.5f; float nz = z + gridspacing * 0.5f; float yaw = Math::RangeRandom(yawfrom, yawto); float scale = Math::RangeRandom(scalefrom, scaleto); Vector3 pos = Vector3(nx, 0, nz); treeLoader->addTree(curTree, pos, Degree(yaw), (Ogre::Real)scale); if (strlen(treeCollmesh)) { pos.y = gEnv->terrainManager->getHeightFinder()->getHeightAt(pos.x, pos.z); scale *= 0.1f; gEnv->collisions->addCollisionMesh(String(treeCollmesh), pos, Quaternion(Degree(yaw), Vector3::UNIT_Y), Vector3(scale, scale, scale)); } } } } else { float gridsize = 10; if (gridspacing < 0 && gridspacing != 0) { gridsize = -gridspacing; } float hd = highdens; // normal style, random for (float x=0; x < mapsizex; x += gridsize) { for (float z=0; z < mapsizez; z += gridsize) { if (highdens < 0) hd = Math::RangeRandom(0, -highdens); float density = densityMap->_getDensityAt_Unfiltered(x, z, bounds); int numTreesToPlace = (int)((float)(hd) * density * terrainManager->getPagedDetailFactor()); float nx=0, nz=0; while(numTreesToPlace-->0) { nx = Math::RangeRandom(x, x + gridsize); nz = Math::RangeRandom(z, z + gridsize); float yaw = Math::RangeRandom(yawfrom, yawto); float scale = Math::RangeRandom(scalefrom, scaleto); Vector3 pos = Vector3(nx, 0, nz); treeLoader->addTree(curTree, pos, Degree(yaw), (Ogre::Real)scale); if (strlen(treeCollmesh)) { pos.y = gEnv->terrainManager->getHeightFinder()->getHeightAt(pos.x, pos.z); gEnv->collisions->addCollisionMesh(String(treeCollmesh),pos, Quaternion(Degree(yaw), Vector3::UNIT_Y), Vector3(scale, scale, scale)); } } } } } paged.loader = (void*)treeLoader; pagedGeometry.push_back(paged); } //ugly stuff to parse grass :) if (!strncmp("grass", line, 5) || !strncmp("grass2", line, 6)) { // is paged geometry disabled by configuration? if (terrainManager->getPagedMode() == 0) continue; int range = 80; float SwaySpeed=0.5, SwayLength=0.05, SwayDistribution=10.0, minx=0.2, miny=0.2, maxx=1, maxy=0.6, Density=0.6, minH=-9999, maxH=9999; char grassmat[256]=""; char colorMapFilename[256]=""; char densityMapFilename[256]=""; int growtechnique = 0; int techn = GRASSTECH_CROSSQUADS; if (!strncmp("grass2", line, 6)) sscanf(line, "grass2 %d, %f, %f, %f, %f, %f, %f, %f, %f, %d, %f, %f, %d, %s %s %s", &range, &SwaySpeed, &SwayLength, &SwayDistribution, &Density, &minx, &miny, &maxx, &maxy, &growtechnique, &minH, &maxH, &techn, grassmat, colorMapFilename, densityMapFilename); else if (!strncmp("grass", line, 5)) sscanf(line, "grass %d, %f, %f, %f, %f, %f, %f, %f, %f, %d, %f, %f, %s %s %s", &range, &SwaySpeed, &SwayLength, &SwayDistribution, &Density, &minx, &miny, &maxx, &maxy, &growtechnique, &minH, &maxH, grassmat, colorMapFilename, densityMapFilename); //Initialize the PagedGeometry engine try { paged_geometry_t paged; PagedGeometry *grass = new PagedGeometry(gEnv->mainCamera, 30); //Set up LODs grass->addDetailLevel<GrassPage>(range * terrainManager->getPagedDetailFactor()); // original value: 80 //Set up a GrassLoader for easy use GrassLoader *grassLoader = new GrassLoader(grass); grass->setPageLoader(grassLoader); grassLoader->setHeightFunction(&getTerrainHeight); // render grass at first grassLoader->setRenderQueueGroup(RENDER_QUEUE_MAIN-1); GrassLayer* grassLayer = grassLoader->addLayer(grassmat); grassLayer->setHeightRange(minH, maxH); grassLayer->setLightingEnabled(true); grassLayer->setAnimationEnabled((SwaySpeed>0)); grassLayer->setSwaySpeed(SwaySpeed); grassLayer->setSwayLength(SwayLength); grassLayer->setSwayDistribution(SwayDistribution); //String grassdensityTextureFilename = String(DensityMap); grassLayer->setDensity(Density * terrainManager->getPagedDetailFactor()); if (techn>10) grassLayer->setRenderTechnique(static_cast<GrassTechnique>(techn-10), true); else grassLayer->setRenderTechnique(static_cast<GrassTechnique>(techn), false); grassLayer->setMapBounds(TBounds(0, 0, mapsizex, mapsizez)); if (strcmp(colorMapFilename,"none") != 0) { grassLayer->setColorMap(colorMapFilename); grassLayer->setColorMapFilter(MAPFILTER_BILINEAR); } if (strcmp(densityMapFilename,"none") != 0) { grassLayer->setDensityMap(densityMapFilename); grassLayer->setDensityMapFilter(MAPFILTER_BILINEAR); } //grassLayer->setMinimumSize(0.5,0.5); //grassLayer->setMaximumSize(1.0, 1.0); grassLayer->setMinimumSize(minx, miny); grassLayer->setMaximumSize(maxx, maxy); // growtechnique if (growtechnique == 0) grassLayer->setFadeTechnique(FADETECH_GROW); else if (growtechnique == 1) grassLayer->setFadeTechnique(FADETECH_ALPHAGROW); else if (growtechnique == 2) grassLayer->setFadeTechnique(FADETECH_ALPHA); paged.geom = grass; paged.loader = (void*)grassLoader; pagedGeometry.push_back(paged); } catch(...) { LOG("error loading grass!"); } continue; } #endif //USE_PAGED { // ugly stuff to parse procedural roads if (!strncmp("begin_procedural_roads", line, 22)) { po = ProceduralObject(); po.loadingState = 1; r2oldmode = 1; proroad = true; continue; } if (!strncmp("end_procedural_roads", line, 20)) { if (r2oldmode) { if (proceduralManager) proceduralManager->addObject(po); po = ProceduralObject(); } proroad = false; continue; } if (proroad) { float rwidth, bwidth, bheight; //position x,y,z rotation rx,ry,rz, width, border width, border height, type int r = sscanf(line, "%f, %f, %f, %f, %f, %f, %f, %f, %f, %s",&pos.x,&pos.y,&pos.z, &rot.x, &rot.y, &rot.z, &rwidth, &bwidth, &bheight, oname); Quaternion rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X)*Quaternion(Degree(rot.y), Vector3::UNIT_Y)*Quaternion(Degree(rot.z), Vector3::UNIT_Z); int roadtype=Road2::ROAD_AUTOMATIC; int pillartype = 0; if (!strcmp(oname, "flat")) roadtype=Road2::ROAD_FLAT; if (!strcmp(oname, "left")) roadtype=Road2::ROAD_LEFT; if (!strcmp(oname, "right")) roadtype=Road2::ROAD_RIGHT; if (!strcmp(oname, "both")) roadtype=Road2::ROAD_BOTH; if (!strcmp(oname, "bridge")) {roadtype=Road2::ROAD_BRIDGE;pillartype=1;} if (!strcmp(oname, "monorail")) {roadtype=Road2::ROAD_MONORAIL;pillartype=2;} if (!strcmp(oname, "monorail2")) {roadtype=Road2::ROAD_MONORAIL;pillartype=0;} if (!strcmp(oname, "bridge_no_pillars")) {roadtype=Road2::ROAD_BRIDGE;pillartype=0;} if (r2oldmode) { //fill object ProceduralPoint pp; pp.bheight = bheight; pp.bwidth = bwidth; pp.pillartype = pillartype; pp.position = pos; pp.rotation = rotation; pp.type = roadtype; pp.width = rwidth; po.points.push_back(pp); } continue; } } //end of the ugly (somewhat) strcpy(name, "generic"); memset(oname, 0, 255); memset(type, 0, 255); memset(name, 0, 255); int r = sscanf(line, "%f, %f, %f, %f, %f, %f, %s %s %s",&pos.x,&pos.y,&pos.z, &rot.x, &rot.y, &rot.z, oname, type, name); if (r < 6) continue; if ((!strcmp(oname, "truck")) || (!strcmp(oname, "load") || (!strcmp(oname, "machine")) || (!strcmp(oname, "boat")) || (!strcmp(oname, "truck2")) )) { if (!strcmp(oname, "boat") && !terrainManager->getWater()) { // no water so do not load boats! continue; } String group = ""; String truckname(type); if (!RoR::Application::GetCacheSystem()->checkResourceLoaded(truckname, group)) { LOG("Error while loading Terrain: truck " + String(type) + " not found. ignoring."); continue; } truck_prepare_t tempTruckPreload; //this is a truck or load declaration tempTruckPreload.px = pos.x; tempTruckPreload.py = pos.y; tempTruckPreload.pz = pos.z; tempTruckPreload.freePosition = (!strcmp(oname, "truck2")); tempTruckPreload.ismachine = (!strcmp(oname, "machine")); tempTruckPreload.rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X)*Quaternion(Degree(rot.y), Vector3::UNIT_Y)*Quaternion(Degree(rot.z), Vector3::UNIT_Z); strcpy(tempTruckPreload.name, truckname.c_str()); truck_preload.push_back(tempTruckPreload); continue; } if ( !strcmp(oname, "road") || !strcmp(oname, "roadborderleft") || !strcmp(oname, "roadborderright") || !strcmp(oname, "roadborderboth") || !strcmp(oname, "roadbridgenopillar") || !strcmp(oname, "roadbridge")) { int pillartype = !(strcmp(oname, "roadbridgenopillar") == 0); // okay, this is a job for roads2 int roadtype=Road2::ROAD_AUTOMATIC; if (!strcmp(oname, "road")) roadtype=Road2::ROAD_FLAT; Quaternion rotation; rotation = Quaternion(Degree(rot.x), Vector3::UNIT_X)*Quaternion(Degree(rot.y), Vector3::UNIT_Y)*Quaternion(Degree(rot.z), Vector3::UNIT_Z); if (pos.distance(r2lastpos) > 20.0f) { // break the road if (r2oldmode != 0) { // fill object ProceduralPoint pp; pp.bheight = 0.2; pp.bwidth = 1.4; pp.pillartype = pillartype; pp.position = r2lastpos + r2lastrot * Vector3(10.0f, 0.0f, 0.9f); pp.rotation = r2lastrot; pp.type = roadtype; pp.width = 8; po.points.push_back(pp); // finish it and start new object if (proceduralManager) proceduralManager->addObject(po); po = ProceduralObject(); r2oldmode = 1; } r2oldmode = 1; // beginning of new ProceduralPoint pp; pp.bheight = 0.2; pp.bwidth = 1.4; pp.pillartype = pillartype; pp.position = pos; pp.rotation = rotation; pp.type = roadtype; pp.width = 8; po.points.push_back(pp); } else { // fill object ProceduralPoint pp; pp.bheight = 0.2; pp.bwidth = 1.4; pp.pillartype = pillartype; pp.position = pos; pp.rotation = rotation; pp.type = roadtype; pp.width = 8; po.points.push_back(pp); } r2lastpos=pos; r2lastrot=rotation; continue; } loadObject(oname, pos, rot, bakeNode, name, type); } // ds closes automatically, so do not close it explicitly here: ds->close(); // finish the last road if (r2oldmode != 0) { // fill object ProceduralPoint pp; pp.bheight = 0.2; pp.bwidth = 1.4; pp.pillartype = 1; pp.position = r2lastpos+r2lastrot*Vector3(10.0,0,0); pp.rotation = r2lastrot; pp.type = Road2::ROAD_AUTOMATIC; pp.width = 8; po.points.push_back(pp); // finish it and start new object if (proceduralManager) proceduralManager->addObject(po); } }