00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <common/Triangle.h>
00022 #include <landscapemap/HeightMap.h>
00023 #include <landscapemap/GraphicalHeightMap.h>
00024 #include <common/Defines.h>
00025
00026 static const int minMapShift = 3;
00027 static FixedVector nvec(fixed(0), fixed(0), fixed(1));
00028
00029 HeightMap::HeightMap() :
00030 heightData_(0), graphicalMap_(0)
00031 {
00032 }
00033
00034 HeightMap::~HeightMap()
00035 {
00036 delete [] heightData_;
00037 }
00038
00039 void HeightMap::create(const int width, const int height)
00040 {
00041 width_ = width;
00042 height_ = height;
00043
00044 delete [] heightData_;
00045 heightData_ = new HeightData[(width_ + 1) * (height_ + 1)];
00046
00047 reset();
00048
00049 if (graphicalMap_) graphicalMap_->create(width, height);
00050 }
00051
00052 void HeightMap::reset()
00053 {
00054 HeightData *current = heightData_;
00055 for (int y=0; y<=height_; y++)
00056 {
00057 for (int x=0; x<=width_; x++)
00058 {
00059 current->position[0] = fixed(x);
00060 current->position[1] = fixed(y);
00061 current->position[2] = fixed(0);
00062
00063 current->normal[0] = fixed(0);
00064 current->normal[1] = fixed(0);
00065 current->normal[2] = fixed(1);
00066
00067 current++;
00068 }
00069 }
00070 }
00071
00072 bool HeightMap::getVector(FixedVector &vec, int x, int y)
00073 {
00074 if (x < 0 || y < 0 || x>width_ || y>height_) return false;
00075
00076 vec = heightData_[(width_+1) * y + x].position;
00077 return true;
00078 }
00079
00080 void HeightMap::getVectorPos(int pos, int &x, int &y, int dist)
00081 {
00082 switch (pos)
00083 {
00084 case 0:
00085 x=-dist; y=0;
00086 break;
00087 case 1:
00088 x=0; y=dist;
00089 break;
00090 case 2:
00091 x=dist; y=0;
00092 break;
00093 default:
00094 x=0; y=-dist;
00095 }
00096 }
00097
00098 bool HeightMap::getIntersect(Line &line, Vector &intersect)
00099 {
00100 Vector direction = -((Vector &)line.getDirection()).Normalize();
00101 Vector start = line.getEnd();
00102
00103 for (int i=0; i<1000; i++)
00104 {
00105 fixed height = getHeight((int) start[0], (int) start[1]);
00106 if (height > fixed(int(start[2])))
00107 {
00108 if (start[0] < 0 || start[0] > getMapWidth() ||
00109 start[1] < 0 || start[1] > getMapHeight())
00110 {
00111 return false;
00112 }
00113
00114 intersect = start;
00115 return true;
00116 }
00117
00118 start += direction;
00119 }
00120 return false;
00121 }
00122
00123 fixed HeightMap::getInterpHeight(fixed w, fixed h)
00124 {
00125 fixed ihx = w.floor();
00126 fixed ihy = h.floor();
00127 fixed ihx2 = ihx+1;
00128 fixed ihy2 = ihy+1;
00129
00130 fixed fhx = w - ihx;
00131 fixed fhy = h - ihy;
00132
00133 fixed heightA = getHeight(ihx.asInt(), ihy.asInt());
00134 fixed heightB = getHeight(ihx.asInt(), ihy2.asInt());
00135 fixed heightC = getHeight(ihx2.asInt(), ihy.asInt());
00136 fixed heightD = getHeight(ihx2.asInt(), ihy2.asInt());
00137
00138 fixed heightDiffAB = heightB-heightA;
00139 fixed heightDiffCD = heightD-heightC;
00140 fixed heightE = heightA + (heightDiffAB * fhy);
00141 fixed heightF = heightC + (heightDiffCD * fhy);
00142
00143 fixed heightDiffEF = heightF - heightE;
00144 fixed height = heightE + (heightDiffEF * fhx);
00145
00146 return height;
00147 }
00148
00149 FixedVector &HeightMap::getNormal(int w, int h)
00150 {
00151 if (w >= 0 && h >= 0 && w<=width_ && h<=height_)
00152 {
00153 int pos = (width_+1) * h + w;
00154
00155 HeightMap::HeightData *heightData = &heightData_[pos];
00156
00157 FixedVector &normal = heightData->normal;
00158 if (normal[0] == fixed(0) &&
00159 normal[1] == fixed(0) &&
00160 normal[2] == fixed(0))
00161 {
00162 int x = w;
00163 int y = h;
00164
00165 static FixedVector C;
00166 C = heightData->position;
00167
00168 static FixedVector total;
00169 total.zero();
00170
00171 int times = 0;
00172 for (int dist=1; dist<=3; dist+=2)
00173 {
00174 for (int a=0, b=1; a<4; a+=2, b+=2)
00175 {
00176 if (b>3) b=0;
00177
00178 static FixedVector A;
00179 int aPosX, aPosY;
00180 getVectorPos(a, aPosX, aPosY, dist);
00181 if (!getVector(A, aPosX + x, aPosY + y)) continue;
00182
00183 static FixedVector B;
00184 int bPosX, bPosY;
00185 getVectorPos(b, bPosX, bPosY, dist);
00186 if (!getVector(B, bPosX + x, bPosY + y)) continue;
00187
00188 A-=C;
00189 B.StoreInvert();
00190 B+=C;
00191 A *= B;
00192 A.StoreNormalize();
00193 total += A;
00194 times += 1;
00195 }
00196
00197 if (times > 4) break;
00198 }
00199
00200 normal = total.Normalize();
00201 if (graphicalMap_) graphicalMap_->setNormal(w, h, normal.asVector());
00202 }
00203
00204 return normal;
00205 }
00206 nvec = FixedVector(fixed(0), fixed(0), fixed(1));
00207 return nvec;
00208 }
00209
00210 void HeightMap::getInterpNormal(fixed w, fixed h, FixedVector &normal)
00211 {
00212 fixed ihx = w.floor();
00213 fixed ihy = h.floor();
00214 fixed ihx2 = ihx+1;
00215 fixed ihy2 = ihy+1;
00216
00217 fixed fhx = w - ihx;
00218 fixed fhy = h - ihy;
00219
00220 FixedVector &normalA = getNormal(ihx.asInt(), ihy.asInt());
00221 FixedVector &normalB = getNormal(ihx.asInt(), ihy2.asInt());
00222 FixedVector &normalC = getNormal(ihx2.asInt(), ihy.asInt());
00223 FixedVector &normalD = getNormal(ihx2.asInt(), ihy2.asInt());
00224
00225 static FixedVector normalDiffAB;
00226 normalDiffAB = normalB;
00227 normalDiffAB -= normalA;
00228 normalDiffAB *= fhy;
00229 static FixedVector normalDiffCD;
00230 normalDiffCD = normalD;
00231 normalDiffCD -= normalC;
00232 normalDiffCD *= fhy;
00233
00234 static FixedVector normalE;
00235 normalE = normalA;
00236 normalE += normalDiffAB;
00237 static FixedVector normalF;
00238 normalF = normalC;
00239 normalF += normalDiffCD;
00240
00241 static FixedVector normalDiffEF;
00242 normalDiffEF = normalF;
00243 normalDiffEF -= normalE;
00244 normalDiffEF *= fhx;
00245
00246 normal = normalE;
00247 normal += normalDiffEF;
00248 }
00249
00250 void HeightMap::setHeight(int w, int h, fixed height)
00251 {
00252 DIALOG_ASSERT(w >= 0 && h >= 0 && w<=width_ && h<=height_);
00253
00254 HeightData &data = heightData_[(width_+1) * h + w];
00255 data.position[2] = height;
00256 if (graphicalMap_) graphicalMap_->setHeight(w, h, height.asFloat());
00257
00258
00259 for (int dist=1; dist<=3; dist++)
00260 {
00261 for (int a=0; a<4; a++)
00262 {
00263 int aPosX, aPosY;
00264 getVectorPos(a, aPosX, aPosY, dist);
00265
00266 int x = w + aPosX;
00267 int y = h + aPosY;
00268 if (x>=0 && y>=0 && x<=width_ && y<=height_)
00269 {
00270 heightData_[(width_+1) * y + x].normal.zero();
00271 }
00272 }
00273 }
00274 heightData_[(width_+1) * h + w].normal.zero();
00275 }