diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | 142 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/TerrainChannel.cs | 12 |
2 files changed, 93 insertions, 61 deletions
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 08891d9..daf9901 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | |||
@@ -149,8 +149,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
149 | 149 | ||
150 | m_scene.RegisterModuleInterface<ITerrainModule>(this); | 150 | m_scene.RegisterModuleInterface<ITerrainModule>(this); |
151 | m_scene.EventManager.OnNewClient += EventManager_OnNewClient; | 151 | m_scene.EventManager.OnNewClient += EventManager_OnNewClient; |
152 | m_scene.EventManager.OnClientClosed += EventManager_OnClientClosed; | ||
152 | m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; | 153 | m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; |
153 | m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick; | 154 | m_scene.EventManager.OnTerrainTick += EventManager_OnTerrainTick; |
155 | m_scene.EventManager.OnFrame += EventManager_OnFrame; | ||
154 | } | 156 | } |
155 | 157 | ||
156 | InstallDefaultEffects(); | 158 | InstallDefaultEffects(); |
@@ -189,8 +191,10 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
189 | // remove the commands | 191 | // remove the commands |
190 | m_scene.UnregisterModuleCommander(m_commander.Name); | 192 | m_scene.UnregisterModuleCommander(m_commander.Name); |
191 | // remove the event-handlers | 193 | // remove the event-handlers |
194 | m_scene.EventManager.OnFrame -= EventManager_OnFrame; | ||
192 | m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick; | 195 | m_scene.EventManager.OnTerrainTick -= EventManager_OnTerrainTick; |
193 | m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole; | 196 | m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole; |
197 | m_scene.EventManager.OnClientClosed -= EventManager_OnClientClosed; | ||
194 | m_scene.EventManager.OnNewClient -= EventManager_OnNewClient; | 198 | m_scene.EventManager.OnNewClient -= EventManager_OnNewClient; |
195 | // remove the interface | 199 | // remove the interface |
196 | m_scene.UnregisterModuleInterface<ITerrainModule>(this); | 200 | m_scene.UnregisterModuleInterface<ITerrainModule>(this); |
@@ -266,7 +270,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
266 | String.Format("Unable to load heightmap: {0}", e.Message)); | 270 | String.Format("Unable to load heightmap: {0}", e.Message)); |
267 | } | 271 | } |
268 | } | 272 | } |
269 | CheckForTerrainUpdates(); | ||
270 | m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully"); | 273 | m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully"); |
271 | return; | 274 | return; |
272 | } | 275 | } |
@@ -347,7 +350,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
347 | } | 350 | } |
348 | } | 351 | } |
349 | 352 | ||
350 | CheckForTerrainUpdates(); | ||
351 | m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully"); | 353 | m_log.Info("[TERRAIN]: File (" + filename + ") loaded successfully"); |
352 | return; | 354 | return; |
353 | } | 355 | } |
@@ -418,7 +420,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
418 | 420 | ||
419 | public void TaintTerrain () | 421 | public void TaintTerrain () |
420 | { | 422 | { |
421 | CheckForTerrainUpdates(); | 423 | m_channel.GetTerrainData().TaintAllTerrain(); |
422 | } | 424 | } |
423 | 425 | ||
424 | #region Plugin Loading Methods | 426 | #region Plugin Loading Methods |
@@ -647,7 +649,39 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
647 | } | 649 | } |
648 | 650 | ||
649 | /// <summary> | 651 | /// <summary> |
652 | /// Called before processing of every simulation frame. | ||
653 | /// This is used to check to see of any of the terrain is tainted and, if so, schedule | ||
654 | /// updates for all the presences. | ||
655 | /// This also checks to see if there are updates that need to be sent for each presence. | ||
656 | /// This is where the logic is to send terrain updates to clients. | ||
657 | /// </summary> | ||
658 | private void EventManager_OnFrame() | ||
659 | { | ||
660 | TerrainData terrData = m_channel.GetTerrainData(); | ||
661 | |||
662 | bool shouldTaint = false; | ||
663 | for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) | ||
664 | { | ||
665 | for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) | ||
666 | { | ||
667 | if (terrData.IsTaintedAt(x, y)) | ||
668 | { | ||
669 | // Found a patch that was modified. Push this flag into the clients. | ||
670 | SendToClients(terrData, x, y); | ||
671 | shouldTaint = true; | ||
672 | } | ||
673 | } | ||
674 | } | ||
675 | if (shouldTaint) | ||
676 | { | ||
677 | m_scene.EventManager.TriggerTerrainTainted(); | ||
678 | m_tainted = true; | ||
679 | } | ||
680 | } | ||
681 | |||
682 | /// <summary> | ||
650 | /// Performs updates to the region periodically, synchronising physics and other heightmap aware sections | 683 | /// Performs updates to the region periodically, synchronising physics and other heightmap aware sections |
684 | /// Called infrequently (like every 5 seconds or so). Best used for storing terrain. | ||
651 | /// </summary> | 685 | /// </summary> |
652 | private void EventManager_OnTerrainTick() | 686 | private void EventManager_OnTerrainTick() |
653 | { | 687 | { |
@@ -698,6 +732,22 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
698 | } | 732 | } |
699 | 733 | ||
700 | /// <summary> | 734 | /// <summary> |
735 | /// Installs terrain brush hook to IClientAPI | ||
736 | /// </summary> | ||
737 | /// <param name="client"></param> | ||
738 | private void EventManager_OnClientClosed(UUID client, Scene scene) | ||
739 | { | ||
740 | ScenePresence presence = scene.GetScenePresence(client); | ||
741 | if (presence != null) | ||
742 | { | ||
743 | presence.ControllingClient.OnModifyTerrain -= client_OnModifyTerrain; | ||
744 | presence.ControllingClient.OnBakeTerrain -= client_OnBakeTerrain; | ||
745 | presence.ControllingClient.OnLandUndo -= client_OnLandUndo; | ||
746 | presence.ControllingClient.OnUnackedTerrain -= client_OnUnackedTerrain; | ||
747 | } | ||
748 | } | ||
749 | |||
750 | /// <summary> | ||
701 | /// Checks to see if the terrain has been modified since last check | 751 | /// Checks to see if the terrain has been modified since last check |
702 | /// but won't attempt to limit those changes to the limits specified in the estate settings | 752 | /// but won't attempt to limit those changes to the limits specified in the estate settings |
703 | /// currently invoked by the command line operations in the region server only | 753 | /// currently invoked by the command line operations in the region server only |
@@ -717,36 +767,32 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
717 | /// </summary> | 767 | /// </summary> |
718 | private void CheckForTerrainUpdates(bool respectEstateSettings) | 768 | private void CheckForTerrainUpdates(bool respectEstateSettings) |
719 | { | 769 | { |
720 | bool shouldTaint = false; | 770 | } |
721 | float[] terrHeights = m_channel.GetFloatsSerialised(); | 771 | |
722 | int x; | 772 | /// <summary> |
723 | for (x = 0; x < m_channel.Width; x += Constants.TerrainPatchSize) | 773 | /// Scan over changes in the terrain and limit height changes. This enforces the |
774 | /// non-estate owner limits on rate of terrain editting. | ||
775 | /// Returns 'true' if any heights were limited. | ||
776 | /// </summary> | ||
777 | private bool EnforceEstateLimits() | ||
778 | { | ||
779 | TerrainData terrData = m_channel.GetTerrainData(); | ||
780 | |||
781 | bool wasLimited = false; | ||
782 | for (int x = 0; x < terrData.SizeX; x += Constants.TerrainPatchSize) | ||
724 | { | 783 | { |
725 | int y; | 784 | for (int y = 0; y < terrData.SizeY; y += Constants.TerrainPatchSize) |
726 | for (y = 0; y < m_channel.Height; y += Constants.TerrainPatchSize) | ||
727 | { | 785 | { |
728 | if (m_channel.Tainted(x, y)) | 786 | if (terrData.IsTaintedAt(x, y, false /* clearOnTest */)) |
729 | { | 787 | { |
730 | // If we should respect the estate settings then | 788 | // If we should respect the estate settings then |
731 | // fixup and height deltas that don't respect them. | 789 | // fixup and height deltas that don't respect them. |
732 | // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values. | 790 | // Note that LimitChannelChanges() modifies the TerrainChannel with the limited height values. |
733 | if (respectEstateSettings && LimitChannelChanges(x, y)) | 791 | wasLimited |= LimitChannelChanges(terrData, x, y); |
734 | { | ||
735 | // Terrain heights were modified. Refetch the terrain info. | ||
736 | terrHeights = m_channel.GetFloatsSerialised(); | ||
737 | } | ||
738 | |||
739 | // m_log.DebugFormat("{0} Patch modified. Sending (x,y) = ({1},{2})", LogHeader, x, y); | ||
740 | SendToClients(terrHeights, x, y); | ||
741 | shouldTaint = true; | ||
742 | } | 792 | } |
743 | } | 793 | } |
744 | } | 794 | } |
745 | if (shouldTaint) | 795 | return wasLimited; |
746 | { | ||
747 | m_scene.EventManager.TriggerTerrainTainted(); | ||
748 | m_tainted = true; | ||
749 | } | ||
750 | } | 796 | } |
751 | 797 | ||
752 | /// <summary> | 798 | /// <summary> |
@@ -754,11 +800,11 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
754 | /// are all within the current estate limits | 800 | /// are all within the current estate limits |
755 | /// <returns>true if changes were limited, false otherwise</returns> | 801 | /// <returns>true if changes were limited, false otherwise</returns> |
756 | /// </summary> | 802 | /// </summary> |
757 | private bool LimitChannelChanges(int xStart, int yStart) | 803 | private bool LimitChannelChanges(TerrainData terrData, int xStart, int yStart) |
758 | { | 804 | { |
759 | bool changesLimited = false; | 805 | bool changesLimited = false; |
760 | double minDelta = m_scene.RegionInfo.RegionSettings.TerrainLowerLimit; | 806 | float minDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainLowerLimit; |
761 | double maxDelta = m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit; | 807 | float maxDelta = (float)m_scene.RegionInfo.RegionSettings.TerrainRaiseLimit; |
762 | 808 | ||
763 | // loop through the height map for this patch and compare it against | 809 | // loop through the height map for this patch and compare it against |
764 | // the revert map | 810 | // the revert map |
@@ -766,19 +812,18 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
766 | { | 812 | { |
767 | for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) | 813 | for (int y = yStart; y < yStart + Constants.TerrainPatchSize; y++) |
768 | { | 814 | { |
769 | 815 | float requestedHeight = terrData[x, y]; | |
770 | double requestedHeight = m_channel[x, y]; | 816 | float bakedHeight = (float)m_revert[x, y]; |
771 | double bakedHeight = m_revert[x, y]; | 817 | float requestedDelta = requestedHeight - bakedHeight; |
772 | double requestedDelta = requestedHeight - bakedHeight; | ||
773 | 818 | ||
774 | if (requestedDelta > maxDelta) | 819 | if (requestedDelta > maxDelta) |
775 | { | 820 | { |
776 | m_channel[x, y] = bakedHeight + maxDelta; | 821 | terrData[x, y] = bakedHeight + maxDelta; |
777 | changesLimited = true; | 822 | changesLimited = true; |
778 | } | 823 | } |
779 | else if (requestedDelta < minDelta) | 824 | else if (requestedDelta < minDelta) |
780 | { | 825 | { |
781 | m_channel[x, y] = bakedHeight + minDelta; //as lower is a -ve delta | 826 | terrData[x, y] = bakedHeight + minDelta; //as lower is a -ve delta |
782 | changesLimited = true; | 827 | changesLimited = true; |
783 | } | 828 | } |
784 | } | 829 | } |
@@ -806,11 +851,16 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
806 | /// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param> | 851 | /// <param name="serialised">A copy of the terrain as a 1D float array of size w*h</param> |
807 | /// <param name="x">The patch corner to send</param> | 852 | /// <param name="x">The patch corner to send</param> |
808 | /// <param name="y">The patch corner to send</param> | 853 | /// <param name="y">The patch corner to send</param> |
809 | private void SendToClients(float[] heightMap, int x, int y) | 854 | private void SendToClients(TerrainData terrData, int x, int y) |
810 | { | 855 | { |
856 | float[] heightMap = terrData.GetFloatsSerialized(); | ||
811 | m_scene.ForEachClient( | 857 | m_scene.ForEachClient( |
812 | delegate(IClientAPI controller) | 858 | delegate(IClientAPI controller) |
813 | { controller.SendLayerData( x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, heightMap); } | 859 | { |
860 | controller.SendLayerData( x / Constants.TerrainPatchSize, | ||
861 | y / Constants.TerrainPatchSize, | ||
862 | heightMap); | ||
863 | } | ||
814 | ); | 864 | ); |
815 | } | 865 | } |
816 | 866 | ||
@@ -856,7 +906,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
856 | m_painteffects[(StandardTerrainEffects) action].PaintEffect( | 906 | m_painteffects[(StandardTerrainEffects) action].PaintEffect( |
857 | m_channel, allowMask, west, south, height, size, seconds); | 907 | m_channel, allowMask, west, south, height, size, seconds); |
858 | 908 | ||
859 | CheckForTerrainUpdates(!god); //revert changes outside estate limits | 909 | //revert changes outside estate limits |
910 | if (!god) | ||
911 | EnforceEstateLimits(); | ||
860 | } | 912 | } |
861 | } | 913 | } |
862 | else | 914 | else |
@@ -897,7 +949,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
897 | m_floodeffects[(StandardTerrainEffects) action].FloodEffect( | 949 | m_floodeffects[(StandardTerrainEffects) action].FloodEffect( |
898 | m_channel, fillArea, size); | 950 | m_channel, fillArea, size); |
899 | 951 | ||
900 | CheckForTerrainUpdates(!god); //revert changes outside estate limits | 952 | //revert changes outside estate limits |
953 | if (!god) | ||
954 | EnforceEstateLimits(); | ||
901 | } | 955 | } |
902 | } | 956 | } |
903 | else | 957 | else |
@@ -948,7 +1002,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
948 | private void InterfaceLoadFile(Object[] args) | 1002 | private void InterfaceLoadFile(Object[] args) |
949 | { | 1003 | { |
950 | LoadFromFile((string) args[0]); | 1004 | LoadFromFile((string) args[0]); |
951 | CheckForTerrainUpdates(); | ||
952 | } | 1005 | } |
953 | 1006 | ||
954 | private void InterfaceLoadTileFile(Object[] args) | 1007 | private void InterfaceLoadTileFile(Object[] args) |
@@ -958,7 +1011,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
958 | (int) args[2], | 1011 | (int) args[2], |
959 | (int) args[3], | 1012 | (int) args[3], |
960 | (int) args[4]); | 1013 | (int) args[4]); |
961 | CheckForTerrainUpdates(); | ||
962 | } | 1014 | } |
963 | 1015 | ||
964 | private void InterfaceSaveFile(Object[] args) | 1016 | private void InterfaceSaveFile(Object[] args) |
@@ -987,7 +1039,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
987 | for (y = 0; y < m_channel.Height; y++) | 1039 | for (y = 0; y < m_channel.Height; y++) |
988 | m_channel[x, y] = m_revert[x, y]; | 1040 | m_channel[x, y] = m_revert[x, y]; |
989 | 1041 | ||
990 | CheckForTerrainUpdates(); | ||
991 | } | 1042 | } |
992 | 1043 | ||
993 | private void InterfaceFlipTerrain(Object[] args) | 1044 | private void InterfaceFlipTerrain(Object[] args) |
@@ -1028,7 +1079,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1028 | } | 1079 | } |
1029 | 1080 | ||
1030 | 1081 | ||
1031 | CheckForTerrainUpdates(); | ||
1032 | } | 1082 | } |
1033 | 1083 | ||
1034 | private void InterfaceRescaleTerrain(Object[] args) | 1084 | private void InterfaceRescaleTerrain(Object[] args) |
@@ -1086,7 +1136,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1086 | } | 1136 | } |
1087 | } | 1137 | } |
1088 | 1138 | ||
1089 | CheckForTerrainUpdates(); | ||
1090 | } | 1139 | } |
1091 | 1140 | ||
1092 | } | 1141 | } |
@@ -1097,7 +1146,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1097 | for (x = 0; x < m_channel.Width; x++) | 1146 | for (x = 0; x < m_channel.Width; x++) |
1098 | for (y = 0; y < m_channel.Height; y++) | 1147 | for (y = 0; y < m_channel.Height; y++) |
1099 | m_channel[x, y] += (double) args[0]; | 1148 | m_channel[x, y] += (double) args[0]; |
1100 | CheckForTerrainUpdates(); | ||
1101 | } | 1149 | } |
1102 | 1150 | ||
1103 | private void InterfaceMultiplyTerrain(Object[] args) | 1151 | private void InterfaceMultiplyTerrain(Object[] args) |
@@ -1106,7 +1154,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1106 | for (x = 0; x < m_channel.Width; x++) | 1154 | for (x = 0; x < m_channel.Width; x++) |
1107 | for (y = 0; y < m_channel.Height; y++) | 1155 | for (y = 0; y < m_channel.Height; y++) |
1108 | m_channel[x, y] *= (double) args[0]; | 1156 | m_channel[x, y] *= (double) args[0]; |
1109 | CheckForTerrainUpdates(); | ||
1110 | } | 1157 | } |
1111 | 1158 | ||
1112 | private void InterfaceLowerTerrain(Object[] args) | 1159 | private void InterfaceLowerTerrain(Object[] args) |
@@ -1115,7 +1162,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1115 | for (x = 0; x < m_channel.Width; x++) | 1162 | for (x = 0; x < m_channel.Width; x++) |
1116 | for (y = 0; y < m_channel.Height; y++) | 1163 | for (y = 0; y < m_channel.Height; y++) |
1117 | m_channel[x, y] -= (double) args[0]; | 1164 | m_channel[x, y] -= (double) args[0]; |
1118 | CheckForTerrainUpdates(); | ||
1119 | } | 1165 | } |
1120 | 1166 | ||
1121 | private void InterfaceFillTerrain(Object[] args) | 1167 | private void InterfaceFillTerrain(Object[] args) |
@@ -1125,7 +1171,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1125 | for (x = 0; x < m_channel.Width; x++) | 1171 | for (x = 0; x < m_channel.Width; x++) |
1126 | for (y = 0; y < m_channel.Height; y++) | 1172 | for (y = 0; y < m_channel.Height; y++) |
1127 | m_channel[x, y] = (double) args[0]; | 1173 | m_channel[x, y] = (double) args[0]; |
1128 | CheckForTerrainUpdates(); | ||
1129 | } | 1174 | } |
1130 | 1175 | ||
1131 | private void InterfaceMinTerrain(Object[] args) | 1176 | private void InterfaceMinTerrain(Object[] args) |
@@ -1138,7 +1183,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1138 | m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]); | 1183 | m_channel[x, y] = Math.Max((double)args[0], m_channel[x, y]); |
1139 | } | 1184 | } |
1140 | } | 1185 | } |
1141 | CheckForTerrainUpdates(); | ||
1142 | } | 1186 | } |
1143 | 1187 | ||
1144 | private void InterfaceMaxTerrain(Object[] args) | 1188 | private void InterfaceMaxTerrain(Object[] args) |
@@ -1151,7 +1195,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1151 | m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]); | 1195 | m_channel[x, y] = Math.Min((double)args[0], m_channel[x, y]); |
1152 | } | 1196 | } |
1153 | } | 1197 | } |
1154 | CheckForTerrainUpdates(); | ||
1155 | } | 1198 | } |
1156 | 1199 | ||
1157 | private void InterfaceShowDebugStats(Object[] args) | 1200 | private void InterfaceShowDebugStats(Object[] args) |
@@ -1214,7 +1257,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain | |||
1214 | if (m_plugineffects.ContainsKey(firstArg)) | 1257 | if (m_plugineffects.ContainsKey(firstArg)) |
1215 | { | 1258 | { |
1216 | m_plugineffects[firstArg].RunEffect(m_channel); | 1259 | m_plugineffects[firstArg].RunEffect(m_channel); |
1217 | CheckForTerrainUpdates(); | ||
1218 | } | 1260 | } |
1219 | else | 1261 | else |
1220 | { | 1262 | { |
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs index 60dc6c9..cc040a6 100644 --- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs +++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs | |||
@@ -124,17 +124,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
124 | // and the caller will probably do the wrong thing if the terrain is not the legacy 256x256. | 124 | // and the caller will probably do the wrong thing if the terrain is not the legacy 256x256. |
125 | public float[] GetFloatsSerialised() | 125 | public float[] GetFloatsSerialised() |
126 | { | 126 | { |
127 | int points = Width * Height; | 127 | return m_terrainData.GetFloatsSerialized(); |
128 | float[] heights = new float[points]; | ||
129 | |||
130 | int idx = 0; | ||
131 | for (int jj = 0; jj < Height; jj++) | ||
132 | for (int ii = 0; ii < Width; ii++) | ||
133 | { | ||
134 | heights[idx++] = m_terrainData[ii, jj]; | ||
135 | } | ||
136 | |||
137 | return heights; | ||
138 | } | 128 | } |
139 | 129 | ||
140 | // ITerrainChannel.GetDoubles() | 130 | // ITerrainChannel.GetDoubles() |