/** ******************************************************************************* @file /gui/model/mapnet.cpp @brief Mapa @author Pavel @version 0.1 ******************************************************************************/ #include "gui/model/mapnet.h" #include "gui/common/Defs.h" #include "gui/engine/TextureManager.h" #include "common/Log.h" #include "common/exc.h" #include "gui/common/mymath.h" #include "gui/GUI.h" using namespace World; namespace gui{ // o kolik je NIZINA vys nez MORE... #define ZMENA_VYSKY 150.0f // jak hodne je teren nahodne zvlnen #define SUM 2.0f // LOD pro hexy, #define n2 4 // delka hrany hexu #define DX HEX_EDGE_LENGTH // tex.u = pos.x*TEXTURE_X_CORECTION #define TEXTURE_X_CORECTION (1.0f/(3.0f*DX)) // tex.v = pos.z*TEXTURE_X_CORECTION #define TEXTURE_Y_CORECTION (1.0f/(2*sqrt3*DX)) #define bod(x,y) (vert[(y)*bodX+(x)].position) #define norm(x,y) (vert[(y)*bodX+(x)].normal) // pro vypocet splineu #define ridic(u,v) RidiciBod[(u)+(v)*4] // parametry hexu #define VYSKAHEXU(j, i) map.hexes[ (i) * map.width + (j) ]->elevation #define TYPTERENU(j, i) map.hexes[ (i) * map.width + (j) ]->terrain /// matice koeficientu pro spline plochy MX4 MXKoef = { -1, 3, -3, 1, 3, -6, 3, 0, -3, 0, 3, 0, 1, 4, 1, 0}; ///transponovana matice koeficientu MX4 MXKoefT; /// spocita normalu plochy dane body A,B,C void upnormala(P3F *N, P3F *A, P3F *B, P3F *C) { P3F u,v; // u = (B-A) CopyV3(u.p, B->p); SubV3(u.p, A->p); // v = (C-A) CopyV3(v.p, C->p); SubV3(v.p,A->p); // N = (u x v) / |u x v| VectMulV3(N->p,u.p,v.p); NormalizeV3(N->p); if (N->z < 0) MulV3(N->p,-1); } void NET::done() { KMemFree(terrained); KMemFree(vert); KMemFree(owner); } void NET::neighbour(int *ni, int *nj, int i, int j, TNeighbour dir) { *ni = i; *nj = j; switch (dir) { case tn_up: *ni -= 2; break; case tn_down: *ni += 2; break; case tn_leftup: *ni -= 1; if ( odd(i) ) *nj -= 1; break; case tn_leftdown: *ni += 1; if ( odd(i) ) *nj -= 1; break; case tn_rightup: if ( !odd(i) ) *nj += 1; *ni -= 1; break; case tn_rightdown: if ( !odd(i) ) *nj += 1; *ni += 1; break; } INDEX2D ind2 = korekt(*ni, *nj); *ni = ind2.y; *nj = ind2.x; } int NET::chooseTextureBitmap(TERRAIN_TYPE me, TERRAIN_TYPE neighbour) { switch (me){ case TT_ROCKS: switch (neighbour){ case TT_ROCKS: return RASTER_ROCK; case TT_SWAMP: return RASTER_ROCKSWAMP; default: return RASTER_ROCKGRASS; } case TT_SWAMP: switch (neighbour){ case TT_ROCKS: return RASTER_SWAMPROCK; case TT_SWAMP: return RASTER_SWAMP; default: return RASTER_SWAMPGRASS; } default: switch (neighbour){ case TT_ROCKS: return RASTER_GRASSROCK; case TT_SWAMP: return RASTER_GRASSSWAMP; default: return RASTER_GRASS; } } } INDEX2D NET::korekt(int i, int j) { INDEX2D k; while (i < 0) i += 2; while (i >= maxY) i -= 2; if (j < 0) { j = 0; i -= 1; } if (j >= maxX){ j = maxX - 1; i -= 1; } while (i < 0) i += 2; while (i >= maxY) i -= 2; k.x = j; k.y = i; return k; } /* vrati souradnice stredu daneho hexu */ INDEX2D NET::middle(int i, int j) { INDEX2D s; s.y = n2 * (i + 1); if ( odd(i) ) s.x = (1 + 3 * j) * n2; else s.x = (2 + 3 * j) * n2; return s; } void NET::splineBuild() { static MX4 MXtemp; MulMatrixMX4(MXtemp, MXKoef, RidiciBod); MulMatrixMX4(MXQ, MXtemp, MXKoefT); for (int i = 0; i < 16; i++) MXQ[i] *= 1.0f/36; } float NET::splineAltitude(float u, float v) { static V4F U, V, W; // U = (u^3, u^2, u, 1) SETV4(U, (u*u*u), (u*u), u, 1); // V = (v^3, v^2, v, 1) SETV4(V, (v*v*v), (v*v), v, 1); // return U * MXQ * V ApplyVectorMX4(U, MXQ, W); return ScalMulV4(W, V); } void NET::applyLevel() { float sx, sy; int x, y; sx = -dx / 2; sy = -dy; // nejdriv se spocita nezvlnena sit for (y = 0; y < bodY; y++) { sx = dx / 2 - ( abs( y % (n2 * 2) - n2) * (ddx / 2) ); for (x = 0; x < bodX; x++) { // souradnice vrcholu site bod(x, y).x = sx + x * ddx; bod(x, y).y = y * ddy; bod(x, y).z = 0.0; // texturovaci souradnice vert[x + bodX * y].texture.x = (bod(x,y).x) * (float)TEXTURE_X_CORECTION; vert[x + bodX * y].texture.y = (bod(x,y).y) * (float)TEXTURE_Y_CORECTION; // barva vert[x + bodX * y].color = 0xE0E0E0; } } // z-ove souradnice INDEX2D ind2d; for (int i = -1; i <= maxY; i++) for (int j = -1; j < maxX; j++) { int u, v; // urcim 16 ridicich bodu pro spline plochu for (u = 0; u < 4; u++) for (v = 0; v < 4; v++) { // na okraji mapy se nektere ridici body pouziji vicekrat ind2d = korekt(i + u - v, j + (u + v + 1 - odd(i) ) / 2 - 1); ridic(u,v) = VYSKAHEXU(ind2d.x, ind2d.y) * ZMENA_VYSKY; } // sestavi matici plochy pro rychlejsi vypocet splineBuild(); ind2d = middle(i - 1, j + 1 - odd(i) ); int basex = ind2d.x; int basey = ind2d.y; int absx, absy; int rowlength = 1; for (y = 0; y <= 2 * n2; y++){ for (x = 0; x < rowlength; x++){ absx = x + basex; absy = y + basey; if ( (absx >= 0) && (absy >= 0) && (absx < bodX) && (absy < bodY) ) { float X = x + abs(n2 - y) * 1.5f; float Y = (float)n2 - y; // nahodne posunuti o hodnotu z intervalu (-SUM, SUM) float randomAlt = (1 - (rand() % 100) * 0.02f) * SUM; // parametry bodu [absx, absy] na aktualni plose float u = (1.0f / ( 6 * n2 ) ) * (2.0f * X + 3.0f * Y); float v = (1.0f / ( 6 * n2 ) ) * (2.0f * X - 3.0f * Y); // z-ova souradnice = aproximace splineem + nahodne posunuti bod(absx, absy).z = splineAltitude(u, v) + randomAlt; } } // for x if (y < n2) { rowlength += 3; basex -= (2-odd(i)); } else { rowlength -= 3; basex += ( 2 - odd(i) ); } } // for y } // for j } #define DEPTH_RIVER (HEX_EDGE_LENGTH/2) #define DEPTH_SHALLOW (DEPTH_RIVER/3) #define DEPTH_SEA DEPTH_RIVER #define SHORE_HEIGHT (DEPTH_RIVER/4) #define SHOREF(x) cos(x) float NET::pitchDepth(int i, int j) { switch (map.hexes[i * maxX + j]->terrain) { case TT_RIVER: return DEPTH_RIVER; case TT_SHALLOW: return DEPTH_SHALLOW; case TT_SEA: return DEPTH_SEA; default: return 0; } } void NET::pitch(int i, int j) { int x, y, k; int ni, nj; // hloubka aktualniho hexu float MyDepth = pitchDepth(i, j); // stred hexu posoupnu o MyDepth dolu INDEX2D mid = middle(i, j); vert[mid.x + mid.y * bodX].position.z -= MyDepth; // kazdou sestinu hexu pocitam zvlast for (k = 0; k < 6; k++){ // hloubka k-teho sousedniho hexu neighbour(&ni, &nj, i, j, (TNeighbour)k ); float DirDepth = pitchDepth(ni, nj); // hloubka sousedniho hexu leveho vzhledem ke k-temu sousedovi neighbour(&ni, &nj, i, j, (TNeighbour)( (k + 5) % 6 ) ); float LeftDepth = pitchDepth(ni, nj); // hloubka sousedniho hexu praveho vzhledem ke k-temu sousedovi neighbour(&ni, &nj, i, j, (TNeighbour)( (k + 1) % 6 ) ); float RightDepth = pitchDepth(ni, nj); // pokud k-soused je melci (nebo breh) if (DirDepth > MyDepth) DirDepth = MyDepth; if (LeftDepth > DirDepth) LeftDepth = DirDepth; if (RightDepth > DirDepth) RightDepth = DirDepth; for (y = 1; y <= n2; y++) { // interpolace hloubky v zavislosti na vzdalenosti od stredu float argy = y / (float)n2 * (float)M_PI / 2; float LeftDepthY = SHOREF(argy) * (MyDepth - LeftDepth) + LeftDepth; float RightDepthY = SHOREF(argy) * (MyDepth - RightDepth) + RightDepth; float DirDepthY = SHOREF(argy) * (MyDepth - DirDepth) + DirDepth; for (x = 1; x <= y; x++) { int bx, by; bx = by = 0; // spocitam souradnice vrcholu, jehoz z-ovou souradnici budu posunovat switch ((TNeighbour)k){ case tn_up: by = -y; bx = x - y * odd(i); break; case tn_rightup: bx = y + odd(i) * (x - y); by = x - y; break; case tn_rightdown: bx = y - odd(i) * x; by = x; break; case tn_down: by = y; bx = -x + (1 - odd(i)) * y; break; case tn_leftdown: bx = -x + odd(i) * (x - y); by = y - x; break; case tn_leftup: bx = -y + x * (1 - odd(i) ); by = -x; break; } int index = (bx + mid.x) + (by + mid.y) * bodX; if (!terrained[index]) { float argx = (2 * x - y) / (float)y * (float)M_PI / 2; float adepth; if (argx < 0) adepth = LeftDepthY + SHOREF(argx) * (DirDepthY - LeftDepthY); else adepth = RightDepthY + SHOREF(argx) * (DirDepthY - RightDepthY); vert[index].position.z -= adepth; terrained[index] = true; } } // for (x... } // for (y... } // for (k... } void NET::applyTeren() { int i, j, index; for (i = 0; i < maxY; i++) for (j = 0; j < maxX; j++) { index = i * maxX + j; switch (map.hexes[index]->terrain){ case TT_RIVER: case TT_SHALLOW: case TT_SEA: pitch(i, j); break; } } } void NET::compNormals() { // spocitam normaly ve vrcholech P3F v, u; int x, y; for (int y2 = 0; y2 < bodY; y2++) for (int x2 = 0; x2 < bodX; x2++) { x = x2; y = y2; // na krajich se pouziji sousedni normaly if (x2 == 0) x++; if (x2 == bodX - 1) x--; if (y2 == 0) y++; if (y2==bodY-1) y--; // normala ve vrcholu = suma normal v prilehlych trojuhelnicich SETV3(u.p,0,0,0); int lichy = ( (y-1) / n2 ) % 2; if (!lichy){ upnormala(&v, &bod(x, y), &bod(x -1, y), &bod(x, y - 1)); AddV3(u.p, v.p); upnormala(&v, &bod(x, y), &bod(x, y - 1), &bod(x + 1,y - 1)); AddV3(u.p, v.p); upnormala(&v, &bod(x, y), &bod(x + 1, y - 1), &bod(x + 1, y)); AddV3(u.p, v.p); } else { upnormala(&v, &bod(x, y), &bod(x - 1, y), &bod(x - 1, y - 1)); AddV3(u.p, v.p); upnormala(&v, &bod(x, y), &bod(x - 1, y - 1),&bod(x, y - 1)); AddV3(u.p, v.p); upnormala(&v, &bod(x, y), &bod(x, y - 1),&bod(x + 1, y)); AddV3(u.p, v.p); } lichy = (y / n2) % 2; if (!lichy){ upnormala(&v, &bod(x, y), &bod(x + 1, y), &bod(x, y + 1)); AddV3(u.p, v.p); upnormala(&v, &bod(x, y), &bod(x, y + 1), &bod(x - 1, y + 1)); AddV3(u.p, v.p); upnormala(&v, &bod(x, y), &bod(x - 1, y + 1), &bod(x - 1, y)); AddV3(u.p, v.p); } else { upnormala(&v, &bod(x, y), &bod(x + 1, y), &bod(x + 1, y + 1)); AddV3(u.p, v.p); upnormala(&v, &bod(x, y), &bod(x + 1, y + 1), &bod(x, y + 1)); AddV3(u.p, v.p); upnormala(&v, &bod(x, y), &bod(x, y + 1), &bod(x - 1, y)); AddV3(u.p, v.p); } NormalizeV3(u.p); CopyV3(norm(x2,y2).p, u.p); } } int NET::triangle(float x, float y, int *A, int *B, int *C) { // y-ova souradnice bodu site tesne nad y int ya = (int)(y / ddy); // relativni vzdalenost ve smeru y od zacatku hexu float ry = y - (ya / n2) * dy; if (ya % (n2 * 2) < n2) ry = dy - ry; // malounko upravena x-ova souradnice float rx = x - (dx / 2) * (dy - ry) / dy; // x-ova souradnice bodu site tesne pred x int xa = (int)(rx / ddx); if ( (rx < 0) || (xa + 1 >= bodX) || (y < 0) || (ya + 1 >= bodY) ) return 0; if (ya % (n2 * 2) < n2) { *A = ya * bodX + (xa + 1); *B = (ya + 1) * bodX + xa; if (ddx * ddy - ddx * (y - ddy * ya) > ddy * (rx - ddx * xa) ) *C = *A - 1; else *C = *B + 1; } else { *A = ya * bodX + xa; *B = (ya + 1) * bodX + (xa + 1); if (ddx * (y - ddy * ya) > ddy * (rx - ddx * xa)) *C = *B - 1; else *C = *A + 1; } if ( (owner[*A] == OWNER_NOONE) || (owner[*B] == OWNER_NOONE) || (owner[*C] == OWNER_NOONE) ) return 0; return 1; } void NET::init(World::MAP _map) { // map.height = _map.height; map.width = _map.width; map.hexes = _map.hexes; // maxX=map.width; maxY=map.height; // pocty skutecnych vrcholu site bodX = 3 * n2 * maxX + 1; bodY = n2 * (maxY + 1) + 1; dx = DX; // pri zvolenem zobrazeni polovina sirky hexu dy = ((float)sqrt3 / 2)*dx; // pri zvolenem zobrazeni polovina vysky hexu ddx = dx / n2; // delka zakladny jednoho trojuhelnicku ddy = dy / n2; // vyska jednoho trojuhelnicku vert = (TVertex *)KMemAlloc(sizeof(TVertex)* bodX * bodY); owner = (int *)KMemAlloc(sizeof(int) * bodX * bodY); terrained = (bool *)KMemAlloc(sizeof(bool) * bodX * bodY); for (int i = 0; i < bodX * bodY; i++) { owner[i] = OWNER_NOONE; terrained[i] = false; } // transponovana matice pro vypocet splineu ConvMX(MXKoefT, MXKoef); dvenan = n2; } #define TRIANGLES_IN_TRIANGLE 16 #define TRIANGLES_IN_HEX (TRIANGLES_IN_TRIANGLE*6) int addBasicTextureMaterial(TModel *model, int bid, bool border = false) { static char stemp[20]; sprintf(stemp, "%d", bid); int position = 0; for(std::vector::iterator it = model->matr.begin(); it != model->matr.end(); it++) { if ( strcmp(stemp, (*it)->name) == 0) return position; position++; } TMaterial *material = model->addMaterialToModel(); strcpy(material->name, stemp); /* if (border) { SETP3(material->ambient, 1.0f, 1.0f, 1.0f); SETP3(material->diffuse, 0.5f, 0.5f, 1.0f); SETP3(material->specular, 0.5f, 0.5f, 1.0f); } else */{ SETP4(material->ambient, 1.0f, 1.0f, 1.0f, 1); SETP4(material->diffuse, 1.0f, 1.0f, 1.0f, 1); SETP4(material->specular, 1.0f, 1.0f, 1.0f, 1); } material->shininess = 0.1f; material->transparency = 0; material->mmap_c = 0; material->mmap = 0; TMaterialMap *matmap = AddMaterialMapToMaterial(material); matmap->bitmap_file = KInitString("FAKE"); TTextureManager::tm->loadTextureQuery((int)bid, &(matmap->id)); matmap->uvw_angle = 0; matmap->uvw_u_offset = 0; matmap->uvw_v_offset = 0; matmap->uvw_u_tiling = 1; matmap->uvw_v_tiling = 1; return (int)model->matr.size() - 1; } P3DObject addBasicHexGeometry(TModel *model, int mesh_count, int triangles_count) { P3DObject obj = model->addGeometry(); obj->mesh_c = mesh_count; obj->mesh = (TMesh *)KMemAlloc(sizeof(TMesh) * obj->mesh_c); obj->poly_c = triangles_count; obj->poly = (TPolygon *)KMemAlloc(sizeof(TPolygon) *obj->poly_c); obj->vert_c = 3 * obj->poly_c; obj->vert = (TVertex *)KMemAlloc(sizeof(TVertex) * obj->vert_c); return obj; } PMeshNode addBasicMeshNode(TModel *model, P3DObject obj, int mesh_number, char *name, int firsttriangle, int lasttriangle, int mat) { PMeshNode mesh_nod = model->addMeshNodToModel(NULL); strcpy(mesh_nod->name, name); mesh_nod->childs = NULL; mesh_nod->childs_c = 0; mesh_nod->parent = NULL; mesh_nod->mesh = mesh_number; mesh_nod->obj = obj; SETP3(mesh_nod->glob_scale, 1, 1, 1); SetIdentityMX4(mesh_nod->global); mesh_nod->initial_rotate.ang = 0; SETP3(mesh_nod->initial_rotate.ax, 0, 0, 1); SETP3(mesh_nod->initial_scale, 1, 1, 1); SETP3(mesh_nod->initial_translate, 0, 0, 0); SETP3(mesh_nod->rotate.ax, 0, 0, 1); SETP3(mesh_nod->scale, 1, 1, 1); SETP3(mesh_nod->translate, 0, 0, 0); mesh_nod->rotate.ang = 0; obj->mesh[mesh_number].first=firsttriangle; obj->mesh[mesh_number].last=lasttriangle; obj->mesh[mesh_number].iFlag=1; obj->mesh[mesh_number].mat=mat; obj->mesh[mesh_number].obj=obj; obj->mesh[mesh_number].display_list=-1; return mesh_nod; } void NET::modelCompVertices(P3DObject obj, int i, int j, TNeighbour part, int firsttriangle) { int x, y; // index prave zpracovavaneho vertexu int vind; // index prave zpracovavaneho polygonu int polyind; // souradnice leveho horniho rohu hexu [j,i] int basex, basey; // indikator, zda se jedna o jeden ze spodnich trojuhelniku hexu int isdown; // korekce x-ove souradnice pri prechodu na novy radek int basex_correct; // if ( (part == tn_down) || (part == tn_leftdown) || (part == tn_rightdown) ) isdown = 1; else isdown = 0; basey = n2 * i; if (isdown) basey += n2; if ( odd(i) ) basex = (3 * j) * n2; else basex=( 2 + 3 * j) * n2; if ( odd( i + isdown ) ) basex_correct = 1; else basex_correct = 0; if (part == tn_rightup) basex += n2; if ( (part == tn_rightdown) || (part == tn_down) ) basex += odd(i)*n2; if ( (part == tn_leftdown) && (!odd(i)) ) basex -= n2; polyind = firsttriangle; switch (part){ case tn_up: case tn_leftdown: case tn_rightdown: for (y = 0; y < n2; y++){ for (x = 0; x < n2 - y; x++) { vind = (basey + y) * bodX + (basex + x); if (y > 0){ // trojuhelniky smerujici nahoru bod2vertex(&obj->vert[3 * polyind + 2], vind); bod2vertex(&obj->vert[3 * polyind + 1], vind + 1); bod2vertex(&obj->vert[3 * polyind + 0], vind - bodX + 1 - basex_correct); // preskocim na dalsi trojuhelnik polyind++; } // trojuhelniky smerujici dolu bod2vertex(&obj->vert[3 * polyind + 0], vind); bod2vertex(&obj->vert[3 * polyind + 1], vind + 1); bod2vertex(&obj->vert[3 * polyind + 2], vind + bodX + basex_correct); // preskocim na dalsi trojuhelnik polyind++; } basex += basex_correct; } break; case tn_down: case tn_leftup: case tn_rightup: basex = basex -1 + basex_correct; for (y = 1; y < n2 + 1; y++){ for (x = 0; x < y; x++) { vind = (basey + y) * bodX + (basex + x); // trojuhelniky smerujici nahoru bod2vertex(&obj->vert[3 * polyind + 2], vind); bod2vertex(&obj->vert[3 * polyind + 1], vind + 1); bod2vertex(&obj->vert[3 * polyind + 0], vind - bodX + 1 - basex_correct); // preskocim na dalsi trojuhelnik polyind++; if (y < n2) { // trojuhelniky smerujici dolu bod2vertex(&obj->vert[3 * polyind + 0], vind); bod2vertex(&obj->vert[3 * polyind + 1], vind + 1); bod2vertex(&obj->vert[3 * polyind + 2], vind + bodX + basex_correct); // preskocim na dalsi trojuhelnik polyind++; } } basex = basex -1 + basex_correct; } break; } /* naplnim pole polygonu */ for (polyind = firsttriangle; polyind < firsttriangle + TRIANGLES_IN_TRIANGLE; polyind++){ obj->poly[polyind].first=3*polyind; obj->poly[polyind].last=3*polyind+2; obj->poly[polyind].lmap_id=0; obj->poly[polyind].mesh=obj->mesh; obj->poly[polyind].submat=0; obj->poly[polyind].udata=0; } } void NET::compOwners(int i, int j) { int basex, basey, rowlength, vind, basex_correct; int x, y; basey = n2 * i; if ( odd(i) ) basex_correct = 0; else basex_correct = 1; /* u bodu site do kterych tento hex zasahuje to zapisi */ if ( odd(i) ) basex = (3 * j) * n2; else basex = (2 + 3*j) * n2; rowlength = n2 + 1; for (y = 0; y < 2 * n2 + 1; y++ ) { for ( x = 0; x < rowlength; x++ ) { vind = (basey + y) * bodX + (basex + x); if (owner[vind] == OWNER_NOONE) owner[vind] = i * maxX + j; else owner[vind] = OWNER_MORE; } if (y < n2) { rowlength++; basex -= basex_correct; } else { rowlength--; basex += basex_correct; } } } #define ISNOTINBORDER(i, j) ( (i >= MAP_BOUND_Y) && (j >= MAP_BOUND_X) && (i < maxY - MAP_BOUND_Y) && (j < maxX - MAP_BOUND_X) ) TModel *NET::model(int i, int j) { // model bez LODu, s hierarchii TModel *model = new TModel(0, 1); // geometrie s danym poctem vrcholu a trojuhelniku P3DObject obj = addBasicHexGeometry(model, 6, TRIANGLES_IN_HEX); modelCompVertices(obj, i, j, tn_up, 0); modelCompVertices(obj, i, j, tn_rightup, TRIANGLES_IN_TRIANGLE); modelCompVertices(obj, i, j, tn_rightdown, TRIANGLES_IN_TRIANGLE*2); modelCompVertices(obj, i, j, tn_down, TRIANGLES_IN_TRIANGLE*3); modelCompVertices(obj, i, j, tn_leftdown, TRIANGLES_IN_TRIANGLE*4); modelCompVertices(obj, i, j, tn_leftup, TRIANGLES_IN_TRIANGLE*5); int ni, nj; int bid; int intmat; // plocha char stemp[20]; for (int k = 0; k < 6; k++){ neighbour(&ni, &nj, i, j, (TNeighbour)k ); bid = chooseTextureBitmap( TYPTERENU(j, i), TYPTERENU(nj, ni) ); sprintf(stemp, "Plane0%d", k); intmat = addBasicTextureMaterial(model, bid, !ISNOTINBORDER(i, j)); PMeshNode mesh_nod = addBasicMeshNode(model, obj, k, stemp, k * TRIANGLES_IN_TRIANGLE, (k + 1) * TRIANGLES_IN_TRIANGLE - 1, intmat); } compOwners(i, j); return model; } TModel *NET::waterModel(int i, int j) { int index = i * maxX + j; // pokud na hexu neni voda tak nic nevyrabim switch (map.hexes[index]->terrain){ case TT_SEA: case TT_RIVER: case TT_SHALLOW: break; default: return NULL; } // model bez LODu, s hierarchii TModel *model = new TModel(0, 1); // geometrie s danym poctem vrcholu a trojuhelniku P3DObject obj = addBasicHexGeometry(model, 1, 6); // index bodu uprostred hexu INDEX2D ind2d = middle(i, j); int mind = ind2d.x + ind2d.y * bodX; int lichy = odd(i); // horni bod2vertex(&obj->vert[0], mind); bod2vertex(&obj->vert[1], mind - (bodX * n2) - n2 * lichy); bod2vertex(&obj->vert[2], mind - (bodX * n2) - n2 * lichy + n2); // dolni bod2vertex(&obj->vert[5], mind); bod2vertex(&obj->vert[4], mind + (bodX * n2) - n2 * lichy); bod2vertex(&obj->vert[3], mind + (bodX * n2) - n2 * lichy + n2); // levy horni bod2vertex(&obj->vert[6], mind); bod2vertex(&obj->vert[7], mind - n2); bod2vertex(&obj->vert[8], mind - (bodX * n2) - n2 * lichy); // pravy dolni bod2vertex(&obj->vert[11], mind); bod2vertex(&obj->vert[10], mind + (bodX * n2) - n2 * lichy + n2); bod2vertex(&obj->vert[9], mind + n2); // levy dolni bod2vertex(&obj->vert[14], mind); bod2vertex(&obj->vert[13], mind - n2); bod2vertex(&obj->vert[12], mind + (bodX * n2) - n2 * lichy); // pravy horni bod2vertex(&obj->vert[15], mind); bod2vertex(&obj->vert[16], mind - (bodX * n2) - n2 * lichy + n2); bod2vertex(&obj->vert[17], mind + n2); int f; for (f = 0; f < 18; f++) obj->vert[f].position.z -= SHORE_HEIGHT; /* naplnim pole polygonu */ for (int polyind = 0; polyind < 6; polyind++){ obj->poly[polyind].first=3*polyind; obj->poly[polyind].last=3*polyind+2; obj->poly[polyind].lmap_id=0; obj->poly[polyind].mesh=obj->mesh; obj->poly[polyind].submat=0; obj->poly[polyind].udata=0; } // material vodni hladiny int intmat = addBasicTextureMaterial(model, RASTER_WATER, !ISNOTINBORDER(i, j)); PMeshNode mesh_nod = addBasicMeshNode(model, obj, 0, "Plane00", 0, 5, intmat); return model; } void NET::bod2vertex(TVertex *v, int ibod) { v->position.x = vert[ibod].position.x; v->position.y = vert[ibod].position.y; v->position.z = vert[ibod].position.z; v->normal.x = vert[ibod].normal.x; v->normal.y = vert[ibod].normal.y; v->normal.z = vert[ibod].normal.z; v->color = vert[ibod].color; v->texture.x = vert[ibod].texture.x; v->texture.y = vert[ibod].texture.y; } }//namespace /********************************************************************************************/