Revision: 1592
          http://rigsofrods.svn.sourceforge.net/rigsofrods/?rev=1592&view=rev
Author:   rorthomas
Date:     2011-01-22 18:32:14 +0000 (Sat, 22 Jan 2011)

Log Message:
-----------
added terrain decals
added ; as comment character for .terrn file

Modified Paths:
--------------
    trunk/source/main/RoRFrameListener.cpp
    trunk/source/main/RoRFrameListener.h

Modified: trunk/source/main/RoRFrameListener.cpp
===================================================================
--- trunk/source/main/RoRFrameListener.cpp      2011-01-22 16:40:09 UTC (rev 
1591)
+++ trunk/source/main/RoRFrameListener.cpp      2011-01-22 18:32:14 UTC (rev 
1592)
@@ -784,7 +784,6 @@
        objectCounter=0;
        hdrListener=0;
        shaderSchemeMode=1;
-
        netPointToUID=-1;
        netcheckGUITimer=0;
        mDOF=0;
@@ -853,6 +852,11 @@
        dashboard=0;//new Dashboard(scm,win);
 
        mSceneMgr=scm;
+
+       terrain_decals_snode = 
mSceneMgr->getRootSceneNode()->createChildSceneNode();
+       terrain_decal_count = 0;
+
+
 #ifdef USE_OPENAL
        ssm=SoundScriptManager::getSingleton();
 #endif //OPENAL
@@ -2367,6 +2371,7 @@
                mDOF->setDebugEnabled(mDOFDebug);
        }
        
+       /*
        if (INPUTENGINE.getEventBoolValueBounce(EV_TOGGLESHADERS, 0.5f))
        {
                if(shaderSchemeMode)
@@ -2383,6 +2388,7 @@
                        if(ow) ow->flashMessage("shaders enabled");
                }
        }
+       */
 
        if (INPUTENGINE.getEventBoolValueBounce(EV_COMMON_SCREENSHOT_BIG, 0.5f))
        {
@@ -5538,6 +5544,14 @@
        po.loadingState = -1;
        int r2oldmode=0;
 
+
+       bool decalSplineMode = false;
+       Ogre::SimpleSpline *spline = 0;
+       Ogre::String splinemat = "", spline_export_fn = "";
+       float spline_width = 5;
+       int spline_segments_x = 10, spline_segments_y = 10;
+       float splinetex_u = 1, splinetex_v = 1, ground_offset=0.001f;
+
        int lastprogress = -1;
        while (!ds->eof())
        {
@@ -5558,8 +5572,48 @@
                float rx, ry, rz;
                //fscanf(fd," %[^\n\r]",line);
                size_t ll=ds->readLine(line, 1023);
-               if (line[0]=='/' || ll==0) continue; //comments
+               if (line[0]=='/' || line[0]==';' || ll==0) continue; //comments
                if (!strcmp("end",line)) break;
+
+
+               if(decalSplineMode)
+               {
+                       if (!strncmp(line,"end_spline_decal", 16))
+                       {
+                               // realize spline decal now
+                               addTerrainSplineDecal(spline, spline_width, 
Vector2(spline_segments_x,spline_segments_y), Vector2(splinetex_u, 
splinetex_v), splinemat, ground_offset, spline_export_fn);
+                               decalSplineMode = false;
+                               continue;
+                       }
+
+                       if (!strncmp("point", line, 5))
+                       {
+                               float x=0,y=0,z=0;
+                               int res = sscanf(line, "point %f, %f, %f", &x, 
&y, &z);
+                               spline->addPoint(Vector3(x, y, z));
+                       } else if (!strncmp("EXPORT", line, 6))
+                       {
+                               char fn[255] = "";
+                               int res = sscanf(line, "EXPORT %s", fn);
+                               spline_export_fn = String(fn);
+                       }
+                       continue;
+               }
+               if (!strncmp("start_spline_decal", line, 18))
+               {
+                       char matname[255]="";
+                       int res = sscanf(line, "start_spline_decal %d, %d, %f, 
%f, %f, %f, %s", &spline_segments_x, &spline_segments_y, &splinetex_u, 
&splinetex_v, &spline_width, &ground_offset, matname);
+                       if(spline_segments_x < 1 || spline_segments_y < 1)
+                       {
+                               LogManager::getSingleton().logMessage("spline  
segments must be at least 1");
+                               continue;
+                       }
+                       splinemat = String(matname);
+
+                       spline = new Ogre::SimpleSpline();
+                       decalSplineMode = true;
+               }
+
                //sandstorm cube texture
                if (!strncmp(line,"sandstormcubemap", 16))
                {
@@ -5703,6 +5757,28 @@
                        paged.loader = (void*)treeLoader;
                        pagedGeometry.push_back(paged);
                }
+               //ugly stuff to parse decals :)
+               if (!strncmp("decal", line, 5))
+               {
+                       float x=0, y=0, z=0, w=0, h=0, rot=0;
+                       int nsx=1, nsy=1;
+
+                       char decal_mat[255]="";
+                       char decal_normal[255]="";
+                       int res = sscanf(line, "decal %f, %f, %f, %f, %f, %f, 
%d, %d, %s %s", &x, &y, &z, &w, &h,  &rot, &nsx, &nsy, decal_mat, decal_normal);
+                       if(rot < 0)
+                               rot = Ogre::Math::RangeRandom(0.0f, 360);
+
+                       addTerrainDecal(Vector3(x,y,z), Vector2(w, w), 
Vector2(nsx, nsy), rot, String(decal_mat), String(decal_normal));
+
+                       continue;
+               }
+               if (!strncmp("bake_decals", line, 11))
+               {
+                       // bake them
+                       finishTerrainDecal();
+               }
+
                //ugly stuff to parse grass :)
                if (!strncmp("grass", line, 5) || !strncmp("grass2", line, 6))
                {
@@ -6024,6 +6100,9 @@
        if(debugCollisions)
                collisions->createCollisionDebugVisualization();
 
+       // bake the decals
+       finishTerrainDecal();
+
 #ifdef USE_MYGUI
        LoadingWindow::get()->hide();
 
@@ -8005,3 +8084,354 @@
        pthread_mutex_unlock(&mutex_data);
        return res;
 }
+
+int RoRFrameListener::addTerrainSplineDecal(Ogre::SimpleSpline *spline, float 
width, Ogre::Vector2 numSeg, Ogre::Vector2 uvSeg, Ogre::String materialname, 
float ground_offset, Ogre::String export_fn)
+{
+       // debug spline line
+       {
+               Ogre::ManualObject *mo_spline = mSceneMgr->createManualObject();
+               SceneNode *mo_spline_node = 
terrain_decals_snode->createChildSceneNode();
+               mo_spline->begin("tracks/transred", 
Ogre::RenderOperation::OT_LINE_STRIP);
+               for(float j=0;j<1;j+=0.001)
+               {
+                       mo_spline->position(spline->interpolate(j));
+               }
+               mo_spline->end();
+               mo_spline_node->attachObject(mo_spline);
+       }
+
+       Ogre::ManualObject *mo = mSceneMgr->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));
+               if(l == numSeg.x)
+                       // last segment uses previous position
+                       pos_next = spline->interpolate(steps_len * (float)(l - 
1));
+
+        Ogre::Vector3 direction = (pos_next - pos_cur);
+        
+               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
+       mSceneMgr->destroyManualObject(mo);
+
+       unsigned short src, dest;
+       if (!mesh->suggestTangentVectorBuildParams(VES_TANGENT, src, dest))
+       {
+               mesh->buildTangentVectors(VES_TANGENT, src, dest);
+       }
+       
+       Entity *ent = mSceneMgr->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);
+               Ogre::LogManager::getSingleton().logMessage("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, "");
+
+       return 0;
+}
+
+int RoRFrameListener::addTerrainDecal(Ogre::Vector3 position, Ogre::Vector2 
size, Ogre::Vector2 numSeg, Ogre::Real rotation, Ogre::String materialname, 
Ogre::String normalname)
+{
+       Ogre::ManualObject *mo = mSceneMgr->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
+       mSceneMgr->destroyManualObject(mo);
+
+       unsigned short src, dest;
+       if (!mesh->suggestTangentVectorBuildParams(VES_TANGENT, src, dest))
+       {
+               mesh->buildTangentVectors(VES_TANGENT, src, dest);
+       }
+       
+       Entity *ent = mSceneMgr->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);
+
+       return 0;
+}
+
+bool RoRFrameListener::RTSSgenerateShadersForMaterial(Ogre::String 
curMaterialName, Ogre::String normalTextureName)
+{
+       bool success;
+
+       // Create the shader based technique of this material.
+       success = 
Ogre::RTShader::ShaderGenerator::getSingleton().createShaderBasedTechnique(curMaterialName,
 
+                                               
MaterialManager::DEFAULT_SCHEME_NAME,
+                                               
RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME);
+       if(!success)
+               return false;
+               
+       // Setup custom shader sub render states according to current setup.
+       MaterialPtr curMaterial = 
MaterialManager::getSingleton().getByName(curMaterialName);
+       Pass* curPass = curMaterial->getTechnique(0)->getPass(0);
+
+
+       // Grab the first pass render state. 
+       // NOTE: For more complicated samples iterate over the passes and build 
each one of them as desired.
+       RTShader::RenderState* renderState = 
Ogre::RTShader::ShaderGenerator::getSingleton().getRenderState(RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME,
 curMaterialName, 0);
+
+       // Remove all sub render states.
+       renderState->reset();
+
+
+#ifdef RTSHADER_SYSTEM_BUILD_CORE_SHADERS
+       // simple vertex lightning
+       /*
+       {
+               RTShader::SubRenderState* perPerVertexLightModel = 
Ogre::RTShader::ShaderGenerator::getSingleton().createSubRenderState(RTShader::FFPLighting::Type);
+               renderState->addTemplateSubRenderState(perPerVertexLightModel); 
+       }
+       */
+#endif
+#ifdef RTSHADER_SYSTEM_BUILD_EXT_SHADERS
+       if(normalTextureName.empty())
+       {
+               // SSLM_PerPixelLighting
+               RTShader::SubRenderState* perPixelLightModel = 
Ogre::RTShader::ShaderGenerator::getSingleton().createSubRenderState(RTShader::PerPixelLighting::Type);
+                               
+               renderState->addTemplateSubRenderState(perPixelLightModel);     
                        
+       } else
+       {
+               // SSLM_NormalMapLightingTangentSpace
+               RTShader::SubRenderState* subRenderState = 
Ogre::RTShader::ShaderGenerator::getSingleton().createSubRenderState(RTShader::NormalMapLighting::Type);
+               RTShader::NormalMapLighting* normalMapSubRS = 
static_cast<RTShader::NormalMapLighting*>(subRenderState);
+                                       
+               
normalMapSubRS->setNormalMapSpace(RTShader::NormalMapLighting::NMS_TANGENT);
+               normalMapSubRS->setNormalMapTextureName(normalTextureName);     
+
+               renderState->addTemplateSubRenderState(normalMapSubRS);
+       }
+       // SSLM_NormalMapLightingObjectSpace
+       /*
+       {
+               // Apply normal map only on main entity.
+               if (entity->getName() == MAIN_ENTITY_NAME)
+               {
+                       RTShader::SubRenderState* subRenderState = 
mShaderGenerator->createSubRenderState(RTShader::NormalMapLighting::Type);
+                       RTShader::NormalMapLighting* normalMapSubRS = 
static_cast<RTShader::NormalMapLighting*>(subRenderState);
+                               
+                       
normalMapSubRS->setNormalMapSpace(RTShader::NormalMapLighting::NMS_OBJECT);
+                       
normalMapSubRS->setNormalMapTextureName("Panels_Normal_Obj.png");       
+
+                       renderState->addTemplateSubRenderState(normalMapSubRS);
+               }
+                               
+               // It is secondary entity -> use simple per pixel lighting.
+               else
+               {
+                       RTShader::SubRenderState* perPixelLightModel = 
mShaderGenerator->createSubRenderState(RTShader::PerPixelLighting::Type);
+                       
renderState->addTemplateSubRenderState(perPixelLightModel);
+               }                               
+       } */
+
+#endif
+
+       // Invalidate this material in order to re-generate its shaders.
+       
Ogre::RTShader::ShaderGenerator::getSingleton().invalidateMaterial(RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME,
 curMaterialName);
+       return true;                                            
+}
+
+void RoRFrameListener::RTSSgenerateShaders(Entity* entity, Ogre::String 
normalTextureName)
+{
+       for (unsigned int i=0; i < entity->getNumSubEntities(); ++i)
+       {
+               SubEntity* curSubEntity = entity->getSubEntity(i);
+               const String& curMaterialName = curSubEntity->getMaterialName();
+       
+               RTSSgenerateShadersForMaterial(curMaterialName, 
normalTextureName);
+       }
+}
+
+int RoRFrameListener::finishTerrainDecal()
+{
+       // if if no decals
+       if(!terrain_decals_snode->numChildren()) return 0;
+       terrain_decal_count++;
+       terrain_decals_sg = 
mSceneMgr->createStaticGeometry("terrain_decals_"+StringConverter::toString(terrain_decal_count));
+       terrain_decals_sg->setCastShadows(false);
+       terrain_decals_sg->addSceneNode(terrain_decals_snode);
+       terrain_decals_sg->setRegionDimensions(Vector3(farclip/2.0, 10000.0, 
farclip/2.0));
+       terrain_decals_sg->setRenderingDistance(farclip);
+       try
+       {
+               terrain_decals_sg->build();
+               terrain_decals_snode->detachAllObjects();
+               //terrain_decals_snode->removeAllChildren();
+               // crash under linux:
+               //bakeNode->removeAndDestroyAllChildren();
+       } catch(Ogre::Exception& e)
+       {
+               LogManager::getSingleton().logMessage("error while baking 
decals: " + e.getFullDescription());
+       }
+       return 0;
+}

Modified: trunk/source/main/RoRFrameListener.h
===================================================================
--- trunk/source/main/RoRFrameListener.h        2011-01-22 16:40:09 UTC (rev 
1591)
+++ trunk/source/main/RoRFrameListener.h        2011-01-22 18:32:14 UTC (rev 
1592)
@@ -379,6 +379,20 @@
 
        int cameramode, lastcameramode;
        void setCameraRotation(Ogre::Radian x, Ogre::Radian y, Ogre::Real 
distance) { camRotX=x; camRotY=y; camDist=distance;};
+
+       // TERRAIN DECALS START
+       int addTerrainDecal(Ogre::Vector3 position, Ogre::Vector2 size, 
Ogre::Vector2 numSeg, Ogre::Real rotation, Ogre::String materialname, 
Ogre::String normalname);
+       int addTerrainSplineDecal(Ogre::SimpleSpline *spline, float width, 
Ogre::Vector2 numSeg, Ogre::Vector2 uvSeg, Ogre::String materialname, float 
ground_offset, Ogre::String export_fn);
+       int finishTerrainDecal();
+       StaticGeometry *terrain_decals_sg;
+       SceneNode *terrain_decals_snode;
+       int terrain_decal_count;
+
+       void RTSSgenerateShaders(Ogre::Entity *entity, Ogre::String 
normalTextureName);
+       bool RTSSgenerateShadersForMaterial(Ogre::String curMaterialName, 
Ogre::String normalTextureName);
+       // TERRAIN DECALS END
+
+
        void hideMap();
        void setDirectionArrow(char *text, Vector3 position);
        Ogre::Radian getCameraRotationX() { return camRotX; };


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------
Special Offer-- Download ArcSight Logger for FREE (a $49 USD value)!
Finally, a world-class log management solution at an even better price-free!
Download using promo code Free_Logger_4_Dev2Dev. Offer expires 
February 28th, so secure your free ArcSight Logger TODAY! 
http://p.sf.net/sfu/arcsight-sfd2d
_______________________________________________
Rigsofrods-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rigsofrods-devel

Reply via email to