/** ******************************************************************************* @file /gui/model/TerrainEntity.cpp @brief Predek/reprezentace tereniho prvku(strom, kamen, ..) @author Vajicek+Pavel @version 0.1 ******************************************************************************/ #include "gui/model/TerrainEntity.h" // #include "gui/model/guimap.h" // vypnout varovani pri prekladu #pragma warning( disable : 4355 ) namespace gui{ /** generator pozice v hexu alternativa: double r = ((rand()%1000)*((sqrt3 / 2)*HEX_EDGE_LENGTH*0.9))/1000.5+0.1*HEX_EDGE_LENGTH; double baseang = (2*M_PI*(j+0.5f))/tc; double ang = ((rand()%1000)*M_PI)/1000/tc; so->moveTo((float)(r*cos(baseang+ang)), (float)(r*sin(baseang+ang)), 0); */ void randomHexPosition(float* x, float* y){ // float xc, yc; float f,pf; while(1){ // *x = RAND(-1,1); *y = RAND(-1,1); // pf = 0; for(int i = 0; i < 6; i++){ xc = cos((i+1)*(float)M_PI/3) - cos((i)*(float)M_PI/3); yc = sin((i+1)*(float)M_PI/3) - sin((i)*(float)M_PI/3); // f = yc*(*x - cos((i)*(float)M_PI/3))-xc*(*y - sin((i)*(float)M_PI/3)); if(pf*f < 0)break; //test na znamenko skal. soucinu pf=f; } if(pf*f > 0)return; } } /*TSceneTerreainObject**********************************************************************/ TSceneTerreainObject::TSceneTerreainObject(TModel *mid, TTerrainEntity* t, int positioning = POSITIONING_STAND_STRAIGHT|POSITIONING_ALIGN_TO_MINIMUM) :TModelSceneObject(mid),TSimpleShadow(this, RASTER_SHADOW) { iPositioning = positioning; fScale = RAND(0.9f, 1.1f); fRotation = RAND(0, 2*M_PI); terrain = t; } void TSceneTerreainObject::drawObject(){ if (getRealFade() < 3) drawShadow(); TModelSceneObject::drawObject(); } /*TerrainEntity*****************************************************************************/ TTerrainEntity::TTerrainEntity(TguiMap* m) :TProxyObject(m, ptTerrain) { } TTerrainEntity::~TTerrainEntity(){ for(Tsceneobjs::iterator it = objs.begin(); it != objs.end(); it++) { delete *it; } objs.clear(); } int TTerrainEntity::chooseRandom(TGUITerrainObjectInfo* tobjs, int tobjs_c){ float r = float(rand())/RAND_MAX; int i = 0; // while( tobjs[i].pvd < r ) i++; // return i; } int TTerrainEntity::addToHex(int newindex) { return 1; } void TTerrainEntity::setFade(int newfade) { Tsceneobjs::iterator it; it = objs.begin(); while(it != objs.end()) { (*it)->fade = newfade; it++; } } int TTerrainEntity::findClosestFreePosition(TSceneObject* scene_obj, P3F* orig_pos, P3F* free_pos) { float r = 0; float full_per = 0; float per = 0; float rad = SizeV2(scene_obj->aabbDim.p)/2; float ang; int col; P3F displacement = {0,0,0}; P3F orig_center; // CopyV3(orig_center.p, scene_obj->aabbCenter.p); //kolecko while(1) { //pozice na kruznicich if(per>full_per){ per = 0; r += rad; full_per = (float)M_PI*2*r; } // ang = (full_per)?(float)(2*M_PI*(per/full_per)):0; col = 0; per += rad; // displacement.x = r*sin(ang); displacement.y = r*cos(ang); // CopyV3(scene_obj->aabbCenter.p, orig_pos->p); AddV3(scene_obj->aabbCenter.p, displacement.p); map->altitude(scene_obj->aabbCenter.x, scene_obj->aabbCenter.y, &(scene_obj->aabbCenter.z)); //predmety v terenu for(Tsceneobjs::iterator it = objs.begin(); it != objs.end(); it++) { if((*it)->Collision(scene_obj)){ col = 1; break; } } //ukoncujici podminka if(!col) { CopyV3(free_pos->p, scene_obj->aabbCenter.p); break; } } CopyV3(scene_obj->aabbCenter.p, orig_center.p); return !col; } void TTerrainEntity::placeToHex(TSceneTerreainObject *obj, int newindex){ float x,y; P3F p3f; TGrad grad; float z; float zz[4]; //vysky rohu bounding boxu int collide = 1; int iteration = 0; while(collide && iterationsetPositionMX4(m); randomHexPosition(&x, &y); obj->moveTo(x*(HEX_EDGE_LENGTH), y*(HEX_EDGE_LENGTH), 0); //----- posad se na ni ----- //nastavit spravnou pozici map->hexCentre(&p3f, newindex); obj->moveBy(p3f.x, p3f.y, 0); obj->calculateAABB(); //spocita souradnici z if(obj->iPositioning & POSITIONING_ALIGN_TO_MINIMUM){ map->altitude(obj->aabbCenter.x-obj->aabbDim.x/2, obj->aabbCenter.y-obj->aabbDim.x/2,&zz[0]); map->altitude(obj->aabbCenter.x+obj->aabbDim.x/2, obj->aabbCenter.y-obj->aabbDim.x/2,&zz[1]); map->altitude(obj->aabbCenter.x+obj->aabbDim.x/2, obj->aabbCenter.y+obj->aabbDim.x/2,&zz[2]); map->altitude(obj->aabbCenter.x-obj->aabbDim.x/2, obj->aabbCenter.y+obj->aabbDim.x/2,&zz[3]); z = HIGH_NODE_HEIGHT; for(int i = 0; i < 4; i ++) if( z > zz[i] )z = zz[i]; } else if(obj->iPositioning & POSITIONING_ALIGN_TO_CENTER){ map->altitude(obj->aabbCenter.x, obj->aabbCenter.y, &z); } //nastaveni polohy if(obj->iPositioning & POSITIONING_LAY_ON_SURFACE){ map->getGradient(obj->aabbCenter.x, obj->aabbCenter.y, &grad); MX4 m; NormalizeV3(grad.dx.p); NormalizeV3(grad.dy.p); NormalizeV3(grad.dz.p); SetMX4(m, grad.dx.x, grad.dx.y, grad.dx.z, 0, grad.dy.x, grad.dy.y, grad.dy.z, 0, grad.dz.x, grad.dz.y, grad.dz.z, 0, obj->aabbCenter.x, obj->aabbCenter.y, z, 1); obj->setPositionMX4(m); } else if(obj->iPositioning & POSITIONING_STAND_STRAIGHT){ obj->moveBy(0, 0, z); } //pootoc a zvets o nahodnou hodnotu obj->uniformScale( obj->fScale ); obj->rotateBy( 0, 0, obj->fRotation ); //preinstaluj obj->calculateAABB(); //----- koliduj ----- collide = 0; for( Tsceneobjs::iterator it = objs.begin(); it != objs.end(); it++) { if( (*it)->Collision(obj) ) collide++; } iteration++; } } void TTerrainEntity::dump2D(FILE* f){ for(Tsceneobjs::iterator it = objs.begin(); it != objs.end(); it++) { P3F c = (*it)->aabbCenter; P3F d = (*it)->aabbDim; fprintf(f,"CircularObstacle\t%f\t%f\t%f\n", c.x, c.y, SizeV2(d.p)/2); } } void TTerrainEntity::initTerrains(){ //rm rm::TRM_model_i* mrm; if( !(mrm = (rm::TRM_model_i*) KSendGlobalMessage(MSG_GET_RM_MODEL_I,MOD_GUI,MOD_RM,NULL) ) ) THROW(E_8K_GUI, "TTerrainEntity::initTerrains(): failed to query rmmodel interface\n"); //inicializuj generatory terenu TTerrainForest::initForest(mrm); TTerrainDeepForest::initDeepForest(mrm); TTerrainRocks::initRocks(mrm); TTerrainSwamp::initSwamp(mrm); TTerrainTown::initTown(mrm); delete mrm; } void TTerrainEntity::freeTerrains(){ //zrus generatory terenu } /*TerrainForest*****************************************************************************/ TTerrainForest::TTerrainForest(TguiMap* m, int hx, int hy) :TTerrainEntity(m) { // TSceneTerreainObject *so; int tc = TTerrainForest::terrain_info.terrobj_count; // for (int j = 0; j < tc; j++){ // rozmisteni (casem to bude trochu prochytanejsi) int fo = chooseRandom(TTerrainForest::terrain_info.tobjs, TTerrainForest::terrain_info.tobjs_c); // so = new TSceneTerreainObject( TTerrainForest::terrain_info.tobjs[fo].mod, this, TTerrainForest::terrain_info.tobjs[fo].positioning); so->selectable = false; placeToHex(so, m->getHexIndex(hx,hy) ); // map->addObject(so); so->tag2 = TAG2_TERRAINLIKE; objs.push_back(so); } } void TTerrainForest::initForest(rm::TRM_model_i* mrm) { static TGUITerrainObjectInfo terrains[1]; TTerrainForest::terrain_info.tobjs = terrains; TTerrainForest::terrain_info.tobjs_c = 1; TTerrainForest::terrain_info.tobjs[0].mod = mrm->get(MODEL_TREE); TTerrainForest::terrain_info.tobjs[0].pvd = 1; TTerrainForest::terrain_info.tobjs[0].positioning = POSITIONING_STAND_STRAIGHT|POSITIONING_ALIGN_TO_CENTER; TTerrainForest::terrain_info.terrobj_count = 8; } TGUITerrainEntityInfo TTerrainForest::terrain_info; /******************************************************************************/ TTerrainDeepForest::TTerrainDeepForest(TguiMap* m, int hx, int hy) :TTerrainEntity(m) { // TSceneTerreainObject *so; int tc = TTerrainDeepForest::terrain_info.terrobj_count; // for (int j = 0; j < tc; j++){ // rozmisteni (casem to bude trochu prochytanejsi) int df = chooseRandom(TTerrainDeepForest::terrain_info.tobjs, TTerrainDeepForest::terrain_info.tobjs_c); // so = new TSceneTerreainObject( TTerrainDeepForest::terrain_info.tobjs[df].mod, this, TTerrainDeepForest::terrain_info.tobjs[df].positioning); so->selectable = false; placeToHex(so, m->getHexIndex(hx,hy) ); // map->addObject(so); so->tag2 = TAG2_TERRAINLIKE; objs.push_back(so); } } void TTerrainDeepForest::initDeepForest(rm::TRM_model_i* mrm) { static TGUITerrainObjectInfo terrains[3]; TTerrainDeepForest::terrain_info.tobjs = terrains; TTerrainDeepForest::terrain_info.tobjs_c = 3; TTerrainDeepForest::terrain_info.tobjs[0].mod = mrm->get(MODEL_TREE); TTerrainDeepForest::terrain_info.tobjs[0].pvd = 0.2f; TTerrainDeepForest::terrain_info.tobjs[0].positioning = POSITIONING_LAY_ON_SURFACE|POSITIONING_ALIGN_TO_CENTER; TTerrainDeepForest::terrain_info.tobjs[1].mod = mrm->get(MODEL_TREE3); TTerrainDeepForest::terrain_info.tobjs[1].pvd = 0.7f; TTerrainDeepForest::terrain_info.tobjs[1].positioning = POSITIONING_STAND_STRAIGHT|POSITIONING_ALIGN_TO_CENTER; TTerrainDeepForest::terrain_info.tobjs[2].mod = mrm->get(MODEL_TREE4); TTerrainDeepForest::terrain_info.tobjs[2].pvd = 1; TTerrainDeepForest::terrain_info.tobjs[2].positioning = POSITIONING_STAND_STRAIGHT|POSITIONING_ALIGN_TO_MINIMUM; TTerrainDeepForest::terrain_info.terrobj_count = 8; } TGUITerrainEntityInfo TTerrainDeepForest::terrain_info; /*****************************************************************************/ TTerrainRocks::TTerrainRocks(TguiMap* m, int hx, int hy) :TTerrainEntity(m) { // TSceneTerreainObject *so; int tc = TTerrainRocks::terrain_info.terrobj_count; // for (int j = 0; j < tc; j++){ // rozmisteni (casem to bude trochu prochytanejsi) int ro = chooseRandom(TTerrainRocks::terrain_info.tobjs, TTerrainRocks::terrain_info.tobjs_c); // so = new TSceneTerreainObject( TTerrainRocks::terrain_info.tobjs[ro].mod, this, TTerrainRocks::terrain_info.tobjs[ro].positioning); so->selectable = false; placeToHex(so, m->getHexIndex(hx,hy) ); // map->addObject(so); so->tag2 = TAG2_TERRAINLIKE; objs.push_back(so); } } void TTerrainRocks::initRocks(rm::TRM_model_i* mrm){ static TGUITerrainObjectInfo terrains[3]; TTerrainRocks::terrain_info.tobjs = terrains; TTerrainRocks::terrain_info.tobjs_c = 3; TTerrainRocks::terrain_info.tobjs[0].mod = mrm->get(MODEL_ROCK1); TTerrainRocks::terrain_info.tobjs[0].pvd = 0.3f; TTerrainRocks::terrain_info.tobjs[0].positioning = POSITIONING_ALIGN_TO_MINIMUM|POSITIONING_STAND_STRAIGHT; TTerrainRocks::terrain_info.tobjs[1].mod = mrm->get(MODEL_ROCK2); TTerrainRocks::terrain_info.tobjs[1].pvd = 0.6f; TTerrainRocks::terrain_info.tobjs[1].positioning = POSITIONING_ALIGN_TO_MINIMUM|POSITIONING_STAND_STRAIGHT; TTerrainRocks::terrain_info.tobjs[2].mod = mrm->get(MODEL_ROCK3); TTerrainRocks::terrain_info.tobjs[2].pvd = 1; TTerrainRocks::terrain_info.tobjs[2].positioning = POSITIONING_ALIGN_TO_MINIMUM|POSITIONING_STAND_STRAIGHT; TTerrainRocks::terrain_info.terrobj_count = 2; } TGUITerrainEntityInfo TTerrainRocks::terrain_info; /*****************************************************************************/ TTerrainSwamp::TTerrainSwamp(TguiMap* m, int hx, int hy) :TTerrainEntity(m) { // TSceneTerreainObject *so; int tc = TTerrainSwamp::terrain_info.terrobj_count; // for (int j = 0; j < tc; j++){ // rozmisteni (casem to bude trochu prochytanejsi) int sw = chooseRandom(TTerrainSwamp::terrain_info.tobjs, TTerrainSwamp::terrain_info.tobjs_c); // so = new TSceneTerreainObject( TTerrainSwamp::terrain_info.tobjs[sw].mod, this, TTerrainSwamp::terrain_info.tobjs[sw].positioning); so->selectable = false; placeToHex(so, m->getHexIndex(hx,hy) ); // map->addObject(so); so->tag2 = TAG2_TERRAINLIKE; objs.push_back(so); } } void TTerrainSwamp::initSwamp(rm::TRM_model_i* mrm){ static TGUITerrainObjectInfo terrains[3]; TTerrainSwamp::terrain_info.tobjs = terrains; TTerrainSwamp::terrain_info.tobjs_c = 3; TTerrainSwamp::terrain_info.tobjs[0].mod = mrm->get(MODEL_FERN1); TTerrainSwamp::terrain_info.tobjs[0].pvd = 0.4f; TTerrainSwamp::terrain_info.tobjs[0].positioning = POSITIONING_ALIGN_TO_MINIMUM|POSITIONING_LAY_ON_SURFACE; TTerrainSwamp::terrain_info.tobjs[1].mod = mrm->get(MODEL_TREE4); TTerrainSwamp::terrain_info.tobjs[1].pvd = 0.65f; TTerrainSwamp::terrain_info.tobjs[1].positioning = POSITIONING_ALIGN_TO_MINIMUM|POSITIONING_STAND_STRAIGHT; TTerrainSwamp::terrain_info.tobjs[2].mod = mrm->get(MODEL_ROCK3); TTerrainSwamp::terrain_info.tobjs[2].pvd = 1; TTerrainSwamp::terrain_info.tobjs[2].positioning = POSITIONING_ALIGN_TO_MINIMUM|POSITIONING_STAND_STRAIGHT; TTerrainSwamp::terrain_info.terrobj_count = 4; } TGUITerrainEntityInfo TTerrainSwamp::terrain_info; /*****************************************************************************/ void TTownObject::drawObject(){ // int i = ((TTerrainTown*)terrain)->iOwner; float mat[] = {ColorPlayer[ i ][0]/255.0f, ColorPlayer[ i ][1]/255.0f, ColorPlayer[ i ][2]/255.0f, 1}; // glMaterialfv(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE, mat); TSceneTerreainObject::drawObject(); } TTownObject::TTownObject(TModel *mid, TTerrainEntity* t, int positioning) :TSceneTerreainObject(mid, t, positioning) { } /*****************************************************************************/ TTerrainTown::TTerrainTown(TguiMap* m, int hx, int hy) :TTerrainEntity(m) { //vlastnik mesta int hid = map->getHexIndex(hx, hy); iOwner = map->getTownHexOwner( hid ); // TSceneTerreainObject *so; int tc = TTerrainTown::terrain_info.terrobj_count; // for (int j = 0; j < tc; j++){ //vyber nahodny objekt int tb = chooseRandom(TTerrainTown::terrain_info.tobjs, TTerrainTown::terrain_info.tobjs_c); // so = new TTownObject( TTerrainTown::terrain_info.tobjs[tb].mod, this, TTerrainTown::terrain_info.tobjs[tb].positioning); so->selectable = false; placeToHex(so, m->getHexIndex(hx,hy) ); // map->addObject(so); so->tag2 = TAG2_TERRAINLIKE; objs.push_back(so); } } void TTerrainTown::initTown(rm::TRM_model_i* mrm){ static TGUITerrainObjectInfo terrains[2]; TTerrainTown::terrain_info.tobjs = terrains; TTerrainTown::terrain_info.tobjs_c = 2; TTerrainTown::terrain_info.tobjs[0].mod = mrm->get(MODEL_HOUSE1); TTerrainTown::terrain_info.tobjs[0].pvd = 0.5f; TTerrainTown::terrain_info.tobjs[0].positioning = POSITIONING_ALIGN_TO_MINIMUM|POSITIONING_STAND_STRAIGHT; TTerrainTown::terrain_info.tobjs[1].mod = mrm->get(MODEL_HOUSE2); TTerrainTown::terrain_info.tobjs[1].pvd = 1; TTerrainTown::terrain_info.tobjs[1].positioning = POSITIONING_ALIGN_TO_MINIMUM|POSITIONING_STAND_STRAIGHT; TTerrainTown::terrain_info.terrobj_count = 3; } TGUITerrainEntityInfo TTerrainTown::terrain_info; }//namespace /*****************************************************************************/