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