00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "Common/Math3D.h"
00012 #include "Common/Directory.h"
00013 #include "Common/Game.h"
00014 #include "Common/Ini.h"
00015 #include "Render/Render.h"
00016 #include "Landscape/TileDraw.h"
00017 #include "Landscape/LandscapeDraw.h"
00018 #include "Landscape/SubTileDraw.h"
00019
00020
00021 void KSubTileDrawMipMesh::ComputeNormal()
00022 {
00023 u32 vtx;
00024 KVector v0, v1, v2, Normal;
00025 float* pnTri;
00026
00027 pnTri = new float[m_nVertex];
00028
00029
00030 for( vtx = 0; vtx < m_nVertex; vtx ++ )
00031 {
00032 m_pVertex[vtx].Normal.x = 0.0f;
00033 m_pVertex[vtx].Normal.y = 0.0f;
00034 m_pVertex[vtx].Normal.z = 0.0f;
00035 pnTri[vtx] = 0.0f;
00036 }
00037
00038
00039 for( u32 mi = 0; mi < KSTMI_COUNT; mi ++ )
00040 {
00041 for( u32 idx = 0; idx < m_nIndex[mi]; idx += 3 )
00042 {
00043 v0 = m_pVertex[ m_pIndex[mi][idx + 0] ].Position;
00044 v1 = m_pVertex[ m_pIndex[mi][idx + 1] ].Position;
00045 v2 = m_pVertex[ m_pIndex[mi][idx + 2] ].Position;
00046
00047 Normal = KVector::CrossProduct( v2 - v0, v1 - v0 );
00048
00049 m_pVertex[ m_pIndex[mi][idx + 0] ].Normal += Normal;
00050 m_pVertex[ m_pIndex[mi][idx + 1] ].Normal += Normal;
00051 m_pVertex[ m_pIndex[mi][idx + 2] ].Normal += Normal;
00052
00053 pnTri[m_pIndex[mi][idx + 0] ] += 1.0f;
00054 pnTri[m_pIndex[mi][idx + 1] ] += 1.0f;
00055 pnTri[m_pIndex[mi][idx + 2] ] += 1.0f;
00056 }
00057 }
00058
00059
00060 for( vtx = 0; vtx < m_nVertex; vtx ++ )
00061 {
00062 m_pVertex[vtx].Normal /= pnTri[vtx];
00063 m_pVertex[vtx].Normal.Normalize();
00064 }
00065
00066 Deletev( pnTri );
00067 }
00068
00069
00070
00071
00072 KSubTileDraw::KSubTileDraw( KTile* pTile, float PosX, float PosY )
00073 : KSubTile( pTile, PosX, PosY )
00074 {
00075 m_pMipMesh = NULL;
00076 m_CurrentMipLevel = 0;
00077 m_bDraw = false;
00078 m_pIndexList = NULL;
00079 m_nIndexList = 0;
00080 m_nIndexListPos = 0;
00081 m_hShader = KSHADER_NO;
00082 m_pShader = NULL;
00083
00084
00085
00086
00087
00088
00089 u32 SizeX = TILE_NCELLS_X/TILE_NSUBTILES_X;
00090 u32 SizeY = TILE_NCELLS_Y/TILE_NSUBTILES_Y;
00091
00092
00093 KASSERT( TILE_NSUBTILES_X == TILE_NSUBTILES_Y );
00094
00095
00096 m_nMipMesh = GetnMipMeshLevels();
00097
00098
00099
00100
00101
00102
00103
00104 u32 MipValue;
00105
00106
00107 m_pMipMesh = new KSubTileDrawMipMesh[ m_nMipMesh ];
00108 for( u32 m = 0; m < m_nMipMesh; m ++ )
00109 {
00110 MipValue = (u32)powf( 2, (float)m );
00111
00112
00113
00114
00115
00116
00117 m_pMipMesh[m].m_nVertex = ((SizeX + 1) * (SizeY + 1)) / MipValue;
00118 m_pMipMesh[m].m_pVertex = new KVertex2[ m_pMipMesh[m].m_nVertex ];
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 u32 idx;
00155 u32 ix, iy;
00156 u32 i;
00157
00158 u32 IndexSizeX = SizeX / MipValue;
00159 u32 IndexSizeY = SizeY / MipValue;
00160
00161
00162
00163
00164 if( ( IndexSizeX > 2 ) && ( IndexSizeY > 2 ) )
00165 {
00166 m_pMipMesh[m].m_nIndex[KSTMI_CENTER] = (IndexSizeX - 2) * (IndexSizeY - 2) * 6;
00167 m_pMipMesh[m].m_pIndex[KSTMI_CENTER] = new KINDEX[ m_pMipMesh[m].m_nIndex[KSTMI_CENTER] ];
00168
00169 i = 0;
00170 for( iy = 1; iy < IndexSizeY - 1; iy ++ )
00171 {
00172 for( ix = 1; ix < IndexSizeX - 1; ix ++ )
00173 {
00174 idx = (iy * (IndexSizeX + 1) + ix);
00175
00176
00177 m_pMipMesh[m].m_pIndex[KSTMI_CENTER][i + 0] = (KINDEX)(idx);
00178 m_pMipMesh[m].m_pIndex[KSTMI_CENTER][i + 1] = (KINDEX)(idx + IndexSizeX + 1);
00179 m_pMipMesh[m].m_pIndex[KSTMI_CENTER][i + 2] = (KINDEX)(idx + 1);
00180
00181
00182 m_pMipMesh[m].m_pIndex[KSTMI_CENTER][i + 3] = (KINDEX)(idx + 1);
00183 m_pMipMesh[m].m_pIndex[KSTMI_CENTER][i + 4] = (KINDEX)(idx + IndexSizeX + 1);
00184 m_pMipMesh[m].m_pIndex[KSTMI_CENTER][i + 5] = (KINDEX)(idx + IndexSizeX + 2);
00185 i += 6;
00186 }
00187 }
00188 KASSERT( i == m_pMipMesh[m].m_nIndex[KSTMI_CENTER] );
00189 }
00190
00191
00192
00193
00194 if( ( IndexSizeX == 1 ) && ( IndexSizeY == 1 ) )
00195 {
00196 m_pMipMesh[m].m_nIndex[KSTMI_CENTER] = 6;
00197 m_pMipMesh[m].m_pIndex[KSTMI_CENTER] = new KINDEX[ m_pMipMesh[m].m_nIndex[KSTMI_CENTER] ];
00198
00199 i = 0;
00200
00201
00202 m_pMipMesh[m].m_pIndex[KSTMI_CENTER][i + 0] = (KINDEX)0;
00203 m_pMipMesh[m].m_pIndex[KSTMI_CENTER][i + 1] = (KINDEX)2;
00204 m_pMipMesh[m].m_pIndex[KSTMI_CENTER][i + 2] = (KINDEX)3;
00205
00206
00207 m_pMipMesh[m].m_pIndex[KSTMI_CENTER][i + 3] = (KINDEX)0;
00208 m_pMipMesh[m].m_pIndex[KSTMI_CENTER][i + 4] = (KINDEX)3;
00209 m_pMipMesh[m].m_pIndex[KSTMI_CENTER][i + 5] = (KINDEX)1;
00210
00211 i += 6;
00212
00213 KASSERT( i == m_pMipMesh[m].m_nIndex[KSTMI_CENTER] );
00214 }
00215
00216
00217
00218
00219 if( IndexSizeX > 1 )
00220 {
00221
00222
00223 m_pMipMesh[m].m_nIndex[KSTMI_UP] = ((IndexSizeX - 2) * 2 + 2) * 3;
00224 m_pMipMesh[m].m_pIndex[KSTMI_UP] = new KINDEX[ m_pMipMesh[m].m_nIndex[KSTMI_UP] ];
00225
00226 i = 0;
00227
00228
00229 m_pMipMesh[m].m_pIndex[KSTMI_UP][i + 0] = (KINDEX)(IndexSizeX * (IndexSizeX + 1));
00230 m_pMipMesh[m].m_pIndex[KSTMI_UP][i + 1] = (KINDEX)(IndexSizeX * (IndexSizeX + 1) + 1);
00231 m_pMipMesh[m].m_pIndex[KSTMI_UP][i + 2] = (KINDEX)(IndexSizeX * IndexSizeX);
00232
00233
00234 m_pMipMesh[m].m_pIndex[KSTMI_UP][i + 3] = (KINDEX)((IndexSizeX + 1) * (IndexSizeX + 1) - 2);
00235 m_pMipMesh[m].m_pIndex[KSTMI_UP][i + 4] = (KINDEX)((IndexSizeX + 1) * (IndexSizeX + 1) - 1);
00236 m_pMipMesh[m].m_pIndex[KSTMI_UP][i + 5] = (KINDEX)((IndexSizeX) * (IndexSizeX + 1) - 2);
00237
00238 i += 6;
00239
00240
00241 for( ix = 1; ix < IndexSizeX - 1; ix += 1 )
00242 {
00243 idx = (IndexSizeY - 1) * (IndexSizeX + 1) + ix;
00244
00245
00246 m_pMipMesh[m].m_pIndex[KSTMI_UP][i + 0] = (KINDEX)(idx);
00247 m_pMipMesh[m].m_pIndex[KSTMI_UP][i + 1] = (KINDEX)(idx + IndexSizeX + 1);
00248 m_pMipMesh[m].m_pIndex[KSTMI_UP][i + 2] = (KINDEX)(idx + 1);
00249
00250
00251 m_pMipMesh[m].m_pIndex[KSTMI_UP][i + 3] = (KINDEX)(idx + 1);
00252 m_pMipMesh[m].m_pIndex[KSTMI_UP][i + 4] = (KINDEX)(idx + IndexSizeX + 1);
00253 m_pMipMesh[m].m_pIndex[KSTMI_UP][i + 5] = (KINDEX)(idx + IndexSizeX + 2);
00254
00255 i += 6;
00256 }
00257
00258 KASSERT( i == m_pMipMesh[m].m_nIndex[KSTMI_UP] );
00259 }
00260
00261
00262
00263
00264 if( IndexSizeX > 1 )
00265 {
00266
00267
00268 m_pMipMesh[m].m_nIndex[KSTMI_MIP_UP] = (IndexSizeX / 2) * 3 + (IndexSizeX - 2) * 3;
00269 m_pMipMesh[m].m_pIndex[KSTMI_MIP_UP] = new KINDEX[ m_pMipMesh[m].m_nIndex[KSTMI_MIP_UP] ];
00270
00271 i = 0;
00272
00273
00274 for( ix = 0; ix < IndexSizeX; ix += 2 )
00275 {
00276 idx = ix + (IndexSizeX + 1) * IndexSizeY;
00277
00278
00279 m_pMipMesh[m].m_pIndex[KSTMI_MIP_UP][i + 0] = (KINDEX)(idx);
00280 m_pMipMesh[m].m_pIndex[KSTMI_MIP_UP][i + 1] = (KINDEX)(idx + 2);
00281 m_pMipMesh[m].m_pIndex[KSTMI_MIP_UP][i + 2] = (KINDEX)(idx - IndexSizeX);
00282
00283 i += 3;
00284 }
00285
00286 for( ix = 1; ix < IndexSizeX - 1; ix += 2 )
00287 {
00288 idx = ix + (IndexSizeX + 1) * IndexSizeY;
00289
00290
00291 m_pMipMesh[m].m_pIndex[KSTMI_MIP_UP][i + 0] = (KINDEX)(idx - IndexSizeX - 1);
00292 m_pMipMesh[m].m_pIndex[KSTMI_MIP_UP][i + 1] = (KINDEX)(idx + 1);
00293 m_pMipMesh[m].m_pIndex[KSTMI_MIP_UP][i + 2] = (KINDEX)(idx - IndexSizeX);
00294
00295
00296 m_pMipMesh[m].m_pIndex[KSTMI_MIP_UP][i + 3] = (KINDEX)(idx - IndexSizeX);
00297 m_pMipMesh[m].m_pIndex[KSTMI_MIP_UP][i + 4] = (KINDEX)(idx + 1);
00298 m_pMipMesh[m].m_pIndex[KSTMI_MIP_UP][i + 5] = (KINDEX)(idx - IndexSizeX + 1);
00299
00300 i += 6;
00301 }
00302
00303 KASSERT( i == m_pMipMesh[m].m_nIndex[KSTMI_MIP_UP] );
00304 }
00305
00306
00307
00308
00309 if( IndexSizeX > 1 )
00310 {
00311
00312
00313 m_pMipMesh[m].m_nIndex[KSTMI_DOWN] = ((IndexSizeX - 2) * 2 + 2) * 3;
00314 m_pMipMesh[m].m_pIndex[KSTMI_DOWN] = new KINDEX[ m_pMipMesh[m].m_nIndex[KSTMI_DOWN] ];
00315
00316 i = 0;
00317
00318
00319 m_pMipMesh[m].m_pIndex[KSTMI_DOWN][i + 0] = (KINDEX)(0);
00320 m_pMipMesh[m].m_pIndex[KSTMI_DOWN][i + 1] = (KINDEX)(IndexSizeX + 2);
00321 m_pMipMesh[m].m_pIndex[KSTMI_DOWN][i + 2] = (KINDEX)(1);
00322
00323
00324 m_pMipMesh[m].m_pIndex[KSTMI_DOWN][i + 3] = (KINDEX)(IndexSizeX - 1);
00325 m_pMipMesh[m].m_pIndex[KSTMI_DOWN][i + 4] = (KINDEX)(IndexSizeX + IndexSizeX);
00326 m_pMipMesh[m].m_pIndex[KSTMI_DOWN][i + 5] = (KINDEX)(IndexSizeX);
00327
00328 i += 6;
00329
00330
00331 for( ix = 1; ix < IndexSizeX - 1; ix += 1 )
00332 {
00333 idx = ix;
00334
00335
00336 m_pMipMesh[m].m_pIndex[KSTMI_DOWN][i + 0] = (KINDEX)(idx);
00337 m_pMipMesh[m].m_pIndex[KSTMI_DOWN][i + 1] = (KINDEX)(idx + IndexSizeX + 1);
00338 m_pMipMesh[m].m_pIndex[KSTMI_DOWN][i + 2] = (KINDEX)(idx + 1);
00339
00340
00341 m_pMipMesh[m].m_pIndex[KSTMI_DOWN][i + 3] = (KINDEX)(idx + 1);
00342 m_pMipMesh[m].m_pIndex[KSTMI_DOWN][i + 4] = (KINDEX)(idx + IndexSizeX + 1);
00343 m_pMipMesh[m].m_pIndex[KSTMI_DOWN][i + 5] = (KINDEX)(idx + IndexSizeX + 2);
00344
00345 i += 6;
00346 }
00347
00348 KASSERT( i == m_pMipMesh[m].m_nIndex[KSTMI_DOWN] );
00349 }
00350
00351
00352
00353
00354 if( IndexSizeX > 1 )
00355 {
00356
00357
00358 m_pMipMesh[m].m_nIndex[KSTMI_MIP_DOWN] = (IndexSizeX / 2) * 3 + (IndexSizeX - 2) * 3;
00359 m_pMipMesh[m].m_pIndex[KSTMI_MIP_DOWN] = new KINDEX[ m_pMipMesh[m].m_nIndex[KSTMI_MIP_DOWN] ];
00360
00361 i = 0;
00362
00363
00364 for( ix = 0; ix < IndexSizeX; ix += 2 )
00365 {
00366 idx = ix;
00367
00368
00369 m_pMipMesh[m].m_pIndex[KSTMI_MIP_DOWN][i + 0] = (KINDEX)(idx);
00370 m_pMipMesh[m].m_pIndex[KSTMI_MIP_DOWN][i + 1] = (KINDEX)(idx + IndexSizeX + 2);
00371 m_pMipMesh[m].m_pIndex[KSTMI_MIP_DOWN][i + 2] = (KINDEX)(idx + 2);
00372
00373 i += 3;
00374 }
00375
00376 for( ix = 1; ix < IndexSizeX - 1; ix += 2 )
00377 {
00378 idx = ix;
00379
00380
00381 m_pMipMesh[m].m_pIndex[KSTMI_MIP_DOWN][i + 0] = (KINDEX)(idx + 1);
00382 m_pMipMesh[m].m_pIndex[KSTMI_MIP_DOWN][i + 1] = (KINDEX)(idx + IndexSizeX + 1);
00383 m_pMipMesh[m].m_pIndex[KSTMI_MIP_DOWN][i + 2] = (KINDEX)(idx + IndexSizeX + 2);
00384
00385
00386 m_pMipMesh[m].m_pIndex[KSTMI_MIP_DOWN][i + 3] = (KINDEX)(idx + 1);
00387 m_pMipMesh[m].m_pIndex[KSTMI_MIP_DOWN][i + 4] = (KINDEX)(idx + IndexSizeX + 2);
00388 m_pMipMesh[m].m_pIndex[KSTMI_MIP_DOWN][i + 5] = (KINDEX)(idx + IndexSizeX + 3);
00389
00390 i += 6;
00391 }
00392
00393 KASSERT( i == m_pMipMesh[m].m_nIndex[KSTMI_MIP_DOWN] );
00394 }
00395
00396
00397
00398
00399 if( IndexSizeY > 1 )
00400 {
00401
00402
00403 m_pMipMesh[m].m_nIndex[KSTMI_LEFT] = ((IndexSizeY - 2) * 2 + 2) * 3;
00404 m_pMipMesh[m].m_pIndex[KSTMI_LEFT] = new KINDEX[ m_pMipMesh[m].m_nIndex[KSTMI_LEFT] ];
00405
00406 i = 0;
00407
00408
00409 m_pMipMesh[m].m_pIndex[KSTMI_LEFT][i + 0] = (KINDEX)(0);
00410 m_pMipMesh[m].m_pIndex[KSTMI_LEFT][i + 1] = (KINDEX)(IndexSizeX + 1);
00411 m_pMipMesh[m].m_pIndex[KSTMI_LEFT][i + 2] = (KINDEX)(IndexSizeX + 2);
00412
00413
00414 m_pMipMesh[m].m_pIndex[KSTMI_LEFT][i + 3] = (KINDEX)(IndexSizeX * IndexSizeY - 1);
00415 m_pMipMesh[m].m_pIndex[KSTMI_LEFT][i + 4] = (KINDEX)(IndexSizeX * (IndexSizeY + 1));
00416 m_pMipMesh[m].m_pIndex[KSTMI_LEFT][i + 5] = (KINDEX)(IndexSizeX * IndexSizeY);
00417
00418 i += 6;
00419
00420
00421 for( iy = 1; iy < IndexSizeY - 1; iy += 1 )
00422 {
00423 idx = iy * (IndexSizeX + 1);
00424
00425
00426 m_pMipMesh[m].m_pIndex[KSTMI_LEFT][i + 0] = (KINDEX)(idx);
00427 m_pMipMesh[m].m_pIndex[KSTMI_LEFT][i + 1] = (KINDEX)(idx + IndexSizeY + 1);
00428 m_pMipMesh[m].m_pIndex[KSTMI_LEFT][i + 2] = (KINDEX)(idx + 1);
00429
00430
00431 m_pMipMesh[m].m_pIndex[KSTMI_LEFT][i + 3] = (KINDEX)(idx + 1);
00432 m_pMipMesh[m].m_pIndex[KSTMI_LEFT][i + 4] = (KINDEX)(idx + IndexSizeY + 1);
00433 m_pMipMesh[m].m_pIndex[KSTMI_LEFT][i + 5] = (KINDEX)(idx + IndexSizeY + 2);
00434
00435 i += 6;
00436 }
00437
00438 KASSERT( i == m_pMipMesh[m].m_nIndex[KSTMI_LEFT] );
00439 }
00440
00441
00442
00443
00444 if( IndexSizeY > 1 )
00445 {
00446
00447
00448 m_pMipMesh[m].m_nIndex[KSTMI_MIP_LEFT] = (IndexSizeY / 2) * 3 + (IndexSizeY - 2) * 3;
00449 m_pMipMesh[m].m_pIndex[KSTMI_MIP_LEFT] = new KINDEX[ m_pMipMesh[m].m_nIndex[KSTMI_MIP_LEFT] ];
00450
00451 i = 0;
00452
00453
00454 for( iy = 0; iy < IndexSizeY; iy += 2 )
00455 {
00456 idx = iy * (IndexSizeX + 1);
00457
00458
00459 m_pMipMesh[m].m_pIndex[KSTMI_MIP_LEFT][i + 0] = (KINDEX)(idx);
00460 m_pMipMesh[m].m_pIndex[KSTMI_MIP_LEFT][i + 1] = (KINDEX)(idx + (IndexSizeX + 1) * 2);
00461 m_pMipMesh[m].m_pIndex[KSTMI_MIP_LEFT][i + 2] = (KINDEX)(idx + IndexSizeX + 2);
00462
00463 i += 3;
00464 }
00465
00466 for( iy = 1; iy < IndexSizeY - 1; iy += 2 )
00467 {
00468 idx = iy * (IndexSizeX + 1);
00469
00470
00471 m_pMipMesh[m].m_pIndex[KSTMI_MIP_LEFT][i + 0] = (KINDEX)(idx + 1);
00472 m_pMipMesh[m].m_pIndex[KSTMI_MIP_LEFT][i + 1] = (KINDEX)(idx + IndexSizeX + 1);
00473 m_pMipMesh[m].m_pIndex[KSTMI_MIP_LEFT][i + 2] = (KINDEX)(idx + IndexSizeX + 2);
00474
00475
00476 m_pMipMesh[m].m_pIndex[KSTMI_MIP_LEFT][i + 3] = (KINDEX)(idx + IndexSizeX + 1);
00477 m_pMipMesh[m].m_pIndex[KSTMI_MIP_LEFT][i + 4] = (KINDEX)(idx + (IndexSizeX + 1 ) * 2 + 1);
00478 m_pMipMesh[m].m_pIndex[KSTMI_MIP_LEFT][i + 5] = (KINDEX)(idx + IndexSizeX + 2);
00479
00480 i += 6;
00481 }
00482
00483 KASSERT( i == m_pMipMesh[m].m_nIndex[KSTMI_MIP_LEFT] );
00484 }
00485
00486
00487
00488
00489 if( IndexSizeY > 1 )
00490 {
00491
00492
00493 m_pMipMesh[m].m_nIndex[KSTMI_RIGHT] = ((IndexSizeY - 2) * 2 + 2) * 3;
00494 m_pMipMesh[m].m_pIndex[KSTMI_RIGHT] = new KINDEX[ m_pMipMesh[m].m_nIndex[KSTMI_RIGHT] ];
00495
00496 i = 0;
00497
00498
00499 m_pMipMesh[m].m_pIndex[KSTMI_RIGHT][i + 0] = (KINDEX)(IndexSizeX);
00500 m_pMipMesh[m].m_pIndex[KSTMI_RIGHT][i + 1] = (KINDEX)(IndexSizeX * 2);
00501 m_pMipMesh[m].m_pIndex[KSTMI_RIGHT][i + 2] = (KINDEX)(IndexSizeX * 2 + 1);
00502
00503
00504 m_pMipMesh[m].m_pIndex[KSTMI_RIGHT][i + 3] = (KINDEX)((IndexSizeX + 1) * IndexSizeY - 2);
00505 m_pMipMesh[m].m_pIndex[KSTMI_RIGHT][i + 4] = (KINDEX)((IndexSizeX + 1) * (IndexSizeY + 1) - 1);
00506 m_pMipMesh[m].m_pIndex[KSTMI_RIGHT][i + 5] = (KINDEX)((IndexSizeX + 1) * IndexSizeY - 1);
00507
00508 i += 6;
00509
00510
00511 for( iy = 1; iy < IndexSizeY - 1; iy += 1 )
00512 {
00513 idx = iy * (IndexSizeX + 1) + IndexSizeX - 1;
00514
00515
00516 m_pMipMesh[m].m_pIndex[KSTMI_RIGHT][i + 0] = (KINDEX)(idx);
00517 m_pMipMesh[m].m_pIndex[KSTMI_RIGHT][i + 1] = (KINDEX)(idx + IndexSizeY + 1);
00518 m_pMipMesh[m].m_pIndex[KSTMI_RIGHT][i + 2] = (KINDEX)(idx + 1);
00519
00520
00521 m_pMipMesh[m].m_pIndex[KSTMI_RIGHT][i + 3] = (KINDEX)(idx + 1);
00522 m_pMipMesh[m].m_pIndex[KSTMI_RIGHT][i + 4] = (KINDEX)(idx + IndexSizeY + 1);
00523 m_pMipMesh[m].m_pIndex[KSTMI_RIGHT][i + 5] = (KINDEX)(idx + IndexSizeY + 2);
00524
00525 i += 6;
00526 }
00527
00528 KASSERT( i == m_pMipMesh[m].m_nIndex[KSTMI_RIGHT] );
00529 }
00530
00531
00532
00533
00534 if( IndexSizeY > 1 )
00535 {
00536
00537
00538 m_pMipMesh[m].m_nIndex[KSTMI_MIP_RIGHT] = (IndexSizeY / 2) * 3 + (IndexSizeY - 2) * 3;
00539 m_pMipMesh[m].m_pIndex[KSTMI_MIP_RIGHT] = new KINDEX[ m_pMipMesh[m].m_nIndex[KSTMI_MIP_RIGHT] ];
00540
00541 i = 0;
00542
00543
00544 for( iy = 0; iy < IndexSizeY; iy += 2 )
00545 {
00546 idx = iy * (IndexSizeX + 1) + IndexSizeX;
00547
00548
00549 m_pMipMesh[m].m_pIndex[KSTMI_MIP_RIGHT][i + 0] = (KINDEX)(idx);
00550 m_pMipMesh[m].m_pIndex[KSTMI_MIP_RIGHT][i + 1] = (KINDEX)(idx + IndexSizeX);
00551 m_pMipMesh[m].m_pIndex[KSTMI_MIP_RIGHT][i + 2] = (KINDEX)(idx + IndexSizeX * 2 + 2);
00552
00553 i += 3;
00554 }
00555
00556 for( iy = 1; iy < IndexSizeY - 1; iy += 2 )
00557 {
00558 idx = iy * (IndexSizeX + 1) + IndexSizeX;
00559
00560
00561 m_pMipMesh[m].m_pIndex[KSTMI_MIP_RIGHT][i + 0] = (KINDEX)(idx - 1);
00562 m_pMipMesh[m].m_pIndex[KSTMI_MIP_RIGHT][i + 1] = (KINDEX)(idx + IndexSizeX);
00563 m_pMipMesh[m].m_pIndex[KSTMI_MIP_RIGHT][i + 2] = (KINDEX)(idx + IndexSizeX + 1);
00564
00565
00566 m_pMipMesh[m].m_pIndex[KSTMI_MIP_RIGHT][i + 3] = (KINDEX)(idx + IndexSizeX);
00567 m_pMipMesh[m].m_pIndex[KSTMI_MIP_RIGHT][i + 4] = (KINDEX)(idx + (IndexSizeX * 2) + 1);
00568 m_pMipMesh[m].m_pIndex[KSTMI_MIP_RIGHT][i + 5] = (KINDEX)(idx + IndexSizeX + 1);
00569
00570 i += 6;
00571 }
00572
00573 KASSERT( i == m_pMipMesh[m].m_nIndex[KSTMI_MIP_RIGHT] );
00574 }
00575 }
00576
00577
00578
00579
00580 BuildVertex();
00581
00582
00583 m_nIndexList = 0;
00584 for( u32 mi = 0; mi < KSTMI_COUNT; mi ++ )
00585 m_nIndexList += m_pMipMesh[0].m_nIndex[mi];
00586 m_pIndexList = new KINDEX[ m_nIndexList ];
00587
00588
00589 ComputeBBox();
00590 }
00591
00592
00593 KSubTileDraw::~KSubTileDraw()
00594 {
00595 for( u32 m = 0; m < m_nMipMesh; m ++ )
00596 {
00597 if( m_pMipMesh[m].m_pVertex )
00598 Deletev( m_pMipMesh[m].m_pVertex );
00599
00600 if( m_pIndexList )
00601 Deletev( m_pIndexList );
00602
00603 for( u32 i = 0; i < KSTMI_COUNT; i ++ )
00604 {
00605 if( m_pMipMesh[m].m_pIndex[i] )
00606 Deletev( m_pMipMesh[m].m_pIndex[i] );
00607 }
00608 }
00609 Deletev( m_pMipMesh );
00610 }
00611
00612
00613 bool KSubTileDraw::Init( KRender* pRender )
00614 {
00615
00616
00617
00618
00619 m_hShader = GetpTileDraw()->GetpRender()->GetpShaderBank()->CreateShader( "SubTile" );
00620 m_pShader = GetpTileDraw()->GetpRender()->GetpShaderBank()->GetpShader( m_hShader );
00621
00622 ReloadShader();
00623
00624
00625
00626 return true;
00627 }
00628
00629
00630 void KSubTileDraw::ReloadShader()
00631 {
00632 m_pShader->FlushAllStages();
00633
00634 if( m_pTextureName )
00635 {
00636
00637
00638
00639
00640 m_pShader->AddStage( m_pTextureName );
00641
00642
00643
00644
00645
00646 u32 Size = g_pGame->GetpIniFile()->ReadInt( "LANDSCAPE", "TextureSize", 1 );
00647 m_pShader->LoadTextures( Size );
00648 }
00649 }
00650
00651
00652 void KSubTileDraw::BuildVertex()
00653 {
00654 u32 MipValue;
00655
00656 u32 vtx;
00657
00658 u32 SizeX = TILE_NCELLS_X/TILE_NSUBTILES_X;
00659 u32 SizeY = TILE_NCELLS_Y/TILE_NSUBTILES_Y;
00660
00661 s32 CellX = (s32)(GetpTileDraw()->GetPosX() + m_PosX) / TILE_CELL_SIZE_X;
00662 s32 CellY = (s32)(GetpTileDraw()->GetPosY() + m_PosY) / TILE_CELL_SIZE_Y;
00663
00664 float u, v;
00665 u32 Angle;
00666
00667 KTILEHEIGHT Height;
00668
00669 for( u32 m = 0; m < m_nMipMesh; m ++ )
00670 {
00671
00672 MipValue = (u32)powf( 2, (float)m );
00673
00674 vtx = 0;
00675 for( u32 vy = 0; vy < SizeY + 1; vy += MipValue )
00676 {
00677 for( u32 vx = 0; vx < SizeX + 1; vx += MipValue )
00678 {
00679
00680
00681
00682
00683
00684
00685
00686
00687 GetpTileDraw()->GetpLandscape()->GetCellHeight( CellX + vx, CellY + vy, &Height );
00688
00689 m_pMipMesh[m].m_pVertex[vtx].Position = KVector( (float)m_PosX + vx * TILE_CELL_SIZE_X, (float)m_PosY + vy * TILE_CELL_SIZE_Y, (float)Height );
00690
00691 float r = ((float)rand() / (float)RAND_MAX);
00692 float g = ((float)rand() / (float)RAND_MAX);
00693 float b = ((float)rand() / (float)RAND_MAX);
00694
00695 u8 rr = 200 + (u8)(50.0f * r);
00696 u8 gg = 200 + (u8)(50.0f * g);
00697 u8 bb = 200 + (u8)(50.0f * b);
00698
00699
00700
00701 m_pMipMesh[m].m_pVertex[vtx].Normal = GetNormal( CellX + vx, CellY + vy );
00702
00703
00704
00705 Angle = (u32)m_MapAngle / 90;
00706 Angle *= 90;
00707 Angle %= 360;
00708
00709 switch( Angle )
00710 {
00711 case 0:
00712 u = (float)(vx / (float)SizeX);
00713 v = (float)(vy / (float)SizeY);
00714 break;
00715 case 90:
00716 u = (float)(vy / (float)SizeY);
00717 v = (float)(vx / (float)SizeX);
00718 break;
00719 case 180:
00720 u = 1.0f - (float)(vx / (float)SizeX);
00721 v = 1.0f - (float)(vy / (float)SizeY);
00722 break;
00723 case 270:
00724 u = 1.0f - (float)(vy / (float)SizeY);
00725 v = 1.0f - (float)(vx / (float)SizeX);
00726 break;
00727 }
00728
00729 m_pMipMesh[m].m_pVertex[vtx].tu1 = u;
00730 m_pMipMesh[m].m_pVertex[vtx].tv1 = v;
00731 m_pMipMesh[m].m_pVertex[vtx].tu2 = (float)(vx);
00732 m_pMipMesh[m].m_pVertex[vtx].tv2 = (float)(vy);
00733 vtx ++;
00734 }
00735 }
00736
00737
00738
00739 }
00740 }
00741
00742
00743 KVector KSubTileDraw::GetNormal( s32 CellX, s32 CellY )
00744 {
00745 KTILEHEIGHT h0, h1, h2, h3, h4, h5, h6;
00746 bool b0, b1, b2, b3, b4, b5, b6;
00747 KVector v0, v1, v2, v3, v4, v5, v6;
00748 KVector Normal( 0.0f, 0.0f, 0.0f );
00749 float n = 0;
00750
00751
00752 b0 = GetpTileDraw()->GetpLandscape()->GetCellHeight( CellX , CellY , &h0 );
00753 b1 = GetpTileDraw()->GetpLandscape()->GetCellHeight( CellX , CellY + 1 , &h1 );
00754 b2 = GetpTileDraw()->GetpLandscape()->GetCellHeight( CellX + 1 , CellY , &h2 );
00755 b3 = GetpTileDraw()->GetpLandscape()->GetCellHeight( CellX , CellY - 1 , &h3 );
00756 b4 = GetpTileDraw()->GetpLandscape()->GetCellHeight( CellX - 1 , CellY , &h4 );
00757 b5 = GetpTileDraw()->GetpLandscape()->GetCellHeight( CellX + 1 , CellY - 1 , &h5 );
00758 b6 = GetpTileDraw()->GetpLandscape()->GetCellHeight( CellX - 1 , CellY + 1 , &h6 );
00759
00760
00761 v0.x = 0.0f;
00762 v0.y = 0.0f;
00763 v0.z = (float)h0;
00764
00765 v1.x = 0.0f;
00766 v1.y = TILE_CELL_SIZE_Y;
00767 v1.z = (float)h1;
00768
00769 v2.x = TILE_CELL_SIZE_X;
00770 v2.y = 0.0f;
00771 v2.z = (float)h2;
00772
00773 v3.x = 0.0f;
00774 v3.y = -TILE_CELL_SIZE_Y;
00775 v3.z = (float)h3;
00776
00777 v4.x = -TILE_CELL_SIZE_X;
00778 v4.y = 0.0f;
00779 v4.z = (float)h4;
00780
00781 v5.x = TILE_CELL_SIZE_X;
00782 v5.y = TILE_CELL_SIZE_Y;
00783 v5.z = (float)h5;
00784
00785 v6.x = -TILE_CELL_SIZE_X;
00786 v6.y = -TILE_CELL_SIZE_Y;
00787 v6.z = (float)h6;
00788
00789
00790 if( b1 && b2 )
00791 {
00792 Normal += KVector::CrossProduct( v2 - v0, v1 - v0 );
00793 n += 1.0f;
00794 }
00795
00796 if( b2 && b3 )
00797 {
00798 Normal += KVector::CrossProduct( v3 - v0, v2 - v0 );
00799 n += 1.0f;
00800 }
00801
00802 if( b3 && b4 )
00803 {
00804 Normal += KVector::CrossProduct( v4 - v0, v3 - v0 );
00805 n += 1.0f;
00806 }
00807
00808 if( b4 && b1 )
00809 {
00810 Normal += KVector::CrossProduct( v1 - v0, v4 - v0 );
00811 n += 1.0f;
00812 }
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851 if( n == 0.0f )
00852 return KVector( 0.0f, 0.0f, 1.0f );
00853
00854
00855 Normal /= n;
00856 Normal.Normalize();
00857
00858 return Normal;
00859 }
00860
00861
00862 bool KSubTileDraw::GetHeight( s32 CellX, s32 CellY, KTILEHEIGHT* pHeight )
00863 {
00864
00865 if( ( CellX < 0 ) || ( CellX >= TILE_NCELLS_X ) || ( CellY < 0 ) || ( CellY >= TILE_NCELLS_Y ) )
00866 {
00867 *pHeight = 0;
00868 return false;
00869 }
00870
00871 *pHeight = GetpTileDraw()->GetHeight( CellX, CellY );
00872
00873 return true;
00874 }
00875
00876
00877
00878 void KSubTileDraw::ComputeBBox()
00879 {
00880 KTILEHEIGHT MinZ, MaxZ, h;
00881 u32 SizeX, SizeY;
00882 u32 CellPosX, CellPosY;
00883 float TilePosX, TilePosY;
00884
00885 MinZ = MAX_TILEHEIGHT;
00886 MaxZ = MIN_TILEHEIGHT;
00887
00888 SizeX = TILE_NCELLS_X/TILE_NSUBTILES_X;
00889 SizeY = TILE_NCELLS_Y/TILE_NSUBTILES_Y;
00890 CellPosX = (u32)m_PosX / TILE_CELL_SIZE_X;
00891 CellPosY = (u32)m_PosY / TILE_CELL_SIZE_Y;
00892
00893
00894 for( u32 sty = 0; sty < SizeY; sty ++ )
00895 {
00896 for( u32 stx = 0; stx < SizeX; stx ++ )
00897 {
00898 h = GetpTileDraw()->GetHeight( CellPosX + stx, CellPosY + sty );
00899
00900 if( h < MinZ )
00901 MinZ = h;
00902
00903 if( h > MaxZ )
00904 MaxZ = h;
00905 }
00906 }
00907
00908 TilePosX = GetpTileDraw()->GetPosX();
00909 TilePosY = GetpTileDraw()->GetPosY();
00910
00911 m_pBBox[0].x = TilePosX + m_PosX;
00912 m_pBBox[0].y = TilePosY + m_PosY;
00913 m_pBBox[0].z = MinZ;
00914 m_pBBox[1].x = TilePosX + m_PosX + SizeX * TILE_CELL_SIZE_X;
00915 m_pBBox[1].y = TilePosY + m_PosY;
00916 m_pBBox[1].z = MinZ;
00917 m_pBBox[2].x = TilePosX + m_PosX;
00918 m_pBBox[2].y = TilePosY + m_PosY + SizeY * TILE_CELL_SIZE_Y;
00919 m_pBBox[2].z = MinZ;
00920 m_pBBox[3].x = TilePosX + m_PosX + SizeX * TILE_CELL_SIZE_X;
00921 m_pBBox[3].y = TilePosY + m_PosY + SizeY * TILE_CELL_SIZE_Y;
00922 m_pBBox[3].z = MinZ;
00923
00924 m_pBBox[4].x = TilePosX + m_PosX;
00925 m_pBBox[4].y = TilePosY + m_PosY;
00926 m_pBBox[4].z = MaxZ;
00927 m_pBBox[5].x = TilePosX + m_PosX + SizeX * TILE_CELL_SIZE_X;
00928 m_pBBox[5].y = TilePosY + m_PosY;
00929 m_pBBox[5].z = MaxZ;
00930 m_pBBox[6].x = TilePosX + m_PosX;
00931 m_pBBox[6].y = TilePosY + m_PosY + SizeY * TILE_CELL_SIZE_Y;
00932 m_pBBox[6].z = MaxZ;
00933 m_pBBox[7].x = TilePosX + m_PosX + SizeX * TILE_CELL_SIZE_X;
00934 m_pBBox[7].y = TilePosY + m_PosY + SizeY * TILE_CELL_SIZE_Y;
00935 m_pBBox[7].z = MaxZ;
00936 }
00937
00938
00939 void KSubTileDraw::FlushIndexList()
00940 {
00941 m_nIndexListPos = 0;
00942 }
00943
00944
00945 void KSubTileDraw::AddIndexList( u32 MipIndices )
00946 {
00947 KASSERT( m_CurrentMipLevel < m_nMipMesh );
00948
00949 KSubTileDrawMipMesh* pMipMesh = &m_pMipMesh[m_CurrentMipLevel];
00950
00951 if( !pMipMesh->m_nIndex[MipIndices] )
00952 return;
00953
00954 KASSERT( pMipMesh->m_pIndex[MipIndices] );
00955 KASSERT( (m_nIndexListPos + pMipMesh->m_nIndex[MipIndices]) <= m_nIndexList );
00956
00957 memcpy( &m_pIndexList[m_nIndexListPos], pMipMesh->m_pIndex[MipIndices], pMipMesh->m_nIndex[MipIndices] * sizeof( KINDEX ) );
00958 m_nIndexListPos += pMipMesh->m_nIndex[MipIndices];
00959 }
00960
00961
00962 void KSubTileDraw::Draw()
00963 {
00964 KASSERT( m_CurrentMipLevel < m_nMipMesh );
00965
00966 KSubTileDrawMipMesh* pMipMesh = &m_pMipMesh[m_CurrentMipLevel];
00967 u32 nIndex = 0;
00968 s32 SubTileX = (s32)((GetpTileDraw()->GetPosX() + m_PosX) / TILE_SUBTILE_SIZE_X);
00969 s32 SubTileY = (s32)((GetpTileDraw()->GetPosY() + m_PosY) / TILE_SUBTILE_SIZE_Y);
00970 KSubTileDraw* pSubTile;
00971
00972
00973 FlushIndexList();
00974
00975
00976 AddIndexList( KSTMI_CENTER );
00977
00978
00979 pSubTile = GetpTileDraw()->GetpLandscapeDraw()->GetpSubTileDraw( SubTileX, SubTileY + 1 );
00980 if( pSubTile && (pSubTile->GetCurrentMipLevel() > m_CurrentMipLevel ) )
00981 AddIndexList( KSTMI_MIP_UP );
00982 else
00983 AddIndexList( KSTMI_UP );
00984
00985
00986 pSubTile = GetpTileDraw()->GetpLandscapeDraw()->GetpSubTileDraw( SubTileX, SubTileY - 1 );
00987 if( pSubTile && (pSubTile->GetCurrentMipLevel() > m_CurrentMipLevel ) )
00988 AddIndexList( KSTMI_MIP_DOWN );
00989 else
00990 AddIndexList( KSTMI_DOWN );
00991
00992
00993 pSubTile = GetpTileDraw()->GetpLandscapeDraw()->GetpSubTileDraw( SubTileX - 1, SubTileY );
00994 if( pSubTile && (pSubTile->GetCurrentMipLevel() > m_CurrentMipLevel ) )
00995 AddIndexList( KSTMI_MIP_LEFT );
00996 else
00997 AddIndexList( KSTMI_LEFT );
00998
00999
01000 pSubTile = GetpTileDraw()->GetpLandscapeDraw()->GetpSubTileDraw( SubTileX + 1, SubTileY );
01001 if( pSubTile && (pSubTile->GetCurrentMipLevel() > m_CurrentMipLevel ) )
01002 AddIndexList( KSTMI_MIP_RIGHT );
01003 else
01004 AddIndexList( KSTMI_RIGHT );
01005
01006 if( !m_nIndexListPos )
01007 return;
01008
01009 KRenderFace RenderFace;
01010
01011 GetpTileDraw()->GetpRender()->SetShader( m_hShader );
01012 GetpTileDraw()->GetpRender()->SetTextureStageState( 0, KRTSS_ADDRESSU, KRTD_MIRROR );
01013 GetpTileDraw()->GetpRender()->SetTextureStageState( 0, KRTSS_ADDRESSV, KRTD_MIRROR );
01014 RenderFace.m_VertexType = KRVERTEX2;
01015 RenderFace.m_nVertex = (u16)pMipMesh->m_nVertex;
01016 RenderFace.m_pVertex = pMipMesh->m_pVertex;
01017 RenderFace.m_nIndices = (u16)m_nIndexListPos;
01018 RenderFace.m_pIndices = m_pIndexList;
01019
01020
01021 GetpTileDraw()->GetpRender()->DrawTriangles( RenderFace );
01022
01023
01024
01025 }
01026
01027
01028 bool KSubTileDraw::GetRayIntersection( KVector& Orig, KVector& Dir, KVector* pPoint )
01029 {
01030 KVector p0, p1, p2;
01031 float t, u, v;
01032 KTILEHEIGHT Height;
01033
01034 s32 SizeX = (s32)TILE_NCELLS_X / TILE_NSUBTILES_X;
01035 s32 SizeY = (s32)TILE_NCELLS_Y / TILE_NSUBTILES_Y;
01036 s32 CellPosX = (s32)(m_PosX + GetpTileDraw()->GetPosX()) / TILE_CELL_SIZE_X;
01037 s32 CellPosY = (s32)(m_PosY + GetpTileDraw()->GetPosY()) / TILE_CELL_SIZE_Y;
01038
01039 for( s32 cy = 0; cy < SizeY; cy ++ )
01040 {
01041 for( s32 cx = 0; cx < SizeX; cx ++ )
01042 {
01043
01044 p0.x = (float)(CellPosX + cx) * TILE_CELL_SIZE_X;
01045 p0.y = (float)(CellPosY + cy) * TILE_CELL_SIZE_Y;
01046 GetpTileDraw()->GetpLandscapeDraw()->GetCellHeight( CellPosX + cx, CellPosY + cy, &Height );
01047 p0.z = (float)Height;
01048
01049 p1.x = (float)(CellPosX + cx) * TILE_CELL_SIZE_X;
01050 p1.y = (float)(CellPosY + cy + 1) * TILE_CELL_SIZE_Y;
01051 GetpTileDraw()->GetpLandscapeDraw()->GetCellHeight( CellPosX + cx, CellPosY + cy + 1, &Height );
01052 p1.z = (float)Height;
01053
01054 p2.x = (float)(CellPosX + cx + 1) * TILE_CELL_SIZE_X;
01055 p2.y = (float)(CellPosY + cy) * TILE_CELL_SIZE_Y;
01056 GetpTileDraw()->GetpLandscapeDraw()->GetCellHeight( CellPosX + cx + 1, CellPosY + cy, &Height );
01057 p2.z = (float)Height;
01058
01059 if( IntersectTriangleCullNone( Orig, Dir, p0, p1, p2, &t, &u, &v ) )
01060 {
01061 KVector Edge1 = p1 - p0;
01062 KVector Edge2 = p2 - p0;
01063 KVector Point = p0 + Edge1 * u + Edge2 * v;
01064
01065 *pPoint = Point;
01066
01067
01068
01069 return true;
01070 }
01071
01072
01073 p0.x = (float)(CellPosX + cx + 1) * TILE_CELL_SIZE_X;
01074 p0.y = (float)(CellPosY + cy) * TILE_CELL_SIZE_Y;
01075 GetpTileDraw()->GetpLandscapeDraw()->GetCellHeight( CellPosX + cx + 1, CellPosY + cy, &Height );
01076 p0.z = (float)Height;
01077
01078 p1.x = (float)(CellPosX + cx) * TILE_CELL_SIZE_X;
01079 p1.y = (float)(CellPosY + cy + 1) * TILE_CELL_SIZE_Y;
01080 GetpTileDraw()->GetpLandscapeDraw()->GetCellHeight( CellPosX + cx, CellPosY + cy + 1, &Height );
01081 p1.z = (float)Height;
01082
01083 p2.x = (float)(CellPosX + cx + 1) * TILE_CELL_SIZE_X;
01084 p2.y = (float)(CellPosY + cy + 1) * TILE_CELL_SIZE_Y;
01085 GetpTileDraw()->GetpLandscapeDraw()->GetCellHeight( CellPosX + cx + 1, CellPosY + cy + 1, &Height );
01086 p2.z = (float)Height;
01087
01088 if( IntersectTriangleCullNone( Orig, Dir, p0, p1, p2, &t, &u, &v ) )
01089 {
01090 KVector Edge1 = p1 - p0;
01091 KVector Edge2 = p2 - p0;
01092 KVector Point = p0 + Edge1 * u + Edge2 * v;
01093
01094 *pPoint = Point;
01095
01096
01097
01098 return true;
01099 }
01100 }
01101 }
01102
01103 return false;
01104 }