| 1 |
/////////////////////////////////////////////////////////// |
|---|
| 2 |
// TexGen // |
|---|
| 3 |
// утилита для подготовки текстур рельефа // |
|---|
| 4 |
// для игры Проклятые Земли // |
|---|
| 5 |
// Copyright (C) 2007-2008 Gipat Group // |
|---|
| 6 |
// Распространяется на условиях // |
|---|
| 7 |
// Gipat Group's opened EI-editor-utility license // |
|---|
| 8 |
// версии 1.0 // |
|---|
| 9 |
// // |
|---|
| 10 |
// www.gipatgroup.org // |
|---|
| 11 |
/////////////////////////////////////////////////////////// |
|---|
| 12 |
|
|---|
| 13 |
//К работе над данным файлом приложили руки, ноги.... короче аффтары: |
|---|
| 14 |
// 1) Снайпер (sniper-rifle@rambler.ru) |
|---|
| 15 |
|
|---|
| 16 |
//////////////////////////////////////////////////////////////////////// |
|---|
| 17 |
//--------------------------------------------------------------------------- |
|---|
| 18 |
#include <VCL.h> |
|---|
| 19 |
|
|---|
| 20 |
#include "Mask.h" |
|---|
| 21 |
//--------------------------------------------------------------------------- |
|---|
| 22 |
void CTileMask::LoadMask(AnsiString FN) |
|---|
| 23 |
{ |
|---|
| 24 |
if(FileExists(FN)) |
|---|
| 25 |
{ |
|---|
| 26 |
int h = FileOpen(FN,fmOpenRead); |
|---|
| 27 |
if(h) |
|---|
| 28 |
{ |
|---|
| 29 |
Clear(); |
|---|
| 30 |
BufLen = FileSeek(h,0,SEEK_END); |
|---|
| 31 |
FileSeek(h,0,SEEK_SET); |
|---|
| 32 |
buf = new byte[BufLen]; |
|---|
| 33 |
FileRead(h,buf,BufLen); |
|---|
| 34 |
FileClose(h); |
|---|
| 35 |
//Теперь проверяем файл %) |
|---|
| 36 |
AnsiString Head="**"; |
|---|
| 37 |
memcpy(&Head[1],buf,2); // Заголовок 2 байта - "TM" |
|---|
| 38 |
if(Head == "TM") // Bce OK, файл нашего типа |
|---|
| 39 |
{ |
|---|
| 40 |
byte Version; |
|---|
| 41 |
memcpy(&Version,buf+2,1); |
|---|
| 42 |
//switch - будет потом наверное если надо))) |
|---|
| 43 |
if(Version == MaskVersion) // Версия совпала %) |
|---|
| 44 |
{ |
|---|
| 45 |
memcpy(&W,buf+3,4); |
|---|
| 46 |
memcpy(&H,buf+7,4); |
|---|
| 47 |
Uncompress(); |
|---|
| 48 |
} |
|---|
| 49 |
else Clear(); // { |
|---|
| 50 |
} // Зачищаем последствия неудачной загрузки |
|---|
| 51 |
else Clear(); // } |
|---|
| 52 |
} |
|---|
| 53 |
} |
|---|
| 54 |
} |
|---|
| 55 |
//--------------------------------------------------------------------------- |
|---|
| 56 |
void CTileMask::SaveMask(AnsiString FN) |
|---|
| 57 |
{ |
|---|
| 58 |
int h = FileCreate(FN, fmOpenWrite); |
|---|
| 59 |
if(h) |
|---|
| 60 |
{ |
|---|
| 61 |
Compress(); |
|---|
| 62 |
//Normalize(); // А то мало ли что %) //Маразм =( |
|---|
| 63 |
FileWrite(h,buf,BufLen); |
|---|
| 64 |
FileClose(h); |
|---|
| 65 |
} |
|---|
| 66 |
} |
|---|
| 67 |
//--------------------------------------------------------------------------- |
|---|
| 68 |
void CTileMask::GetPoint(int X, int Y, byte *dwDest) |
|---|
| 69 |
{ |
|---|
| 70 |
byte A, B, C, D; |
|---|
| 71 |
memcpy(&A,buf+HeadLen+Y*W*3+X*3+0,1); |
|---|
| 72 |
memcpy(&B,buf+HeadLen+Y*W*3+X*3+1,1); |
|---|
| 73 |
memcpy(&C,buf+HeadLen+Y*W*3+X*3+2,1); |
|---|
| 74 |
D = 0; |
|---|
| 75 |
//Считали - теперь формируем А, B, C и D |
|---|
| 76 |
if(A & 0x40) |
|---|
| 77 |
{ |
|---|
| 78 |
A -= 0x40; |
|---|
| 79 |
D += 0x01; |
|---|
| 80 |
} |
|---|
| 81 |
if(A & 0x80) |
|---|
| 82 |
{ |
|---|
| 83 |
A -= 0x80; |
|---|
| 84 |
D += 0x02; |
|---|
| 85 |
} |
|---|
| 86 |
if(B & 0x40) |
|---|
| 87 |
{ |
|---|
| 88 |
B -= 0x40; |
|---|
| 89 |
D += 0x04; |
|---|
| 90 |
} |
|---|
| 91 |
if(B & 0x80) |
|---|
| 92 |
{ |
|---|
| 93 |
B -= 0x80; |
|---|
| 94 |
D += 0x08; |
|---|
| 95 |
} |
|---|
| 96 |
if(C & 0x40) |
|---|
| 97 |
{ |
|---|
| 98 |
C -= 0x40; |
|---|
| 99 |
D += 0x10; |
|---|
| 100 |
} |
|---|
| 101 |
if(C & 0x80) |
|---|
| 102 |
{ |
|---|
| 103 |
C -= 0x80; |
|---|
| 104 |
D += 0x20; |
|---|
| 105 |
} |
|---|
| 106 |
// Заполнили - теперь возвращаем результат |
|---|
| 107 |
|
|---|
| 108 |
memcpy(dwDest+0,&A,1); |
|---|
| 109 |
memcpy(dwDest+1,&B,1); |
|---|
| 110 |
memcpy(dwDest+2,&C,1); |
|---|
| 111 |
memcpy(dwDest+3,&D,1); |
|---|
| 112 |
//Готово! %) |
|---|
| 113 |
} |
|---|
| 114 |
//--------------------------------------------------------------------------- |
|---|
| 115 |
void CTileMask::SetPoint(int X, int Y, byte *dwSrc) |
|---|
| 116 |
{ |
|---|
| 117 |
byte A, B, C, D; |
|---|
| 118 |
memcpy(&A,dwSrc+0,1); |
|---|
| 119 |
memcpy(&B,dwSrc+1,1); |
|---|
| 120 |
memcpy(&C,dwSrc+2,1); |
|---|
| 121 |
memcpy(&D,dwSrc+3,1); |
|---|
| 122 |
//Теперь перегоняем инфу из D в A,B и C. |
|---|
| 123 |
A += (D & 0x01)?0x40:0; |
|---|
| 124 |
A += (D & 0x02)?0x80:0; |
|---|
| 125 |
B += (D & 0x04)?0x40:0; |
|---|
| 126 |
B += (D & 0x08)?0x80:0; |
|---|
| 127 |
C += (D & 0x10)?0x40:0; |
|---|
| 128 |
C += (D & 0x20)?0x80:0; |
|---|
| 129 |
//Перегоняем в буфер %) |
|---|
| 130 |
memcpy(buf+HeadLen+Y*W*3+X*3+0,&A,1); |
|---|
| 131 |
memcpy(buf+HeadLen+Y*W*3+X*3+1,&B,1); |
|---|
| 132 |
memcpy(buf+HeadLen+Y*W*3+X*3+2,&C,1); |
|---|
| 133 |
//Я тут подумал - а фигли я вы@#$!аюсь? Экономлю, понимаешь ли, 1 байт, запутываю код, теряю скорость |
|---|
| 134 |
|
|---|
| 135 |
//Ответ прост: комары тут кусают, и спать пора. Вот и фигею помаленьку %))) |
|---|
| 136 |
} |
|---|
| 137 |
//--------------------------------------------------------------------------- |
|---|
| 138 |
void CTileMask::NewMask(int szW, int szH, bool F) |
|---|
| 139 |
{ |
|---|
| 140 |
AnsiString Header="TM"; |
|---|
| 141 |
Clear(); |
|---|
| 142 |
W = szW; |
|---|
| 143 |
H = szH; |
|---|
| 144 |
BufLen = HeadLen+W*H*3; |
|---|
| 145 |
buf = new byte[BufLen]; |
|---|
| 146 |
memcpy(buf,&Header[1],2); |
|---|
| 147 |
memcpy(buf+2,&MaskVersion,1); |
|---|
| 148 |
memcpy(buf+3,&W,4); |
|---|
| 149 |
memcpy(buf+7,&H,4); |
|---|
| 150 |
if(F) |
|---|
| 151 |
{ |
|---|
| 152 |
//А теперь заполняем массив "4х16" |
|---|
| 153 |
byte A=16,B=16,C=16,D=15, *dwTmp = new byte[4]; |
|---|
| 154 |
memcpy(dwTmp , &A, 1); |
|---|
| 155 |
memcpy(dwTmp+1, &B, 1); |
|---|
| 156 |
memcpy(dwTmp+2, &C, 1); |
|---|
| 157 |
memcpy(dwTmp+3, &D, 1); |
|---|
| 158 |
for(int X=0; X<W;X++) |
|---|
| 159 |
for(int Y=0;Y<H;Y++) |
|---|
| 160 |
{ |
|---|
| 161 |
SetPoint(X,Y,dwTmp); |
|---|
| 162 |
} |
|---|
| 163 |
Uncompress(); |
|---|
| 164 |
//Прошу любить и жаловать %) |
|---|
| 165 |
delete [] dwTmp; |
|---|
| 166 |
} |
|---|
| 167 |
} |
|---|
| 168 |
//--------------------------------------------------------------------------- |
|---|
| 169 |
void CTileMask::NormalizeW(int X, int Y) |
|---|
| 170 |
{ |
|---|
| 171 |
byte A,B,C,D, *dwTmp=new byte[4]; |
|---|
| 172 |
GetPointW(X,Y,dwTmp); |
|---|
| 173 |
A = dwTmp[0]; |
|---|
| 174 |
B = dwTmp[1]; |
|---|
| 175 |
C = dwTmp[2]; |
|---|
| 176 |
D = dwTmp[3]; |
|---|
| 177 |
while(A+B+C+D>=63) |
|---|
| 178 |
{ |
|---|
| 179 |
if(A>0)A--; |
|---|
| 180 |
if(B>0)B--; |
|---|
| 181 |
if(C>0)C--; |
|---|
| 182 |
if(D>0)D--; |
|---|
| 183 |
} |
|---|
| 184 |
dwTmp[0]=A; |
|---|
| 185 |
dwTmp[1]=B; |
|---|
| 186 |
dwTmp[2]=C; |
|---|
| 187 |
dwTmp[3]=D; |
|---|
| 188 |
SetPointW(X,Y,dwTmp); |
|---|
| 189 |
delete [] dwTmp; |
|---|
| 190 |
} |
|---|
| 191 |
//--------------------------------------------------------------------------- |
|---|
| 192 |
void CTileMask::Uncompress() |
|---|
| 193 |
{ |
|---|
| 194 |
ClearW();//Потрём данные, если они каким-то чудом остались целы |
|---|
| 195 |
if(BufLen>0) |
|---|
| 196 |
{ |
|---|
| 197 |
byte *dwTmp=new byte[4]; |
|---|
| 198 |
Buf2Len = W*H*4; |
|---|
| 199 |
WorkData = new byte[Buf2Len]; |
|---|
| 200 |
for(int X=0; X<W; X++) |
|---|
| 201 |
for(int Y=0; Y<H; Y++) |
|---|
| 202 |
{ |
|---|
| 203 |
GetPoint(X,Y,dwTmp); |
|---|
| 204 |
SetPointW(X,Y,dwTmp); |
|---|
| 205 |
} |
|---|
| 206 |
int A=W,B=H; |
|---|
| 207 |
W=A;H=B; |
|---|
| 208 |
delete [] dwTmp; |
|---|
| 209 |
} |
|---|
| 210 |
} |
|---|
| 211 |
//--------------------------------------------------------------------------- |
|---|
| 212 |
void CTileMask::Compress() |
|---|
| 213 |
{ |
|---|
| 214 |
int A=W,B=H; |
|---|
| 215 |
Clear(); |
|---|
| 216 |
if(Buf2Len>0) |
|---|
| 217 |
{ |
|---|
| 218 |
byte *dwTmp=new byte[4]; |
|---|
| 219 |
W=A; |
|---|
| 220 |
H=B; |
|---|
| 221 |
NewMask(W,H,false); |
|---|
| 222 |
for(int X=0; X<W; X++) |
|---|
| 223 |
for(int Y=0; Y<H; Y++) |
|---|
| 224 |
{ |
|---|
| 225 |
GetPointW(X,Y,dwTmp); |
|---|
| 226 |
SetPoint(X,Y,dwTmp); |
|---|
| 227 |
} |
|---|
| 228 |
delete [] dwTmp; |
|---|
| 229 |
} |
|---|
| 230 |
} |
|---|
| 231 |
//--------------------------------------------------------------------------- |
|---|
| 232 |
void CTileMask::GetPointW(int X, int Y, byte *dwDest) |
|---|
| 233 |
{ |
|---|
| 234 |
memcpy(dwDest,WorkData+Y*W*4+X*4,4); |
|---|
| 235 |
} |
|---|
| 236 |
//--------------------------------------------------------------------------- |
|---|
| 237 |
void CTileMask::SetPointW(int X, int Y, byte *dwSrc) |
|---|
| 238 |
{ |
|---|
| 239 |
memcpy(WorkData+Y*W*4+X*4,dwSrc,4); |
|---|
| 240 |
} |
|---|
| 241 |
//--------------------------------------------------------------------------- |
|---|
| 242 |
int CTileMask::CheckSumW(int X, int Y) |
|---|
| 243 |
{ |
|---|
| 244 |
//Проверяем сумму мощностей материалов в точке, чтобы не было глюков. |
|---|
| 245 |
//Нормальная сумма равна 64. |
|---|
| 246 |
byte *dwTmp=new byte[4]; |
|---|
| 247 |
GetPointW(X,Y,dwTmp); |
|---|
| 248 |
int Rez = dwTmp[0]+dwTmp[1]+dwTmp[2]+dwTmp[3]; |
|---|
| 249 |
delete [] dwTmp; |
|---|
| 250 |
return Rez; |
|---|
| 251 |
} |
|---|