This file is indexed.

/usr/include/crystalspace-2.0/imesh/terrain2.h is in libcrystalspace-dev 2.0+dfsg-1build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
/*
  Copyright (C) 2006 by Kapoulkine Arseny
                2007 by Marten Svanfeldt

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free
  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef __CS_IMESH_TERRAIN2_H__
#define __CS_IMESH_TERRAIN2_H__

/**\file
 * Terrain2 interfaces
 */

#include "csutil/scf_interface.h"
#include "iutil/array.h"
#include "ivideo/shader/shader.h"
#include "imesh/object.h"

class csVector3;
struct csCollisionPair;
struct iCollider;
struct iTerrainCell;
struct iRenderView;
struct iTerrainSystem;
struct iMovable;

/**
 * Locked height data. This class holds an information needed to
 * fill/interpret height data. The elements are object-space heights
 * (that is, they are _not_ affected by cell.GetSize ().z).
 *
 * Two-dimensional height array is linearized, so additional math is needed
 * to get access to desired height values:
 * Instead of data[y][x], use data[y * pitch + x]
 */
struct csLockedHeightData
{
  /// height data array
  float* data;

  /// array pitch
  size_t pitch;	    
};

/**
 * Locked material data. This class holds an information needed to
 * fill/interpret material map data. The elements are indices of materials
 * in material palette.
 *
 * Two-dimensional material index array is linearized, so additional math is
 * needed to get access to desired values:
 * Instead of data[y][x], use data[y * pitch + x]
 */
struct csLockedMaterialMap
{
  /// material index data array
  unsigned char* data;	

  /// array pitch
  size_t pitch;	
};

/**
 * Locked normal data. This class holds an information needed to
 * fill/interpret normal data. The elements are object space normals.
 *
 * Two-dimensional normal array is linearized, so additional math is
 * needed to get access to desired values:
 * Instead of data[y][x], use data[y * pitch + x]
 */
struct csLockedNormalData
{
  /// normal data array
  csVector3* data;

  /// array pitch
  size_t pitch;	
};

/// Class for an array of csVector3. Used for communication with plugins.
struct iTerrainVector3Array : public iArrayChangeAll<csVector3>
{
  SCF_IARRAYCHANGEALL_INTERFACE(iTerrainVector3Array);
};

/// Class for an array of csCollisionPair. Used for communication with plugins.
struct iTerrainCollisionPairArray : public iArrayChangeAll<csCollisionPair>
{
  SCF_IARRAYCHANGEALL_INTERFACE(iTerrainCollisionPairArray);
};

/// Type of the material palette
typedef csRefArray<iMaterialWrapper> csTerrainMaterialPalette;


/**
 * This is a base class for per-cell collider-specific properties.
 * The classes which hold the collision-related data that is specific to a given
 * cell and collider.
 */
struct iTerrainCellCollisionProperties : public virtual iBase
{
  SCF_INTERFACE (iTerrainCellCollisionProperties, 2, 0, 1);

  /**
   * Get collidable flag (if it is not set, the cell does not collide with
   * anything).
   * 
   * \return collidable flag
   */
  virtual bool GetCollidable () const = 0;
  
  /**
   * Set collidable flag
   * 
   * \param value new flag value
   */
  virtual void SetCollidable (bool value) = 0;

  /**
   * Set named parameter
   *
   * \param param parameter name
   * \param value parameter value
   */
  virtual void SetParameter(const char* param, const char* value) = 0;

  /**
   * Get a copy of the properties object
   */
  virtual csPtr<iTerrainCellCollisionProperties> Clone () = 0;

  /// Get number of parameters this object has set
  virtual size_t GetParameterCount() = 0;

  /// Get name of a parameter
  virtual const char* GetParameterName (size_t index) = 0;

  //@{
  /// Get value of a parameter
  virtual const char* GetParameterValue (size_t index) = 0;
  virtual const char* GetParameterValue (const char* name) = 0;
  //@}
};

/**
 * This is a base class for per-cell renderer-specific properties.
 * The classes which hold the render-related data that is specific to a given
 * cell and renderer.
 * Also provides a shader variable context for the cell.
 */
struct iTerrainCellRenderProperties : public virtual iShaderVariableContext
{
  SCF_INTERFACE (iTerrainCellRenderProperties, 2, 0, 1);

  /**
   * Get visibility flag (if it is not set, the cell does not get rendered)
   * 
   * \return visibility flag
   */
  virtual bool GetVisible () const = 0;
  
  /**
   * Set visibility flag
   * 
   * \param value new flag value
   */
  virtual void SetVisible (bool value) = 0;
  
  /**
   * Set named parameter
   *
   * \param param parameter name
   * \param value parameter value
   */
  virtual void SetParameter (const char* param, const char* value) = 0;

  /**
   * Get a copy of the properties object
   */
  virtual csPtr<iTerrainCellRenderProperties> Clone () = 0;

  /// Get number of parameters this object has set
  virtual size_t GetParameterCount() = 0;

  /// Get name of a parameter
  virtual const char* GetParameterName (size_t index) = 0;

  //@{
  /// Get value of a parameter
  virtual const char* GetParameterValue (size_t index) = 0;
  virtual const char* GetParameterValue (const char* name) = 0;
  //@}
};

/**
 * This is a base class for per-cell feeder-specific properties.
 */
struct iTerrainCellFeederProperties : public virtual iBase
{
  SCF_INTERFACE (iTerrainCellFeederProperties, 3, 2, 0);
  
  /**
   * Set heightmap source.
   */
  virtual void SetHeightmapSource (const char* source, const char* format) = 0;

  /**
   * Set normalmap source.
   */
  virtual void SetNormalMapSource (const char* source) = 0;

  /**
   * Set materialmap source
   */
  virtual void SetMaterialMapSource (const char* source) = 0;

  /**
   * Set height offset
   */
  virtual void SetHeightOffset (float offset) = 0;

  /**
   * Add an explicit material/alpha-map pair
   */
  virtual void AddAlphaMap (const char* material, const char* alphaMapSource) = 0;

  /**
   * Set named parameter
   *
   * \param param parameter name
   * \param value parameter value
   */
  virtual void SetParameter (const char* param, const char* value) = 0;

  /**
   * Get a copy of the properties object
   */
  virtual csPtr<iTerrainCellFeederProperties> Clone () = 0;

  /// Get number of parameters this object has set
  virtual size_t GetParameterCount() = 0;

  /// Get name of a parameter
  virtual const char* GetParameterName (size_t index) = 0;

  //@{
  /// Get value of a parameter
  virtual const char* GetParameterValue (size_t index) = 0;
  virtual const char* GetParameterValue (const char* name) = 0;
  //@}


  /// Get number of alpha maps this object has set
  virtual size_t GetAlphaMapCount() = 0;

  /// Get material of an alpha map
  virtual const char* GetAlphaMapMaterial (size_t index) = 0;

  //@{
  /// Get source of an alpha map
  virtual const char* GetAlphaMapSource (size_t index) = 0;
  virtual const char* GetAlphaMapSource (const char* material) = 0;
  //@}

  //@{
  virtual void SetHeightmapSmooth (bool doSmooth) = 0;
  virtual bool GetHeightmapSmooth () const = 0;
  //@}
};

/**
 * Provides an interface for reading cell data
 */
struct iTerrainDataFeeder : public virtual iBase
{
  SCF_INTERFACE (iTerrainDataFeeder, 2, 0, 0);

  /**
   * Create an object that implements iTerrainCellFeederProperties
   * This object will be stored in the cell. This function gets invoked
   * at cells creation.
   *
   * \return properties object
   */
  virtual csPtr<iTerrainCellFeederProperties> CreateProperties () = 0;

  /**
   * Start cell data preloading (in case of threaded/async loading). This is
   * triggered by TerrainSystem::PreLoadCells, which is either called by user
   * or called automatically while rendering terrain.
   *
   * \param cell cell to start preloading for
   *
   * \return preloading success flag
   */
  virtual bool PreLoad (iTerrainCell* cell) = 0;
  
  /**
   * Load cell data. After the completion of this call the cell should have
   * all necessary information.
   *
   * \param cell cell to load
   *
   * \return loading success flag
   */
  virtual bool Load (iTerrainCell* cell) = 0;

  /**
   * Set feeder-dependent parameter
   *
   * \param param parameter name
   * \param value parameter value
   */
  virtual void SetParameter (const char* param, const char* value) = 0;
};

/**
 * Return structure for the
 * iTerrainCollider::CollideSegment(iTerrainCell*, const csVector3&, const csVector3&)
 * routine.
 */
struct csTerrainColliderCollideSegmentResult
{
  /// True if we hit.
  bool hit;

  /// Intersection point in world space.
  csVector3 isect;

  //@{
  /// Triangle we hit.
  csVector3 a, b, c;	
  //@}
  
  csTerrainColliderCollideSegmentResult()
   : hit (false), isect (0), a (0), b (0), c (0) {}
};

/// Provides an interface for custom collision
struct iTerrainCollider : public virtual iBase
{
  SCF_INTERFACE (iTerrainCollider, 3, 0, 0);

  /**
   * Create an object that implements iTerrainCellCollisionProperties
   * This object will be stored in the cell. This function gets invoked
   * at cells creation.
   *
   * \return properties object
   */
  virtual csPtr<iTerrainCellCollisionProperties> CreateProperties () = 0;
  
  /**
   * Collide segment with cell
   *
   * \param cell cell
   * \param start segment start (specified in object space)
   * \param end segment end (specified in object space)
   * \param oneHit if this is true, than stop on finding the first
   * intersection point (the closest to the segment start); otherwise, detect
   * all intersections
   * \param points destination point array
   * 
   * \return true if there were any intersections, false if there were none
   */
  virtual bool CollideSegment (iTerrainCell* cell, const csVector3& start,
                               const csVector3& end, bool oneHit, 
                               iTerrainVector3Array* points) = 0;

  /**
   * Collide segment with cell.
   * Stops on finding the first intersection point (the closest to the segment
   * start).
   * \param cell cell
   * \param start segment start (specified in object space)
   * \param end segment end (specified in object space)
   * \param hitPoint receives the intersection point
   * 
   * \return true if there was an intersections, false if there was none
   */
  virtual bool CollideSegment (iTerrainCell* cell, const csVector3& start,
                               const csVector3& end,
			       csVector3& hitPoint) = 0;
			       
  /**
   * Collide segment with cell
   *
   * \param cell cell
   * \param start segment start (specified in object space)
   * \param end segment end (specified in object space)
   * 
   * \return a csTerrainColliderCollideSegmentResult instance
   * indicating what we hit.
   */
  virtual csTerrainColliderCollideSegmentResult CollideSegment (
      iTerrainCell* cell, const csVector3& start, const csVector3& end) = 0;

  /**
   * Collide set of triangles with cell
   *
   * \param cell cell
   * \param vertices vertex array
   * \param tri_count triangle count
   * \param indices vertex indices, 3 indices for each triangle
   * \param radius radius of the bounding sphere surrounding the given set
   * of triangles (used for fast rejection)
   * \param trans triangle set transformation (vertices' coordinates are
   * specified in the space defined by this transformation)
   * \param oneHit if this is true, than stop on finding the first
   * collision pair; otherwise, detect all collisions
   * \param points destination collision pair array
   * 
   * \return true if there were any collisions, false if there were none
   */
  virtual bool CollideTriangles (iTerrainCell* cell, const csVector3* vertices,
                                 size_t tri_count,
                                 const unsigned int* indices, float radius,
                                 const csReversibleTransform& trans,
                                 bool oneHit, iTerrainCollisionPairArray* pairs) = 0;

  /**
   * Collide collider with cell
   *
   * \param cell cell
   * \param collider collider
   * \param radius radius of the bounding sphere surrounding the given set
   * of triangles (used for fast rejection)
   * \param trans triangle set transformation (vertices' coordinates are
   * specified in the space defined by this transformation)
   * \param oneHit if this is true, than stop on finding the first
   * collision pair; otherwise, detect all collisions
   * \param points destination collision pair array
   * 
   * \return true if there were any collisions, false if there were none
   */
  virtual bool Collide (iTerrainCell* cell, iCollider* collider,
                       float radius, const csReversibleTransform& trans,
                       bool oneHit, iTerrainCollisionPairArray* pairs) = 0;
};


/// Provides an interface for custom rendering
struct iTerrainRenderer : public virtual iBase
{
  SCF_INTERFACE (iTerrainRenderer, 3, 0, 0);

  /**
   * Create an object that implements iTerrainCellRenderProperties
   * This object will be stored in the cell. This function gets invoked
   * at cells creation.
   *
   * \return properties object
   */
  virtual csPtr<iTerrainCellRenderProperties> CreateProperties () = 0;

  /**
   * Connect to a given terrain system. 
   * Setup any per-terrain render data
   */
  virtual void ConnectTerrain (iTerrainSystem* system) = 0;

  /**
   * Disconnect from a given terrain system.
   */
  virtual void DisconnectTerrain (iTerrainSystem* system) = 0;


  /**
   * Render the visible cells
   *
   * \param n output value, that will contain the size of the resulting
   * mesh array
   * \param rview view that was used for rendering
   * \param movable the terrain object
   * \param frustum_mask frustum mask
   * \param cells array with visible cells
   * \param cell_count number of visible cells
   *
   * \return array of render meshes
   */
  virtual CS::Graphics::RenderMesh** GetRenderMeshes (int& n, iRenderView* rview,
                                   iMovable* movable, uint32 frustum_mask,
                                   const csArray<iTerrainCell*>& cells) = 0;

  
  /**
   * Indicates that the material palette has been changed, and that the
   * renderer should update its internal structures to reflect the changes.
   *
   * \param material_palette new material palette
   */
  virtual void OnMaterialPaletteUpdate (const csTerrainMaterialPalette&
                                        material_palette) = 0;

  /**
   * Indicates that the cells material mask has been changed (while
   * unlocking the cell material map data either by a feeder or by a user-
   * provided functions or while setting the new mask with the respective
   * functions), and that the renderer should update its internal structures
   * to reflect the changes.
   *
   * \param cell cell with the changed data   
   * \param rectangle rectangle that was updated
   * \param materialMap the updated material map
   * \param pitch data pitch
   */
  virtual void OnMaterialMaskUpdate (iTerrainCell* cell, 
    const csRect& rectangle, const unsigned char* materialMap, size_t pitch) = 0; 

  /**
   * Indicates that the cells material mask has been changed (while
   * unlocking the cell material map data either by a feeder or by a user-
   * provided functions or while setting the new mask with the respective
   * functions), and that the renderer should update its internal structures
   * to reflect the changes.
   *
   * \param cell cell with the changed data   
   * \param materialIdx specific material index
   * \param rectangle rectangle that was updated
   * \param materialMap the updated material map
   * \param pitch data pitch
   */
  virtual void OnMaterialMaskUpdate (iTerrainCell* cell, size_t materialIdx, 
    const csRect& rectangle, const unsigned char* materialMap, size_t pitch) = 0; 

  /**
   * Indicate that the cells alpha-map matching a given material have changed
   * and that the renderer should update its internal structures.
   *
   * \param cell cell with changed data
   * \param material material
   * \param alphaMap the alpha map
   */
  virtual void OnAlphaMapUpdate (iTerrainCell* cell,
    iMaterialWrapper* material, iImage* alphaMap) = 0;
};

/// Callbacks for cell height data modifications
struct iTerrainCellHeightDataCallback : public virtual iBase
{
  SCF_INTERFACE (iTerrainCellHeightDataCallback, 1, 0, 0);

  /**
   * Callback called when the height data of a terrain cell is modified.
   *
   * \param cell updated cell
   * \param rectangle rectangle of coordinates that were updated
   */
  virtual void OnHeightUpdate (iTerrainCell* cell, const csRect& rectangle) = 0;
};

/// Callbacks for cell load/unload events
struct iTerrainCellLoadCallback : public virtual iBase
{
  SCF_INTERFACE (iTerrainCellLoadCallback, 1, 0, 0);

  /**
   * Callback on loading of a terrain cell.
   *
   * \param cell loaded cell
   */
  virtual void OnCellLoad (iTerrainCell* cell) = 0;

  /**
   * Callback on pre-loading of a terrain cell.
   *
   * \param cell pre-loaded cell
   */
  virtual void OnCellPreLoad (iTerrainCell* cell) = 0;

  /**
   * Callback when unloading a terrain cell.
   *
   * \param cell unloaded cell
   */
  virtual void OnCellUnload (iTerrainCell* cell) = 0;
};

struct iTerrainFactoryCell;

/**
 * This class represents the terrain object as a set of cells. The object
 * can be rendered and collided with. To gain access to some operations that
 * are done at cell level you might want to use cell quering functions
 * (GetCell)
 */
struct iTerrainSystem : public virtual iBase
{
  SCF_INTERFACE (iTerrainSystem, 3, 0, 0);

  /**
   * Query a cell by name
   *
   * \param name name of cell
   * \param load set if cell should be loaded if it isn't. Default is not
   * to load cell data.
   * \return pointer to the cell with the given name, or NULL, if none found
   */
  virtual iTerrainCell* GetCell (const char* name, bool loadData = false) = 0;

  /**
   * Query a cell by position
   *
   * \param load set if cell should be loaded if it isn't. Default is not
   * to load cell data.
   * \return pointer to the first cell which intersects with the vertical ray
   * of given position, or NULL if none found
   *
   * \rem this will perform cell loading if the resulted cell was not
   * completely loaded
   */
  virtual iTerrainCell* GetCell (const csVector2& pos, bool loadData = false) = 0;

  /**
   * Query a cell by index (0 to GetCellCount ()).
   *
   * \param load set if cell should be loaded if it isn't. Default is not to
   * load cell data.
   */
  virtual iTerrainCell* GetCell (size_t index, bool loadData = false) = 0;

  /**
   * Get total number of cells in terrain (loaded or not)
   */
  virtual size_t GetCellCount () const = 0;

  /**
   * Get material palette. The material map indices index this array.
   *
   * \return material palette
   */
  virtual const csTerrainMaterialPalette& GetMaterialPalette () const = 0;
  
  /**
   * Set a new material palette.
   *
   * \param array new  material palette
   */
  virtual void SetMaterialPalette (const csTerrainMaterialPalette& array) = 0;

  /**
   * Collide segment with the terrain.
   * \param start segment start (specified in object space)
   * \param end segment end (specified in object space)
   * \param oneHit if this is true, than stop on finding the first
   * intersection point (the closest to the segment start); otherwise, detect
   * all intersections
   * \param points destination point array
   * 
   * \return true if there were any intersections, false if there were none
   *
   * \rem this will perform cell loading for the cells that potentially
   * collide with the segment
   *
   * \rem this will not perform collision for cells that have Collideable
   * property set to false
   */
  virtual bool CollideSegment (const csVector3& start, const csVector3& end,
                           bool oneHit, iTerrainVector3Array* points,
                           iMaterialArray* materials) = 0;
			   
  /**
   * Collide segment with the terrain.
   * Stops on finding the first intersection point (the closest to the segment
   * start).
   * \param start segment start (specified in object space)
   * \param end segment end (specified in object space)
   * \param hitPoint receives intersection point
   * \param hitMaterial receives material at intersection point if not null
   * 
   * \return true if there was an intersections, false if there were none
   *
   * \rem this will perform cell loading for the cells that potentially
   * collide with the segment
   *
   * \rem this will not perform collision for cells that have Collideable
   * property set to false
   */
  virtual bool CollideSegment (const csVector3& start, const csVector3& end,
			       csVector3& hitPoint,
			       iMaterialWrapper** hitMaterial) = 0;

  /**
   * Collide segment with the terrain
   *
   * \param start segment start (specified in object space)
   * \param end segment end (specified in object space)
   * \param use_ray if true then use a ray instead of a segment
   * (default false).
   * 
   * \return the intersection result.
   *
   * \rem this will perform cell loading for the cells that potentially
   * collide with the segment
   *
   * \rem this will not perform collision for cells that have Collideable
   * property set to false
   */
  virtual csTerrainColliderCollideSegmentResult CollideSegment (
      const csVector3& start, const csVector3& end,
      bool use_ray = false) = 0;

  /**
   * Collide set of triangles with the terrain
   *
   * \param vertices vertex array
   * \param tri_count triangle count
   * \param indices vertex indices, 3 indices for each triangle
   * \param radius radius of the bounding sphere surrounding the given set
   * of triangles (used for fast rejection)
   * \param trans triangle set transformation (vertices' coordinates are
   * specified in the space defined by this transformation)
   * \param oneHit if this is true, than stop on finding the first
   * collision pair; otherwise, detect all collisions
   * \param points destination collision pair array
   * 
   * \return true if there were any collisions, false if there were none
   *
   * \rem this will perform cell loading for the cells that potentially
   * collide with the triangle set
   *
   * \rem this will not perform collision for cells that have Collideable
   * property set to false
   */
  virtual bool CollideTriangles (const csVector3* vertices,
                       size_t tri_count,
                       const unsigned int* indices, float radius,
                       const csReversibleTransform& trans,
                       bool oneHit, iTerrainCollisionPairArray* pairs) = 0;

  /**
   * Collide collider with the terrain
   *
   * \param collider collider
   * \param radius radius of the bounding sphere surrounding the given set
   * of triangles (used for fast rejection)
   * \param trans triangle set transformation (vertices' coordinates are
   * specified in the space defined by this transformation)
   * \param oneHit if this is true, than stop on finding the first
   * collision pair; otherwise, detect all collisions
   * \param points destination collision pair array
   * 
   * \return true if there were any collisions, false if there were none
   *
   * \rem this will perform cell loading for the cells that potentially
   * collide with the collider
   *
   * \rem this will not perform collision for cells that have Collideable
   * property set to false
   */
  virtual bool Collide (iCollider* collider, float radius,
                       const csReversibleTransform& trans, bool oneHit,
                       iTerrainCollisionPairArray* pairs) = 0;

  /**
   * Get virtual view distance, that is, the distance from camera, at which
   * the cells are preloaded
   *
   * \return virtual view distance
   */
  virtual float GetVirtualViewDistance () const = 0;
  
  /**
   * Set virtual view distance, that is, the distance from camera, at which
   * the cells are preloaded
   *
   * \param distance new virtual view distance
   */
  virtual void SetVirtualViewDistance (float distance) = 0;

  /**
   * Get automatic preload flag. If it is set, then PreLoadCells is called
   * when rendering an object. Otherwise, you have to call it yourself if
   * you want cell streaming. The default value is true.
   *
   * \return automatic preload flag
   */
  virtual bool GetAutoPreLoad () const = 0;
  
  /**
   * Set automatic preload flag.
   *
   * \param mode new automatic preload flag
   */
  virtual void SetAutoPreLoad (bool mode) = 0;

  /**
   * Preload all cells that are in the 'virtual view' (that is, the given
   * view, extended to virtual view distance). Preloading is feeder-
   * dependent (that is, cell feeders are free to either implement or not
   * implement it).
   *
   * \param rview real view
   * \param movable terrain object
   *
   * \rem this will not perform preloading for cells that have Visible
   * property set to false
   */
  virtual void PreLoadCells (iRenderView* rview, iMovable* movable) = 0;
  
  /**
   * Query height doing bilinear interpolation. This is equivalent to doing
   * an intersection with vertical ray, except that it is faster.
   *
   * \param pos object-space position.
   *
   * \return height value
   *
   * \rem this will perform cell loading for the cell that is used to sample
   * height value
   */
  virtual float GetHeight (const csVector2& pos) = 0;
  
  /**
   * Get tangent with bilinear interpolation.
   *
   * \param pos object-space position.
   *
   * \return tangent value
   *
   * \rem this will perform cell loading for the cell that is used to sample
   * tangent value
   */
  virtual csVector3 GetTangent (const csVector2& pos) = 0;
  
  /**
   * Get binormal with bilinear interpolation.
   *
   * \param pos object-space position.
   *
   * \return binormal value
   *
   * \rem this will perform cell loading for the cell that is used to sample
   * binormal value
   */
  virtual csVector3 GetBinormal (const csVector2& pos) = 0;

  /**
   * Get normal with bilinear interpolation.
   *
   * \param pos object-space position.
   *
   * \return normal value
   *
   * \rem this will perform cell loading for the cell that is used to sample
   * normal value
   */
  virtual csVector3 GetNormal (const csVector2& pos) = 0;

  /**
   * Get maximum number of loaded cells
   *
   * \return maximum number of loaded cells
   */
  virtual size_t GetMaxLoadedCells () const = 0;

  /**
   * Set maximum number of loaded cells. If the number of loaded cells becomes
   * greater than this value (in the process of cell loading), the cell with
   * least recent usage is unloaded.
   *
   * \param value maximum number of loaded cells
   */
  virtual void SetMaxLoadedCells (size_t value) = 0;

  /**
   * Unload cells to satisfy the requirement of max loaded cell count
   */
  virtual void UnloadOldCells () = 0;

  /**
   * Add a listener to the cell load/unload callback
   */
  virtual void AddCellLoadListener (iTerrainCellLoadCallback* cb) = 0;

  /**
   * Remove a listener to the cell load/unload callback
   */
  virtual void RemoveCellLoadListener (iTerrainCellLoadCallback* cb) = 0;
  
  /**
   * Add a listener to the cell height update callback
   */
  virtual void AddCellHeightUpdateListener (iTerrainCellHeightDataCallback* cb) = 0;

  /**
   * Remove a listener to the cell height update callback
   */
  virtual void RemoveCellHeightUpdateListener (iTerrainCellHeightDataCallback* cb) = 0;

  /**
   * Add a cell to the terrain instance based on the given iTerrainFactoryCell.
   *
   * \return added cell
   * \rem If you change the renderer, collider or feeder after adding cells
   * you might get into trouble.
   */
  virtual iTerrainCell* AddCell (iTerrainFactoryCell*) = 0;

  /**
   * Remove the given cell from this instance
   */
  virtual void RemoveCell (iTerrainCell*) = 0;
};

/**
 * Terrain cell class. Terrain consists of cells, each cell has its own
 * coordinate system (2-axis position and 3-axis scaling). All operations
 * (loading, preloading, destroying, construction of inner structures for
 * rendering, etc.) are done at cell level.
 *
 * A cell can be created via iTerrainFactory interface.
 */
struct iTerrainCell : public virtual iBase
{
  SCF_INTERFACE (iTerrainCell, 6, 0, 0);

  /// Enumeration that specifies current cell state
  enum LoadState
  {
    NotLoaded,    /**< cell is not loaded in memory, do not do any operations
                       with it directly */
    PreLoaded,    /**< cell is in preload state, do not do any operations with 
                       it directly */
    Loaded        ///< cell is loaded, you can use it as you like
  };

  /**
   * Get cell's current loading state.
   *
   * \return cell's current loading state
   */
  virtual LoadState GetLoadState () const = 0;

  /**
   * Set cell's current loading state.
   *
   * If the cell's current state is equal to the passed state, nothing happens.
   * If the cell was not loaded (NotLoaded state), then it is put into the
   * passed state (either preloading or loading is started)
   * If the cell was loaded, then it is unloaded in case of NotLoaded state.
   * Passing PreLoaded state has no effect.
   * If the cell was being preloaded, then it is loaded in case of Loaded state.
   * Passing NotLoaded state has no effect (note, that if you want to stop
   * preloading, you'll have to finish it (SetLoadState (Loaded)) and then
   * unload the cell (SetLoadState (NotLoaded)).)
   *
   * \param state cell's new loading state
   */
  virtual void SetLoadState (LoadState state) = 0;

  /**
   * Get the terrain to which the cell belongs
   *
   * \return terrain object
   */
  virtual iTerrainSystem* GetTerrain () = 0;

  /**
   * Get cell name. It is specified at creation time and may be 0.
   * The name is used only for cell identification purposes (i.e. to get
   * the needed cell from a terrain, see iTerrainSystem::GetCell)
   *
   * \return cell name
   */
  virtual const char* GetName () const = 0;

  /**
   * Get cell rendering properties. Returns pointer to a renderer-specific
   * class, though it is possible to check/change some general properties.
   *
   * \return cell rendering properties
   */
  virtual iTerrainCellRenderProperties* GetRenderProperties () const = 0;
  
  /**
   * Get cell collision properties. Returns pointer to a collider-specific
   * class, though it is possible to check/change some general properties.
   *
   * \return cell collision properties
   */
  virtual iTerrainCellCollisionProperties* GetCollisionProperties () const = 0;

  /**
   * Get cell feeder properties. Returns pointer to a feeder-specific class
   * though it is possible to check/change some general properties.
   *
   * \return cell feeder properties
   */
  virtual iTerrainCellFeederProperties* GetFeederProperties () const = 0;

  /**
   * Get grid width. It is the width of an array of height data.
   * You can expect it to be 2^n + 1.
   *
   * \return grid width
   */
  virtual int GetGridWidth () const = 0;
  
  /**
   * Get grid height. It is the height of an array of height data.
   * You can expect it to be 2^n + 1 (note: it is equal to grid width)
   *
   * \return grid height
   */
  virtual int GetGridHeight () const = 0;

  /**
   * Get height data (for reading purposes: do not modify it!)
   * This can be used to perform very fast height lookups.
   *
   * \return cell height data
   */
  virtual csLockedHeightData GetHeightData () = 0;
  
  /**
   * Lock an area of height data (for reading/writing purposes)
   * This can be used for terrain deforming.
   * If you want to lock the whole cell, use the rectangle
   * csRect(0, 0, grid width, grid height).
   *
   * Only one area may be locked at a time, locking more than once results in
   * undefined behaviour.
   *
   * \param rectangle the rectangle which you want to lock.
   *
   * \return cell height data
   */
  virtual csLockedHeightData LockHeightData (const csRect& rectangle) = 0;
  
  /**
   * Commit changes to height data. Use it after changing the desired height values.
   *
   * Unlocking the cell that was not locked results in undefined behaviour
   */
  virtual void UnlockHeightData () = 0;

  /**
   * Get normal data (for reading purposes: do not modify it!)
   * This can be used to perform very fast normal lookups.
   *
   * \return cell normal data
   */
  virtual csLockedNormalData GetNormalData () = 0;
  
  /**
   * Lock an area of normal data (for reading/writing purposes)
   * If you want to lock the whole cell, use the rectangle
   * csRect(0, 0, grid width, grid height).
   *
   * Only one area may be locked at a time, locking more than once results in
   * undefined behaviour.
   *
   * \param rectangle the rectangle which you want to lock.
   *
   * \return cell normal data
   */
  virtual csLockedNormalData LockNormalData (const csRect& rectangle) = 0;
  
  /**
   * Commit changes to height data. Use it after changing the desired height values.
   *
   * Unlocking the cell that was not locked results in undefined behaviour
   */
  virtual void UnlockNormalData () = 0;

  /**
   * Recalculates the cell normals.
   */
  virtual void RecalculateNormalData () = 0;

  /**
   * Get cell position (in object space). X and Y components specify the
   * offsets along X and Z axes, respectively.
   *
   * \return cell position
   */
  virtual const csVector2& GetPosition () const = 0;
  
  /**
   * Get cell size (in object space). X and Y components specify the
   * sizes along X and Z axes, respectively. Z component specifies height
   * scale (warning: it is used only at loading stage, after that all scales
   * are in object space).
   *
   * \return cell size
   */
  virtual const csVector3& GetSize () const = 0;

  /**
   * Get material map width (essentially a width of both material array and
   * material masks, if any).
   *
   * \return material map width
   */
  virtual int GetMaterialMapWidth () const = 0;
  
  /**
   * Get material map height (essentially a height of both material array and
   * material masks, if any).
   *
   * \return material map height
   */
  virtual int GetMaterialMapHeight () const = 0;

  /**
   * Get material persistent flag. If it is true, material data is stored in
   * the cell (that makes updating material data faster and makes material data
   * lock read/write, but it means larger memory overhead)
   */
  virtual bool GetMaterialPersistent() const = 0;

  /**
   * Lock an area of material map (practically write-only, reading the
   * values will not produce sensible values if you did not just write
   * them that is, the returned block memory is a read-write one, but
   * it is a temporary block of memory filled with garbage).
   * Note, that if you created cell with 'material_persistent' flag, the
   * lock is read/write.
   *
   * If you want to lock the whole cell, use the rectangle
   * csRect(0, 0, material map width, material map height).
   *
   * Only one area may be locked at a time, locking more than once results in
   * undefined behaviour.
   *
   * \param rectangle the rectangle which you want to lock.
   *
   * \return cell material data
   */
  virtual csLockedMaterialMap LockMaterialMap (const csRect& rectangle) = 0;

  /**
   * Commit changes to material data. Use it after setting the desired
   * material map values.
   *
   * Unlocking the cell that was not locked results in undefined behaviour
   *
   * This updates the material masks with appropriate values.
   */
  virtual void UnlockMaterialMap() = 0;

  /**
   * Set new material mask for the specified material.
   *
   * This function will do image rescaling if needed (i.e. if material map
   * dimensions and image dimensions do not match).
   *
   * \param material material index
   * \param image an image of format CS_IMGFMT_PALETTED8
   */
  virtual void SetMaterialMask (unsigned int material, iImage* image) = 0;
  
  /**
   * Set new material mask for the specified material.
   *
   * This function will do image rescaling if needed (i.e. if material map
   * dimensions and image dimensions do not match).
   *
   * \param material material index
   * \param data linearized array with material indices
   * \param width image width
   * \param height image height
   */
  virtual void SetMaterialMask (unsigned int material, const unsigned char*
                          data, unsigned int width, unsigned int height) = 0;
  
  /**
   * Set alpha mask for a specified material.
   *
   * \param material the material
   * \param alphaMap the alpha map to use
   */
  virtual void SetAlphaMask (iMaterialWrapper* material, iImage* alphaMap) = 0;

  /**
   * Set base material for the cell.
   *
   * \param material material handle of base material
   */
  virtual void SetBaseMaterial (iMaterialWrapper* material) = 0;

  /**
   * Get base material for the cell
   */
  virtual iMaterialWrapper* GetBaseMaterial () const = 0;

  /**
   * Set the optional alpha-splat material for the cell.
   *
   * \param material material handle of the alpha-splat material.
   */
  virtual void SetAlphaSplatMaterial (iMaterialWrapper* material) = 0;

  /**
   * Get the optional alpha-splat material for the cell.
   *
   * \return nullptr if no material, else the material.
   */
  virtual iMaterialWrapper* GetAlphaSplatMaterial () const = 0;

  /**
   * Collide segment with cell (using the collider)
   *
   * \param start segment start (specified in object space)
   * \param end segment end (specified in object space)
   * \param oneHit if this is true, than stop on finding the first
   * intersection point (the closest to the segment start); otherwise, detect
   * all intersections
   * \param points destination point array
   * 
   * \return true if there were any intersections, false if there were none
   */
  virtual bool CollideSegment (const csVector3& start, const csVector3& end,
                           bool oneHit, iTerrainVector3Array* points) = 0;

  /**
   * Collide segment with cell.
   * Stops on finding the first intersection point (the closest to the segment
   * start).
   * \param cell cell
   * \param start segment start (specified in object space)
   * \param end segment end (specified in object space)
   * \param hitPoint receives the intersection point
   * 
   * \return true if there was an intersections, false if there was none
   */
  virtual bool CollideSegment (const csVector3& start, const csVector3& end,
			       csVector3& hitPoint) = 0;

  /**
   * Collide set of triangles with cell (using the collider)
   *
   * \param vertices vertex array
   * \param tri_count triangle count
   * \param indices vertex indices, 3 indices for each triangle
   * \param radius radius of the bounding sphere surrounding the given set
   * of triangles (used for fast rejection)
   * \param trans triangle set transformation (vertices' coordinates are
   * specified in the space defined by this transformation)
   * \param oneHit if this is true, than stop on finding the first
   * collision pair; otherwise, detect all collisions
   * \param points destination collision pair array
   * 
   * \return true if there were any collisions, false if there were none
   */
  virtual bool CollideTriangles (const csVector3* vertices,
                       size_t tri_count,
                       const unsigned int* indices, float radius,
                       const csReversibleTransform& trans,
                       bool oneHit, iTerrainCollisionPairArray* pairs) = 0;

  /**
   * Collide collider with cell (using the collider)
   *
   * \param collider collider
   * \param radius radius of the bounding sphere surrounding the given set
   * of triangles (used for fast rejection)
   * \param trans triangle set transformation (vertices' coordinates are
   * specified in the space defined by this transformation)
   * \param oneHit if this is true, than stop on finding the first
   * collision pair; otherwise, detect all collisions
   * \param points destination collision pair array
   * 
   * \return true if there were any collisions, false if there were none
   */
  virtual bool Collide (iCollider* collider, float radius,
                       const csReversibleTransform& trans, bool oneHit,
                       iTerrainCollisionPairArray* pairs) = 0;

  /**
   * Query height, that is, do a lookup on height table. For a set of
   * lookups, use GetHeightData for efficiency reasons.
   *
   * \param x x coordinate (from 0 to grid width - 1 all inclusive)
   * \param y y coordinate (from 0 to grid height - 1 all inclusive)
   *
   * \return height value
   */
  virtual float GetHeight (int x, int y) const = 0;

  /**
   * Query height doing bilinear interpolation. This is equivalent to doing
   * an intersection with vertical ray, except that it is faster.
   *
   * \param pos object-space position.
   *
   * \return height value
   */
  virtual float GetHeight (const csVector2& pos) const = 0;
  
  /**
   * Get tangent value.
   *
   * \param x x coordinate (from 0 to grid width - 1 all inclusive)
   * \param y y coordinate (from 0 to grid height - 1 all inclusive)
   *
   * \return tangent value
   */
  virtual csVector3 GetTangent (int x, int y) const = 0;
  
  /**
   * Get tangent with bilinear interpolation.
   *
   * \param pos object-space position.
   *
   * \return tangent value
   */
  virtual csVector3 GetTangent (const csVector2& pos) const = 0;

  /**
   * Get binormal value.
   *
   * \param x x coordinate (from 0 to grid width - 1 all inclusive)
   * \param y y coordinate (from 0 to grid height - 1 all inclusive)
   *
   * \return binormal value
   */
  virtual csVector3 GetBinormal (int x, int y) const = 0;
  
  /**
   * Get binormal with bilinear interpolation.
   *
   * \param pos object-space position.
   *
   * \return binormal value
   */
  virtual csVector3 GetBinormal (const csVector2& pos) const = 0;

  /**
   * Get normal value.
   *
   * \param x x coordinate (from 0 to grid width - 1 all inclusive)
   * \param y y coordinate (from 0 to grid height - 1 all inclusive)
   *
   * \return normal value
   */
  virtual csVector3 GetNormal (int x, int y) const = 0;
  
  /**
   * Get normal with bilinear interpolation.
   *
   * \param pos object-space position.
   *
   * \return normal value
   */
  virtual csVector3 GetNormal (const csVector2& pos) const = 0;

  /// Get render-specific data. Only to be used by renderer plugin.
  virtual csRefCount* GetRenderData () const = 0;

  /// Set render-specific data. Only to be used by renderer plugin.
  virtual void SetRenderData (csRefCount* data) = 0;

  /// Get collider-specific data. Only to be used by collision plugin.
  virtual csRefCount* GetCollisionData () const = 0;

  /// Set collider-specific data. Only to be used by collision plugin.
  virtual void SetCollisionData (csRefCount* data) = 0;

  /// Get feeder-specific data. Only to be used by feeder plugin.
  virtual csRefCount* GetFeederData () const = 0;

  /// Set feeder-specific data. Only to be used by feeder plugin.
  virtual void SetFeederData (csRefCount* data) = 0;

  /**
   * Set name of this cell.
   * \warning The cell name is used to map object cells to factory cells.
   *   Changing the name of a cell does not change any existing mappings,
   *   however, it will take effect when saving the mesh. If that is done
   *   careless changing of cell names can confuse the mapping of cells.
   */
  virtual void SetName (const char* name) = 0;

  /**
   * Set optional splat base material for the cell.
   * The splat base material is rendered before splatting or
   * alpha-splatting is rendered for the cell.
   * \param material material handle of spalt base material.
   */
  virtual void SetSplatBaseMaterial (iMaterialWrapper* material) = 0;
  
  /// Get splat base material for the cell.
  virtual iMaterialWrapper* GetSplatBaseMaterial () const = 0;

  /**
   * Get tangent data (for reading purposes: do not modify it!).
   * \return cell tangent data
   */
  virtual csLockedNormalData GetTangentData () = 0;
  
  /**
   * Get tangent data (for reading purposes: do not modify it!).
   * \return cell tangent data
   */
  virtual csLockedNormalData GetBitangentData () = 0;
};

/// Factory representation of a cell
struct iTerrainFactoryCell : public virtual iBase
{
  SCF_INTERFACE (iTerrainFactoryCell, 2, 0, 1);

  /**
   * Get cell rendering properties. Returns pointer to a renderer-specific
   * class, though it is possible to check/change some general properties.
   *
   * \return cell rendering properties
   */
  virtual iTerrainCellRenderProperties* GetRenderProperties () const = 0;
  
  /**
   * Get cell collision properties. Returns pointer to a collider-specific
   * class, though it is possible to check/change some general properties.
   *
   * \return cell collision properties
   */
  virtual iTerrainCellCollisionProperties* GetCollisionProperties () const = 0;

  /**
   * Get cell feeder properties. Returns pointer to a feeder-specific class
   * though it is possible to check/change some general properties.
   *
   * \return cell feeder properties
   */
  virtual iTerrainCellFeederProperties* GetFeederProperties () const = 0;

  /**
   * Set base material for the cell.
   *
   * \param material material handle of base material.
   */
  virtual void SetBaseMaterial (iMaterialWrapper* material) = 0;

  /**
   * Set the optional alpha-splat material for the cell.
   *
   * \param material material handle of the alpha-splat material.
   */
  virtual void SetAlphaSplatMaterial (iMaterialWrapper* material) = 0;

  /// Get name of this cell
  virtual const char* GetName() = 0;

  /// Set name of this cell
  virtual void SetName (const char* name) = 0;

  /**
   * Get grid width. It is the width of an array of height data.
   * You can expect it to be 2^n + 1.
   *
   * \return grid width
   */
  virtual int GetGridWidth () const = 0;
  
  /**
   * Get grid height. It is the height of an array of height data.
   * You can expect it to be 2^n + 1 (note: it is equal to grid width)
   *
   * \return grid height
   */
  virtual int GetGridHeight () const = 0;

  /**
   * Get cell position (in object space). X and Y components specify the
   * offsets along X and Z axes, respectively.
   *
   * \return cell position
   */
  virtual const csVector2& GetPosition () const = 0;
  
  /**
   * Get cell size (in object space). X and Y components specify the
   * sizes along X and Z axes, respectively. Z component specifies height
   * scale (warning: it is used only at loading stage, after that all scales
   * are in object space).
   *
   * \return cell size
   */
  virtual const csVector3& GetSize () const = 0;

  /**
   * Get material map width (essentially a width of both material array and
   * material masks, if any).
   *
   * \return material map width
   */
  virtual int GetMaterialMapWidth () const = 0;
  
  /**
   * Get material map height (essentially a height of both material array and
   * material masks, if any).
   *
   * \return material map height
   */
  virtual int GetMaterialMapHeight () const = 0;

  /**
   * Get base material for the cell.
   */
  virtual iMaterialWrapper* GetBaseMaterial () const = 0;

  /**
   * Get the optional alpha-splat material for the cell.
   *
   * \return nullptr if no material, else the material.
   */
  virtual iMaterialWrapper* GetAlphaSplatMaterial () const = 0;

  /**
   * Get material persistent flag. If it is true, material data is stored in
   * the cell (that makes updating material data faster and makes material data
   * lock read/write, but it means larger memory overhead)
   */
  virtual bool GetMaterialPersistent() const = 0;

  /**
   * Set grid width. It will be changed to match the grid
   * width requirements`- it will be 2^n + 1.
   */
  virtual void SetGridWidth (int w) = 0;
  
  /**
   * Set grid height. It will be changed to match the grid
   * width requirements`- equal to grid width.
   */
  virtual void SetGridHeight (int h) = 0;

  /**
   * Set cell position (in object space). X and Y components specify the
   * offsets along X and Z axes, respectively.
   */
  virtual void SetPosition (const csVector2& pos) = 0;
  
  /**
   * Set cell size (in object space). X and Y components specify the
   * sizes along X and Z axes, respectively. Z component specifies height
   * scale (warning: it is used only at loading stage, after that all scales
   * are in object space).
   */
  virtual void SetSize (const csVector3& size) = 0;

  /**
   * Set material map width (essentially a width of both material array and
   * material masks, if any).
   */
  virtual void SetMaterialMapWidth (int w) = 0;
  
  /**
   * Set material map height (essentially a height of both material array and
   * material masks, if any).
   */
  virtual void SetMaterialMapHeight (int h) = 0;

  /**
   * Set material persistent flag. 
   * \sa GetMaterialPersistent
   */
  virtual void SetMaterialPersistent (bool flag) = 0;

  /**
   * Set optional splat base material for the cell.
   * The splat base material is rendered before splatting or
   * alpha-splatting is rendered for the cell.
   * \param material material handle of spalt base material.
   */
  virtual void SetSplatBaseMaterial (iMaterialWrapper* material) = 0;
  
  /// Get splat base material for the cell.
  virtual iMaterialWrapper* GetSplatBaseMaterial () const = 0;
};

/// Provides an interface for creating terrain system
struct iTerrainFactory : public virtual iBase
{
  SCF_INTERFACE (iTerrainFactory, 2, 0, 3);

  /**
   * Set desired renderer (there is a single renderer for the whole terrain)
   *
   * \param renderer new renderer
   */
  virtual void SetRenderer (iTerrainRenderer* renderer) = 0;
  
  /**
   * Set desired collider (there is a single collider for the whole terrain)
   *
   * \param collider new collider
   */
  virtual void SetCollider (iTerrainCollider* collider) = 0;

  /**
   * Set desired feeder (there is a single feeder for the whole terrain)
   *
   * \param feeder new feeder
   */
  virtual void SetFeeder (iTerrainDataFeeder* feeder) = 0;
  
  /**
   * Add cell to the terrain
   *
   * \param name optional cell name
   * \param grid_width grid width. It will be changed to match the grid
   * width requirements. See iTerrainCell::GetGridWidth
   * \param grid_height grid height. It will be changed to match the grid
   * height requirements. See iTerrainCell::GetGridHeight
   * \param material_width material map width
   * \param material_height material map height
   * \param material_persistent true if you want to store material data
   * (that makes updating material data faster and makes material data lock
   * read/write, but it means larger memory overhead)
   * \param position cell object-space position
   * \param size cell object-space size and height scale
   *
   * \return added cell
   * \rem If you change the renderer, collider or feeder after adding cells
   * you might get into trouble.
   */
  virtual iTerrainFactoryCell* AddCell (const char* name, 
    int gridWidth, int gridHeight, int materialMapWidth,
    int materialMapHeight, bool materiaMapPersistent,
    const csVector2& position, const csVector3& size) = 0;
  
  /**
   * Set maximum number of loaded cells. See iTerrainSystem::SetMaxLoadedCells
   *
   * \param number maximum number of loaded cells
   */
  virtual void SetMaxLoadedCells (size_t number) = 0;
  
  /**
   * Set virtual view distance, that is, the distance from camera, at which
   * the cells are preloaded
   *
   * \param distance new virtual view distance
   */
  virtual void SetVirtualViewDistance (float distance) = 0;
  
  /**
   * Set automatic preload flag.
   *
   * \param mode new automatic preload flag
   */
  virtual void SetAutoPreLoad (bool mode) = 0;


  /**
   * Get renderer for the whole terrain
   */
  virtual iTerrainRenderer* GetRenderer () = 0;
  
  /**
   * Get collider for the whole terrain
   */
  virtual iTerrainCollider* GetCollider () = 0;

  /**
   * Set feeder for the whole terrain
   */
  virtual iTerrainDataFeeder* GetFeeder () = 0;

  /**
   * Get maximum number of loaded cells.
   * \param number maximum number of loaded cells
   */
  virtual size_t GetMaxLoadedCells () = 0;

  /// Get number of cells in this factory
  virtual size_t GetCellCount () = 0;

  /// Get a cell in this factory
  virtual iTerrainFactoryCell* GetCell (size_t index) = 0;

  /// Get pseudo-cell with default settings for all cells
  virtual iTerrainFactoryCell* GetDefaultCell () = 0;

  /**
   * Add cell to the terrain
   *
   * \return added cell
   * \rem If you change the renderer, collider or feeder after adding cells
   * you might get into trouble.
   */
  virtual iTerrainFactoryCell* AddCell () = 0;

  /// Get a cell in this factory by name
  virtual iTerrainFactoryCell* GetCell (const char* name) = 0;

  /// Remove the given cell from this factory
  virtual void RemoveCell (iTerrainFactoryCell*) = 0;
};


#endif