00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "Terrain3D.h"
00024 #include <stdlib.h>
00025 #include <time.h>
00026 #include <osg/Billboard>
00027 #include <osg/AlphaFunc>
00028 #include <osg/BlendFunc>
00029
00030
00031 Terrain3D::Terrain3D(char* path, osg::Group* terrain,int nbTree)
00032 {
00033 float perc[4];
00034
00035 osg::Image * heights = osgDB::readImageFile(path);
00036 if(!heights)
00037 {
00038 printf("Erreur lors du chargement de la heigtmap\n");
00039 ok = false;
00040 return;
00041 }
00042
00043 std::cout << "Heightmap chargée" << std::endl;
00044
00045
00046
00047 HeightMap = new osg::HeightField();
00048 if(!HeightMap)
00049 {
00050 printf("Erreur lors de l'allocation de la heightmap\n");
00051 ok = false;
00052 return;
00053 }
00054
00055
00056 SDL_Surface* TextureFinale = SDL_CreateRGBSurface(SDL_HWSURFACE,heights->s(), heights->t(), 32, 0, 0, 0, 0);
00057 if(!TextureFinale)
00058 {
00059 printf("Erreur lors de l'allocation de la texture de terrain\n");
00060 ok = false;
00061 return;
00062 }
00063
00064
00065
00066
00067 SDL_Surface* terre = SDL_LoadBMP("data/Heightmap/terre.bmp");
00068 if(!terre)
00069 {
00070 printf("Erreur lors de la récupération de la texture de terre\n");
00071 ok = false;
00072 return;
00073 }
00074
00075 SDL_Surface* prairies = SDL_LoadBMP("data/Heightmap/grassm.bmp");
00076 if(!prairies)
00077 {
00078 printf("Erreur lors de la récupération de la texture de prairie\n");
00079 ok = false;
00080 return;
00081 }
00082
00083 SDL_Surface* rocheuses = SDL_LoadBMP("data/Heightmap/rock.bmp");
00084 if(!rocheuses)
00085 {
00086 printf("Erreur lors de la récupération de la texture de montagne\n");
00087 ok = false;
00088 return;
00089 }
00090
00091 SDL_Surface* neige = SDL_LoadBMP("data/Heightmap/snow.bmp");
00092 if(!neige)
00093 {
00094 printf("Erreur lors de la récupération de la texture de neige\n");
00095 ok = false;
00096 return;
00097 }
00098
00099 std::cout << "Textures chargées" << std::endl;
00100
00101
00102 printf("Heightmap : width=%d\theight=%d\n", heights->s(), heights->t());
00103 HeightMap->allocate(heights->s(), heights->t());
00104
00105
00106 for(int row=0; row<heights->s(); row++)
00107 for(int column=0; column<heights->t(); column++)
00108 {
00109
00110 int tmpi = (int ) (( ((float) column)/TextureFinale->h) * heights->s()) ;
00111 int tmpj = (int ) (( ((float) row)/TextureFinale->w) * heights->t()) ;
00112 RemplitPerc(perc,heights->data(column,row)[0]);
00113
00114
00115 tmpi = column%terre->h;
00116 tmpj = row%terre->w;
00117
00118 double b = perc[0] * GetPixelColor(terre,tmpi,tmpj,0);
00119 double g = perc[0] * GetPixelColor(terre,tmpi,tmpj,1);
00120 double r = perc[0] * GetPixelColor(terre,tmpi,tmpj,2);
00121
00122 tmpi = column%prairies->h;
00123 tmpj = row%prairies->w;
00124
00125 b += perc[1] * GetPixelColor(prairies,tmpi,tmpj,0);
00126 g += perc[1] * GetPixelColor(prairies,tmpi,tmpj,1);
00127 r += perc[1] * GetPixelColor(prairies,tmpi,tmpj,2);
00128
00129 tmpi = column%rocheuses->h;
00130 tmpj = row%rocheuses->w;
00131
00132 b += perc[2] * GetPixelColor(rocheuses,tmpi,tmpj,0);
00133 g += perc[2] * GetPixelColor(rocheuses,tmpi,tmpj,1);
00134 r += perc[2] * GetPixelColor(rocheuses,tmpi,tmpj,2);
00135
00136 tmpi = column%neige->h;
00137 tmpj = row%neige->w;
00138
00139 b += perc[3] * GetPixelColor(neige,tmpi,tmpj,0);
00140 g += perc[3] * GetPixelColor(neige,tmpi,tmpj,1);
00141 r += perc[3] * GetPixelColor(neige,tmpi,tmpj,2);
00142
00143
00144 SetPixel(TextureFinale, row, column, SDL_MapRGB(TextureFinale->format, (unsigned char)r, (unsigned char)g, (unsigned char)b));
00145 if(row==(heights->s()-1) ||column == (heights->t()-1) || row==0 || column==0)
00146 {
00147 SetPixel(TextureFinale, row, column, SDL_MapRGB(TextureFinale->format, 0,0,0));
00148 HeightMap->setHeight(row, heights->t()-column-1, -10);
00149 } else
00150
00151 HeightMap->setHeight(row, heights->t()-column-1, heights->data(column,row)[0]);
00152
00153 }
00154
00155 std::cout << "Textures crées" << std::endl;
00156
00157
00158 SDL_SaveBMP(TextureFinale, "data/Heightmap/TextTerrain.bmp");
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 osg::ShapeDrawable * HMDrawable = new osg::ShapeDrawable(HeightMap);
00177 HeightMapGeode = new osg::Geode();
00178 HeightMapGeode->addDrawable(HMDrawable);
00179
00180
00181 TextureHeightMap();
00182
00183 std::cout << "Heightmap terminée. " << std::endl;
00184
00185 if(nbTree>0)
00186 {
00187 std::cout << "Génération des arbres. " << std::endl;
00188
00189 osg::Texture2D *treeTexture = new osg::Texture2D;
00190 treeTexture->setImage(osgDB::readImageFile("data/Textures/Arbre3.png"));
00191
00192 osg::Texture2D *treeTexture2 = new osg::Texture2D;
00193 treeTexture2->setImage(osgDB::readImageFile("data/Textures/Arbre2.png"));
00194
00195 osg::Texture2D *treeTexture3 = new osg::Texture2D;
00196 treeTexture3->setImage(osgDB::readImageFile("data/Textures/falltree.png"));
00197
00198 osg::Texture2D *treeTexture4 = new osg::Texture2D;
00199 treeTexture4->setImage(osgDB::readImageFile("data/Textures/arbre.png"));
00200
00201 osg::Texture2D *grassTexture = new osg::Texture2D;
00202 grassTexture->setImage(osgDB::readImageFile("data/Textures/grass1.tga"));
00203
00204 osg::Texture2D *grassTexture1 = new osg::Texture2D;
00205 grassTexture1->setImage(osgDB::readImageFile("data/Textures/grass2.tga"));
00206
00207 osg::Texture2D *grassTexture2 = new osg::Texture2D;
00208 grassTexture2->setImage(osgDB::readImageFile("data/Textures/grass3.tga"));
00209
00210 osg::Texture2D *grassTexture3 = new osg::Texture2D;
00211 grassTexture3->setImage(osgDB::readImageFile("data/Textures/grass4.tga"));
00212
00213 osg::Texture2D *grassTexture4 = new osg::Texture2D;
00214 grassTexture4->setImage(osgDB::readImageFile("data/Textures/grass5.tga"));
00215
00216
00217 srand(time(NULL));
00218
00219
00220 addTrees(terrain,grassTexture,2,1.0,1.1,nbTree,83,92);
00221 addTrees(terrain,grassTexture1,2,1.0,1.0,nbTree,83,90);
00222 addTrees(terrain,grassTexture2,2,2.0,1.0,nbTree,83,96);
00223 addTrees(terrain,grassTexture4,2,1.0,1.0,nbTree,83,95);
00224 addTrees(terrain,treeTexture,3,1.2,1.2,nbTree/2,90,125);
00225 addTrees(terrain,treeTexture2,3,2.0,1.5,nbTree,83,120);
00226 addTrees(terrain,treeTexture3,3,1.0,1.3,nbTree/4,85,110);
00227 addTrees(terrain,treeTexture4,3,1.2,1.2,nbTree,83,110);
00228 }
00229
00230 std::cout << "Génération terminée." << std::endl;
00231 ok = true;
00232 }
00233
00234 void Terrain3D::RemplitPerc(float *perc, unsigned char haut)
00235 {
00236
00237 int add = haut + (rand()%30)-15;
00238
00239 if(add<0)
00240 add = 0;
00241
00242 if(add>255)
00243 add = 255;
00244
00245 haut = add;
00246
00247 if(haut<60)
00248 {
00249 perc[0] = 1.0f;
00250 perc[1] = 0.0f;
00251 perc[2] = 0.0f;
00252 perc[3] = 0.0f;
00253 }
00254
00255 else if(haut<80)
00256 {
00257 perc[0] = 1.0f - (haut-60.0f)/20.0f;
00258 perc[1] = (haut-60.0f)/20.0f;
00259 perc[2] = 0.0f;
00260 perc[3] = 0.0f;
00261 }
00262
00263 else if(haut<100)
00264 {
00265 perc[0] = 0.0f;
00266 perc[1] = 1.0f;
00267 perc[2] = 0.0f;
00268 perc[3] = 0.0f;
00269 }
00270
00271 else if(haut<150)
00272 {
00273 perc[0] = 0.0f;
00274 perc[1] = 1.0f - (haut-100.0f)/50.0f;
00275 perc[2] = (haut-100.0f)/50.0f;
00276 perc[3] = 0.0f;
00277 }
00278
00279 else if(haut<180)
00280 {
00281 perc[0] = 0.0f;
00282 perc[1] = 0.0f;
00283 perc[2] = 1.0f;
00284 perc[3] = 0.0f;
00285 }
00286
00287 else if(haut<220)
00288 {
00289 perc[0] = 0.0f;
00290 perc[1] = 0.0f;
00291 perc[2] = 1.0f - (haut-180.0f)/40.0f;
00292 perc[3] = (haut-180.0f)/40.0f;
00293 }
00294
00295 else
00296 {
00297 perc[0] = 0.0f;
00298 perc[1] = 0.0f;
00299 perc[2] = 0.0f;
00300 perc[3] = 1.0f;
00301 }
00302 }
00303
00304 unsigned char Terrain3D::GetPixelColor(SDL_Surface *image, int i, int j,int k)
00305 {
00306 Uint8 *p = (Uint8*)image->pixels + j * image->pitch + i * image->format->BytesPerPixel;
00307 unsigned char r, g, b;
00308 SDL_GetRGB(*(Uint32*)p,image->format,&r,&g,&b);
00309 switch(k)
00310 {
00311 case 0:
00312 return b;
00313 case 1:
00314 return g;
00315 case 2:
00316 return r;
00317 default:
00318 return 0;
00319 }
00320 }
00321
00322 void Terrain3D::SetPixel(SDL_Surface* Surface, int x, int y, Uint32 pixel)
00323 {
00324
00325 Uint8 *p = (Uint8*)Surface->pixels + y * Surface->pitch + x * Surface->format->BytesPerPixel;
00326
00327 switch(Surface->format->BytesPerPixel)
00328 {
00329 case 1:
00330 *p = pixel;
00331 break;
00332
00333 case 2:
00334 *(Uint16*)p = pixel;
00335 break;
00336
00337 case 3:
00338 if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
00339 {
00340 p[0] = (pixel >> 16) & 0xff;
00341 p[1] = (pixel >> 8) & 0xff;
00342 p[2] = pixel & 0xff;
00343 }
00344
00345 else
00346 {
00347 p[0] = pixel & 0xff;
00348 p[1] = (pixel >> 8) & 0xff;
00349 p[2] = (pixel >> 16) & 0xff;
00350 }
00351 break;
00352
00353 case 4:
00354 *(Uint32 *)p = pixel;
00355 break;
00356 }
00357 }
00358
00359 void Terrain3D::TextureHeightMap()
00360 {
00361
00362 osg::Texture2D* GrassTex = new osg::Texture2D;
00363 GrassTex->setDataVariance(osg::Object::DYNAMIC);
00364
00365 osg::Image* GrassImg = osgDB::readImageFile("Heightmap/TextTerrain.bmp");
00366 if (!GrassImg)
00367 {
00368 std::cout << "Texture non trouvée" << std::endl;
00369 ok = false;
00370 return;
00371 }
00372
00373
00374 GrassTex->setImage(GrassImg);
00375
00376
00377 osg::StateSet* stateGrass = new osg::StateSet();
00378
00379
00380
00381 stateGrass->setTextureAttributeAndModes(0,GrassTex,osg::StateAttribute::ON);
00382
00383
00384 osg::Light* Lumiere = new osg::Light();
00385 Lumiere->setPosition(osg::Vec4(0,0,50,1));
00386 Lumiere->setAmbient(osg::Vec4(220,220,220,1));
00387 Lumiere->setDirection(osg::Vec3(0,-0.25,-1));
00388 Lumiere->setDiffuse(osg::Vec4(0,120,120,1));
00389 stateGrass->setAttributeAndModes(Lumiere);
00390
00391 HeightMapGeode->setStateSet(stateGrass);
00392 }
00393
00394 bool Terrain3D::Ok()
00395 {
00396 return ok;
00397 }
00398
00399 osg::Geode* Terrain3D::getGeode()
00400 {
00401 return HeightMapGeode;
00402 }
00403
00408 void Terrain3D::addTrees(osg::Group* rootNode, osg::Texture2D* treeTexture, float scale,float width,float height, int number, float hmin, float hmax)
00409 {
00410
00411 osg::Billboard* shrubBillBoard = new osg::Billboard();
00412
00413 shrubBillBoard->setMode(osg::Billboard::AXIAL_ROT);
00414 shrubBillBoard->setAxis(osg::Vec3(0.0f,0.0f,1.0f));
00415 shrubBillBoard->setNormal(osg::Vec3(0.0f,-1.0f,0.0f));
00416
00417
00418 osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
00419 alphaFunc->setFunction(osg::AlphaFunc::GEQUAL,0.5f);
00420
00421 osg::StateSet* billBoardStateSet = new osg::StateSet;
00422
00423 billBoardStateSet->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
00424 billBoardStateSet->setTextureAttributeAndModes(0, treeTexture, osg::StateAttribute::ON );
00425 billBoardStateSet->setAttributeAndModes
00426 (new osg::BlendFunc, osg::StateAttribute::ON );
00427 osg::AlphaFunc* alphaFunction = new osg::AlphaFunc;
00428 alphaFunction->setFunction(osg::AlphaFunc::GEQUAL,0.05f);
00429 billBoardStateSet->setAttributeAndModes( alphaFunc, osg::StateAttribute::ON );
00430
00431 osg::Drawable* shrub1Drawable = createBillboardDrawable( scale, billBoardStateSet,width,height);
00432
00433
00434
00435 for(int i=0; i<(number); i++)
00436 {
00437 bool place = false;
00438 while(!place)
00439 {
00440 int c = rand()%HeightMap->getNumColumns();
00441 int r = rand()%HeightMap->getNumRows();
00442
00443 if((HeightMap->getHeight(c,r)>hmin) && (HeightMap->getHeight(c,r)<hmax) ||
00444 r<160 && c<220&& (HeightMap->getHeight(c,r)>hmin-18) && (HeightMap->getHeight(c,r)<hmax))
00445 {
00446 float x = HeightMap->getOrigin().x() + c * HeightMap->getXInterval();
00447 float y = HeightMap->getOrigin().y() + r * HeightMap->getYInterval();
00448 float z = HeightMap->getHeight(c,r);
00449 shrubBillBoard->addDrawable( shrub1Drawable , osg::Vec3(x,y,z) );
00450 place = true;
00451 }
00452 }
00453 }
00454
00455
00456 rootNode->addChild(shrubBillBoard);
00457
00458
00459 }
00460
00461 osg::Drawable* Terrain3D::createBillboardDrawable(float scale, osg::StateSet* bbState,float width,float height)
00462 {
00463
00464
00465
00466
00467
00468 width *= scale;
00469 height *= scale;
00470
00471
00472 osg::Geometry* shrubQuad = new osg::Geometry;
00473
00474
00475
00476 osg::Vec3Array* shrubVerts = new osg::Vec3Array(4);
00477 (*shrubVerts)[0] = osg::Vec3(-width/2.0f, 0, 0);
00478 (*shrubVerts)[1] = osg::Vec3( width/2.0f, 0, 0);
00479 (*shrubVerts)[2] = osg::Vec3( width/2.0f, 0, height);
00480 (*shrubVerts)[3] = osg::Vec3(-width/2.0f, 0, height);
00481 shrubQuad->setVertexArray(shrubVerts);
00482
00483
00484 osg::Vec2Array* shrubTexCoords = new osg::Vec2Array(4);
00485 (*shrubTexCoords)[0].set(0.0f,0.0f);
00486 (*shrubTexCoords)[1].set(1.0f,0.0f);
00487 (*shrubTexCoords)[2].set(1.0f,1.0f);
00488 (*shrubTexCoords)[3].set(0.0f,1.0f);
00489 shrubQuad->setTexCoordArray(0,shrubTexCoords);
00490
00491
00492 shrubQuad->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
00493
00494
00495 shrubQuad->setStateSet(bbState);
00496
00497 return shrubQuad;
00498 }