| 628 | } |
| 629 | |
| 630 | FORCE_INLINE byte GetPhysicalMaterial(const Color32& raw, const TerrainDataUpdateInfo& info, int32 chunkZ, int32 chunkX, int32 z, int32 x) |
| 631 | { |
| 632 | byte result = 0; |
| 633 | if (ReadIsHole(raw)) |
| 634 | { |
| 635 | // Hole |
| 636 | result = (uint8)PhysicsBackend::HeightFieldMaterial::Hole; |
| 637 | } |
| 638 | else if (info.SplatMaps[0]) |
| 639 | { |
| 640 | // Use the layer with the highest influence (splatmap data is Mip0 so convert x/z coords back to LOD0) |
| 641 | uint8 layer = 0; |
| 642 | uint8 layerWeight = 0; |
| 643 | const int32 splatmapTextureIndex = (chunkZ * info.ChunkSize + z) * info.HeightmapSize + chunkX * info.ChunkSize + x; |
| 644 | ASSERT(splatmapTextureIndex < info.HeightmapLength); |
| 645 | for (int32 splatIndex = 0; splatIndex < TERRAIN_MAX_SPLATMAPS_COUNT; splatIndex++) |
| 646 | { |
| 647 | for (int32 channelIndex = 0; channelIndex < 4; channelIndex++) |
| 648 | { |
| 649 | // Assume splatmap data pitch matches the row size and shift by channel index to simply sample at R chanel |
| 650 | const Color32* splatmap = (const Color32*)((const byte*)info.SplatMaps[splatIndex] + channelIndex); |
| 651 | const uint8 splat = splatmap[splatmapTextureIndex].R; |
| 652 | if (splat > layerWeight) |
| 653 | { |
| 654 | layer = splatIndex * 4 + channelIndex; |
| 655 | layerWeight = splat; |
| 656 | if (layerWeight == MAX_uint8) |
| 657 | break; |
| 658 | } |
| 659 | } |
| 660 | if (layerWeight == MAX_uint8) |
| 661 | break; |
| 662 | } |
| 663 | result = layer; |
| 664 | } |
| 665 | return result; |
| 666 | } |
| 667 | |
| 668 | bool CookCollision(TerrainDataUpdateInfo& info, TextureBase::InitData* initData, int32 collisionLod, Array<byte>* collisionData) |
| 669 | { |
no test coverage detected