Ticket #794: Camera.patch
File Camera.patch, 21.4 KB (added by , 12 years ago) |
---|
-
binaries/data/config/default.cfg
95 95 view.near = 2.0 ; Near plane distance 96 96 view.far = 4096.0 ; Far plane distance 97 97 view.fov = 45.0 ; Field of view (degrees), lower is narrow, higher is wide 98 view.height.smoothness = 0.5 99 view.height.min = 16 98 100 99 101 ; HOTKEY MAPPINGS: 100 102 -
source/graphics/GameView.cpp
190 190 JoystickRotateY(-1), 191 191 JoystickZoomIn(-1), 192 192 JoystickZoomOut(-1), 193 HeightSmoothness(0.5f), 194 HeightMin(16.f), 193 195 194 196 PosX(0, 0, 0.01f), 195 197 PosY(0, 0, 0.01f), … … 289 291 int JoystickRotateY; 290 292 int JoystickZoomIn; 291 293 int JoystickZoomOut; 294 float HeightSmoothness; 295 float HeightMin; 292 296 293 297 //////////////////////////////////////// 294 298 // Camera Controls State … … 426 430 CFG_GET_SYS_VAL("joystick.camera.zoom.in", Int, m->JoystickZoomIn); 427 431 CFG_GET_SYS_VAL("joystick.camera.zoom.out", Int, m->JoystickZoomOut); 428 432 433 CFG_GET_SYS_VAL("view.height.smoothness", Float, m->HeightSmoothness); 434 CFG_GET_SYS_VAL("view.height.min", Float, m->HeightMin); 435 429 436 CFG_GET_SYS_VAL("view.pos.smoothness", Float, m->PosX.m_Smoothness); 430 437 CFG_GET_SYS_VAL("view.pos.smoothness", Float, m->PosY.m_Smoothness); 431 438 CFG_GET_SYS_VAL("view.pos.smoothness", Float, m->PosZ.m_Smoothness); … … 595 602 g_Renderer.GetWaterManager()->UnloadWaterTextures(); 596 603 } 597 604 605 static void FocusHeight(CGameViewImpl* m, bool smooth) 606 { 607 /* 608 The camera pivot height is moved towards ground level. 609 To prevent excessive zoom when looking over a cliff, 610 the target ground level is the maximum of the ground level at the camera's near and pivot points. 611 The ground levels are filtered to achieve smooth camera movement. 612 The filter radius is proportional to the zoom level. 613 The camera height is clamped to prevent map penetration. 614 */ 598 615 599 static void ClampDistance(CGameViewImpl* m, bool smooth)600 {601 616 if (!m->ConstrainCamera) 602 617 return; 603 618 604 619 CCamera targetCam = m->ViewCamera; 605 620 SetupCameraMatrixSmoothRot(m, &targetCam.m_Orientation); 606 621 607 CVector3D forwards = targetCam.m_Orientation.GetIn(); 622 const CVector3D position = targetCam.m_Orientation.GetTranslation(); 623 const CVector3D forwards = targetCam.m_Orientation.GetIn(); 608 624 609 CVector3D delta = targetCam.GetFocus() - targetCam.m_Orientation.GetTranslation(); 625 // horizontal view radius 626 const float radius = hypot( forwards.X, forwards.Z ) * m->Zoom.GetSmoothedValue(); 627 const float near_radius = radius * m->HeightSmoothness; 628 const float pivot_radius = radius * m->HeightSmoothness; 610 629 611 float dist = delta.Dot(forwards); 612 float clampedDist = Clamp(dist, m->ViewZoomMin, m->ViewZoomMax); 613 float diff = clampedDist - dist; 630 const CVector3D nearPoint = position + forwards * m->ViewNear; 631 const CVector3D pivotPoint = position + forwards * m->Zoom.GetSmoothedValue(); 614 632 633 const float ground = m->Game->GetWorld()->GetTerrain()->GetExactGroundLevel(nearPoint.X, nearPoint.Z); 634 635 // filter ground levels for smooth camera movement 636 const float filtered_near_ground = m->Game->GetWorld()->GetTerrain()->GetFilteredGroundLevel(nearPoint.X, nearPoint.Z, near_radius); 637 const float filtered_pivot_ground = m->Game->GetWorld()->GetTerrain()->GetFilteredGroundLevel(pivotPoint.X, pivotPoint.Z, pivot_radius); 638 639 // filtered maximum visible ground level in view 640 const float filtered_ground = std::max<float>(filtered_near_ground, filtered_pivot_ground); 641 642 // target camera height above pivot point 643 const float pivot_height = -forwards.Y * (m->Zoom.GetSmoothedValue() - m->ViewNear); 644 // minimum camera height above filtered ground level 645 const float min_height = (m->HeightMin + ground - filtered_ground); 646 647 const float target_height = std::max<float>(pivot_height , min_height); 648 const float height = (nearPoint.Y - filtered_ground); 649 const float diff = target_height - height; 650 615 651 if (!diff) 616 652 return; 617 653 618 654 if (smooth) 619 655 { 620 m->PosX.AddSmoothly(forwards.X * -diff); 621 m->PosY.AddSmoothly(forwards.Y * -diff); 622 m->PosZ.AddSmoothly(forwards.Z * -diff); 656 m->PosY.AddSmoothly(diff); 623 657 } 624 658 else 625 659 { 626 m->PosX.Add(forwards.X * -diff); 627 m->PosY.Add(forwards.Y * -diff); 628 m->PosZ.Add(forwards.Z * -diff); 660 m->PosY.Add(diff); 629 661 } 630 662 } 631 663 664 CVector3D CGameView::GetSmoothPivot(CCamera &camera) const 665 { 666 ENSURE( m != 0 ); 667 return camera.m_Orientation.GetTranslation() + camera.m_Orientation.GetIn() * m->Zoom.GetSmoothedValue(); 668 } 669 632 670 void CGameView::Update(float DeltaTime) 633 671 { 634 672 // If camera movement is being handled by the touch-input system, … … 758 796 // Move the camera to match the unit 759 797 CCamera targetCam = m->ViewCamera; 760 798 SetupCameraMatrixSmoothRot(m, &targetCam.m_Orientation); 761 762 CVector3D pivot = targetCam.GetFocus();799 800 CVector3D pivot = GetSmoothPivot(targetCam); 763 801 CVector3D delta = pos - pivot; 764 802 m->PosX.AddSmoothly(delta.X); 765 803 m->PosY.AddSmoothly(delta.Y); … … 774 812 } 775 813 776 814 if (HotkeyIsPressed("camera.zoom.in")) 815 m->Zoom.AddSmoothly(-m->ViewZoomSpeed * DeltaTime); 816 if (HotkeyIsPressed("camera.zoom.out")) 777 817 m->Zoom.AddSmoothly(m->ViewZoomSpeed * DeltaTime); 778 if (HotkeyIsPressed("camera.zoom.out"))779 m->Zoom.AddSmoothly(-m->ViewZoomSpeed * DeltaTime);780 818 781 float zoomDelta = m->Zoom.Update(DeltaTime); 819 if (m->ConstrainCamera) 820 m->Zoom.ClampSmoothly( m->ViewZoomMin, m->ViewZoomMax ); 821 822 float zoomDelta = -m->Zoom.Update(DeltaTime); 782 823 if (zoomDelta) 783 824 { 784 825 CVector3D forwards = m->ViewCamera.m_Orientation.GetIn(); … … 790 831 if (m->ConstrainCamera) 791 832 m->RotateX.ClampSmoothly(DEGTORAD(m->ViewRotateXMin), DEGTORAD(m->ViewRotateXMax)); 792 833 793 ClampDistance(m, true);834 FocusHeight(m, true); 794 835 795 836 // Ensure the ViewCamera focus is inside the map with the chosen margins 796 837 // if not so - apply margins to the camera … … 801 842 802 843 CTerrain* pTerrain = m->Game->GetWorld()->GetTerrain(); 803 844 804 CVector3D pivot = targetCam.GetFocus();845 CVector3D pivot = GetSmoothPivot(targetCam); 805 846 CVector3D delta = targetCam.m_Orientation.GetTranslation() - pivot; 806 847 807 848 CVector3D desiredPivot = pivot; … … 846 887 847 888 CVector3D upwards(0.0f, 1.0f, 0.0f); 848 889 849 CVector3D pivot = targetCam.GetFocus();890 CVector3D pivot = GetSmoothPivot(targetCam); 850 891 CVector3D delta = targetCam.m_Orientation.GetTranslation() - pivot; 851 892 852 893 CQuaternion q; … … 869 910 { 870 911 CVector3D rightwards = targetCam.m_Orientation.GetLeft() * -1.0f; 871 912 872 CVector3D pivot = m->ViewCamera.GetFocus();913 CVector3D pivot = GetSmoothPivot(targetCam); 873 914 CVector3D delta = targetCam.m_Orientation.GetTranslation() - pivot; 874 915 875 916 CQuaternion q; … … 919 960 CCamera targetCam = m->ViewCamera; 920 961 SetupCameraMatrixNonSmooth(m, &targetCam.m_Orientation); 921 962 922 CVector3D pivot = targetCam.GetFocus();963 CVector3D pivot = GetSmoothPivot(targetCam); 923 964 CVector3D delta = target - pivot; 924 965 925 966 m->PosX.SetValueSmoothly(delta.X + m->PosX.GetValue()); 926 967 m->PosZ.SetValueSmoothly(delta.Z + m->PosZ.GetValue()); 927 968 928 ClampDistance(m, false);969 FocusHeight(m, false); 929 970 930 971 // Break out of following mode so the camera really moves to the target 931 972 m->FollowEntity = INVALID_ENTITY; … … 944 985 m->PosZ.SetValue(target.Z - delta.Z); 945 986 m->RotateX.SetValue(DEGTORAD(m->ViewRotateXDefault)); 946 987 m->RotateY.SetValue(DEGTORAD(m->ViewRotateYDefault)); 988 m->Zoom.SetValue(m->ViewZoomDefault); 947 989 948 ClampDistance(m, false);990 FocusHeight(m, false); 949 991 950 992 SetupCameraMatrixSmooth(m, &m->ViewCamera.m_Orientation); 951 993 m->ViewCamera.UpdateFrustum(); … … 961 1003 962 1004 // Compute the zoom adjustment to get us back to the default 963 1005 CVector3D forwards = targetCam.m_Orientation.GetIn(); 964 CVector3D delta = targetCam.GetFocus() - targetCam.m_Orientation.GetTranslation(); 1006 1007 CVector3D pivot = GetSmoothPivot(targetCam); 1008 CVector3D delta = pivot - targetCam.m_Orientation.GetTranslation(); 965 1009 float dist = delta.Dot(forwards); 966 1010 m->Zoom.AddSmoothly(dist - m->ViewZoomDefault); 967 1011 … … 1049 1093 // and we never get to see the "down" state inside Update(). 1050 1094 else if (hotkey == "camera.zoom.wheel.in") 1051 1095 { 1052 m->Zoom.AddSmoothly( m->ViewZoomSpeedWheel);1096 m->Zoom.AddSmoothly(-m->ViewZoomSpeedWheel); 1053 1097 return IN_HANDLED; 1054 1098 } 1055 1099 else if (hotkey == "camera.zoom.wheel.out") 1056 1100 { 1057 m->Zoom.AddSmoothly( -m->ViewZoomSpeedWheel);1101 m->Zoom.AddSmoothly(m->ViewZoomSpeedWheel); 1058 1102 return IN_HANDLED; 1059 1103 } 1060 1104 else if (hotkey == "camera.rotate.wheel.cw") -
source/graphics/GameView.h
85 85 void CameraFollow(entity_id_t entity, bool firstPerson); 86 86 entity_id_t GetFollowedEntity(); 87 87 88 CVector3D GetSmoothPivot(CCamera &camera) const; 89 88 90 float GetNear() const; 89 91 float GetFar() const; 90 92 float GetFOV() const; -
source/graphics/HeightMipmap.cpp
1 /* Copyright (C) 2012 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "precompiled.h" 19 20 #include "HeightMipmap.h" 21 #include "lib/bits.h" 22 23 CHeightMipmap::CHeightMipmap() 24 {}; 25 26 CHeightMipmap::~CHeightMipmap() 27 { 28 ReleaseData(); 29 } 30 31 void CHeightMipmap::ReleaseData() 32 { 33 for (size_t i = 0 ; i < m_Mipmap.size(); ++i) 34 { 35 delete [] m_Mipmap[i].m_Heightmap; 36 m_Mipmap[i].m_MapSize = 0; 37 } 38 m_Mipmap.clear(); 39 } 40 41 void CHeightMipmap::Update(const u16* ptr) 42 { 43 ENSURE( ptr != 0 ); 44 45 Update(ptr, 0, 0, m_MapSize, m_MapSize); 46 } 47 48 void CHeightMipmap::Update(const u16* ptr, size_t left, size_t bottom, size_t right, size_t top) 49 { 50 ENSURE( ptr != 0 ); 51 52 size_t mapSize = m_MapSize; 53 54 for (size_t i = 0; i < m_Mipmap.size(); ++i) 55 { 56 // update window 57 left = clamp<size_t>( (size_t)floorf((left / mapSize) * m_Mipmap[i].m_MapSize), 0, m_Mipmap[i].m_MapSize - 1 ); 58 bottom = clamp<size_t>( (size_t)floorf((bottom / mapSize) * m_Mipmap[i].m_MapSize), 0, m_Mipmap[i].m_MapSize - 1 ); 59 60 right = clamp<size_t>( (size_t)ceilf((right / mapSize) * m_Mipmap[i].m_MapSize), 0, m_Mipmap[i].m_MapSize ); 61 top = clamp<size_t>( (size_t)ceilf((top / mapSize) * m_Mipmap[i].m_MapSize), 0, m_Mipmap[i].m_MapSize ); 62 63 // update mipmap 64 BilinearUpdate(m_Mipmap[i], mapSize, ptr, left, bottom, right, top); 65 66 mapSize = m_Mipmap[i].m_MapSize; 67 ptr = m_Mipmap[i].m_Heightmap; 68 } 69 } 70 71 void CHeightMipmap::Initialize(size_t mapSize, const u16* ptr) 72 { 73 ENSURE( ptr != 0 ); 74 ENSURE( mapSize > 0 ); 75 76 ReleaseData(); 77 78 m_MapSize = mapSize; 79 size_t mipmapSize = round_down_to_pow2(mapSize); 80 81 while (mipmapSize > 1) 82 { 83 m_Mipmap.push_back(SMipmap(mipmapSize, new u16[mipmapSize*mipmapSize])); 84 mipmapSize >>= 1; 85 }; 86 87 Update(ptr); 88 } 89 90 float CHeightMipmap::GetTrilinearGroundLevel(float x, float z, float radius) const 91 { 92 const float y = clamp<float>(logf(radius * m_Mipmap[0].m_MapSize) / logf(2), 0, m_Mipmap.size()); 93 const size_t iy = (size_t)clamp<ssize_t>((ssize_t)floorf(y), 0, m_Mipmap.size() - 1); 94 95 const float fy = y - iy; 96 97 const float h0 = BilinearFilter(m_Mipmap[iy], x, z); 98 const float h1 = BilinearFilter(m_Mipmap[iy + 1], x, z); 99 100 return (1 - fy) * h0 + fy * h1; 101 } 102 103 float CHeightMipmap::BilinearFilter(const SMipmap &mipmap, float x, float z) const 104 { 105 x *= mipmap.m_MapSize; 106 z *= mipmap.m_MapSize; 107 108 const size_t xi = (size_t)clamp<ssize_t>((ssize_t)floor(x), 0, mipmap.m_MapSize - 1); 109 const size_t zi = (size_t)clamp<ssize_t>((ssize_t)floor(z), 0, mipmap.m_MapSize - 1); 110 111 const float xf = clamp<float>(x-xi, 0.0f, 1.0f); 112 const float zf = clamp<float>(z-zi, 0.0f, 1.0f); 113 114 const float h00 = mipmap.m_Heightmap[zi*mipmap.m_MapSize + xi]; 115 const float h01 = mipmap.m_Heightmap[(zi+1)*mipmap.m_MapSize + xi]; 116 const float h10 = mipmap.m_Heightmap[zi*mipmap.m_MapSize + (xi+1)]; 117 const float h11 = mipmap.m_Heightmap[(zi+1)*mipmap.m_MapSize + (xi+1)]; 118 119 return 120 (1.f - xf) * (1.f - zf) * h00 + 121 xf * (1.f - zf) * h10 + 122 (1.f - xf) * zf * h01 + 123 xf * zf * h11; 124 } 125 126 void CHeightMipmap::HalfResizeUpdate(SMipmap &out_mipmap, size_t mapSize, const u16* ptr, size_t left, size_t bottom, size_t right, size_t top) 127 { 128 // specialized, faster version of BilinearUpdate for powers of 2 129 130 ENSURE(out_mipmap.m_MapSize != 0); 131 132 if (out_mipmap.m_MapSize * 2 != mapSize) 133 debug_warn(L"wrong size"); 134 135 // valid update window 136 ENSURE(left < out_mipmap.m_MapSize ); 137 ENSURE(bottom < out_mipmap.m_MapSize ); 138 ENSURE(right > left && right <= out_mipmap.m_MapSize ); 139 ENSURE(top > bottom && top <= out_mipmap.m_MapSize ); 140 141 for (size_t dstZ = bottom; dstZ < top; ++dstZ) 142 for (size_t dstX = left; dstX < right; ++dstX) 143 { 144 size_t srcX = dstX << 1; 145 size_t srcZ = dstZ << 1; 146 147 u16 h00 = ptr[srcX + 0 + srcZ * mapSize]; 148 u16 h10 = ptr[srcX + 1 + srcZ * mapSize]; 149 u16 h01 = ptr[srcX + 0 + (srcZ + 1) * mapSize]; 150 u16 h11 = ptr[srcX + 1 + (srcZ + 1) * mapSize]; 151 152 out_mipmap.m_Heightmap[dstX + dstZ * out_mipmap.m_MapSize] = (h00 + h10 + h01 + h11) / 4; 153 } 154 } 155 156 void CHeightMipmap::BilinearUpdate(SMipmap &out_mipmap, size_t mapSize, const u16* ptr, size_t left, size_t bottom, size_t right, size_t top) 157 { 158 ENSURE(out_mipmap.m_MapSize != 0); 159 160 // filter should have full coverage 161 ENSURE(out_mipmap.m_MapSize <= mapSize && out_mipmap.m_MapSize * 2 >= mapSize); 162 163 // valid update window 164 ENSURE(left < out_mipmap.m_MapSize ); 165 ENSURE(bottom < out_mipmap.m_MapSize ); 166 ENSURE(right > left && right <= out_mipmap.m_MapSize ); 167 ENSURE(top > bottom && top <= out_mipmap.m_MapSize ); 168 169 if (out_mipmap.m_MapSize * 2 == mapSize) 170 { 171 // optimized for powers of 2 172 HalfResizeUpdate(out_mipmap, mapSize, ptr, left, bottom, right, top); 173 } 174 else 175 { 176 for (size_t dstZ = bottom; dstZ < top; ++dstZ) 177 for (size_t dstX = left; dstX < right; ++dstX) { 178 const float x = ((float)dstX / (float)out_mipmap.m_MapSize) * mapSize; 179 const float z = ((float)dstZ / (float)out_mipmap.m_MapSize) * mapSize; 180 181 const size_t srcX = clamp<size_t>( (size_t)x, 0, mapSize - 1); 182 const size_t srcZ = clamp<size_t>( (size_t)z, 0, mapSize - 1); 183 184 const float fx = clamp<float>(x - srcX, 0.0f, 1.0f); 185 const float fz = clamp<float>(z - srcZ, 0.0f, 1.0f); 186 187 const float h00 = ptr[srcX + 0 + srcZ * mapSize]; 188 const float h10 = ptr[srcX + 1 + srcZ * mapSize]; 189 const float h01 = ptr[srcX + 0 + (srcZ + 1) * mapSize]; 190 const float h11 = ptr[srcX + 1 + (srcZ + 1) * mapSize]; 191 192 out_mipmap.m_Heightmap[dstX + dstZ * out_mipmap.m_MapSize] = (u16) 193 ((1.f - fx) * (1.f - fz) * h00 + 194 fx * (1.f - fz) * h10 + 195 (1.f - fx) * fz * h01 + 196 fx * fz * h11); 197 } 198 } 199 } -
source/graphics/HeightMipmap.h
1 /* Copyright (C) 2011 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 19 /* 20 * Describes ground using heightmap mipmaps 21 * Used for camera movement 22 */ 23 24 #ifndef INCLUDED_HEIGHTMIPMAP 25 #define INCLUDED_HEIGHTMIPMAP 26 27 #include <cmath> 28 #include "maths/MathUtil.h" 29 #include "ps/CLogger.h" 30 #include "ps/Profile.h" 31 32 struct SMipmap 33 { 34 SMipmap() 35 { 36 m_MapSize = 0; 37 m_Heightmap = 0; 38 }; 39 40 SMipmap(size_t MapSize,u16* Heightmap) : m_MapSize(MapSize), m_Heightmap(Heightmap) 41 {} 42 43 size_t m_MapSize; 44 u16* m_Heightmap; 45 }; 46 47 class CHeightMipmap 48 { 49 NONCOPYABLE(CHeightMipmap); 50 public: 51 52 CHeightMipmap(); 53 ~CHeightMipmap(); 54 55 void Initialize(size_t mapSize, const u16* ptr); 56 void ReleaseData(); 57 58 // update (a rectangular piece of) the heightmap mipmaps 59 void Update(const u16* ptr); 60 void Update(const u16* ptr, size_t left, size_t bottom, size_t right, size_t top); 61 62 float GetTrilinearGroundLevel(float x, float z, float radius) const; 63 64 private: 65 66 // get bilinear filtered height from mipmap 67 float BilinearFilter(const SMipmap &mipmap, float x, float z) const; 68 69 // update rectangle of the output mipmap by bilinear interpolating an input mipmap of exactly twice its size 70 void HalfResizeUpdate(SMipmap &out_mipmap, size_t mapSize, const u16* ptr, size_t left, size_t bottom, size_t right, size_t top); 71 72 // update rectangle of the output mipmap by bilinear interpolating the input mipmap 73 void BilinearUpdate(SMipmap &out_mipmap, size_t mapSize, const u16* ptr, size_t left, size_t bottom, size_t right, size_t top); 74 75 // size of this map in each direction 76 size_t m_MapSize; 77 78 // mipmap list 79 std::vector<SMipmap> m_Mipmap; 80 81 }; 82 83 #endif 84 No newline at end of file -
source/graphics/Terrain.cpp
57 57 // ReleaseData: delete any data allocated by this terrain 58 58 void CTerrain::ReleaseData() 59 59 { 60 m_HeightMipmap.ReleaseData(); 61 60 62 delete[] m_Heightmap; 61 63 delete[] m_Patches; 62 64 } … … 89 91 // setup patch parents, indices etc 90 92 InitialisePatches(); 91 93 94 // initialise mipmap 95 m_HeightMipmap.Initialize(m_MapSize,m_Heightmap); 96 92 97 return true; 93 98 } 94 99 … … 330 335 return fixed::FromInt(delta / TERRAIN_TILE_SIZE) / (int)HEIGHT_UNITS_PER_METRE; 331 336 } 332 337 338 float CTerrain::GetFilteredGroundLevel(float x, float z, float radius) const 339 { 340 // convert to [0,1] interval 341 float nx = x / (TERRAIN_TILE_SIZE*m_MapSize); 342 float nz = z / (TERRAIN_TILE_SIZE*m_MapSize); 343 float nr = radius / (TERRAIN_TILE_SIZE*m_MapSize); 344 345 // get trilinear filtered mipmap height 346 return HEIGHT_SCALE * m_HeightMipmap.GetTrilinearGroundLevel(nx, nz, nr); 347 } 348 333 349 float CTerrain::GetExactGroundLevel(float x, float z) const 334 350 { 335 351 // Clamp to size-2 so we can use the tiles (xi,zi)-(xi+1,zi+1) … … 530 546 531 547 // initialise all the new patches 532 548 InitialisePatches(); 549 550 // initialise mipmap 551 m_HeightMipmap.Initialize(m_MapSize,m_Heightmap); 533 552 } 534 553 535 554 /////////////////////////////////////////////////////////////////////////////// … … 560 579 patch->SetDirty(RENDERDATA_UPDATE_VERTICES); 561 580 } 562 581 } 582 583 // update mipmap 584 m_HeightMipmap.Update(m_Heightmap); 563 585 } 564 586 565 587 … … 589 611 } 590 612 } 591 613 614 // update mipmap 615 m_HeightMipmap.Update(m_Heightmap,tx0,tz0,tx1,tz1); 616 592 617 MakeDirty(tx0, tz0, tx1, tz1, RENDERDATA_UPDATE_VERTICES); 593 618 594 619 return avgY*HEIGHT_SCALE; -
source/graphics/Terrain.h
25 25 #include "maths/Vector3D.h" 26 26 #include "maths/Fixed.h" 27 27 #include "graphics/SColor.h" 28 #include "graphics/HeightMipmap.h" 28 29 29 30 class CPatch; 30 31 class CMiniPatch; … … 84 85 fixed GetVertexGroundLevelFixed(ssize_t i, ssize_t j) const; 85 86 float GetExactGroundLevel(float x, float z) const; 86 87 fixed GetExactGroundLevelFixed(fixed x, fixed z) const; 88 float GetFilteredGroundLevel(float x, float z, float radius) const; 87 89 88 90 // get the approximate slope (0 = horizontal, 0.5 = 30 degrees, 1.0 = 45 degrees, etc) 89 91 fixed GetSlopeFixed(ssize_t i, ssize_t j) const; … … 164 166 u16* m_Heightmap; 165 167 // base colour (usually white) 166 168 SColor4ub m_BaseColour; 169 // heightmap mipmap 170 CHeightMipmap m_HeightMipmap; 167 171 }; 168 172 169 173 #endif -
source/lib/bits.h
246 246 } 247 247 248 248 /** 249 * round down to next larger power of two. 250 **/ 251 template<typename T> 252 inline T round_down_to_pow2(T x) 253 { 254 return T(1) << floor_log2(x); 255 } 256 257 /** 249 258 * round number up/down to the next given multiple. 250 259 * 251 260 * @param n Number to round.