* Various terrain engine fixes

* Includes patch #894 fixes for terrain load-tile
* Large number of other terrain fixes and new commands included.
0.6.0-stable
Adam Frisby 2008-04-06 13:48:28 +00:00
parent 899f00b83d
commit 996309a6e1
9 changed files with 233 additions and 91 deletions

View File

@ -946,6 +946,7 @@ namespace OpenSim
}
break;
case "exit":
case "quit":
case "shutdown":
Shutdown();

View File

@ -249,7 +249,7 @@ namespace OpenSim.Region.Environment.Modules.ModuleFramework
{
if (m_commands.ContainsKey(function))
{
if (args[0] == "help")
if (args.Length > 0 && args[0] == "help")
{
m_commands[function].ShowConsoleHelp();
}

View File

@ -62,30 +62,63 @@ namespace OpenSim.Region.Environment.Modules.Terrain.FileLoaders
return "RAW32";
}
public ITerrainChannel LoadFile(string filename, int fileStartX, int fileStartY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight)
public ITerrainChannel LoadFile(string filename, int offsetX, int offsetY, int fileWidth, int fileHeight, int sectionWidth, int sectionHeight)
{
TerrainChannel retval = new TerrainChannel(sectionWidth, sectionHeight);
FileInfo file = new FileInfo(filename);
FileStream s = file.Open(FileMode.Open, FileAccess.Read);
BinaryReader bs = new BinaryReader(s);
int currFileXOffset = 0;
int currFileYOffset = 0;
// Advance to our section of the file
if (fileStartY * sectionHeight > 0)
bs.ReadBytes(fileStartY * sectionHeight);
int x, y;
for (y = 0; y < retval.Height; y++)
// if our region isn't on the first Y section of the areas to be landscaped, then
// advance to our section of the file
while (currFileYOffset < offsetY)
{
// Advance the stream if we aren't at the start of the section in the file
if (fileStartX * sectionWidth > 0)
bs.ReadBytes(fileStartX * sectionHeight);
// read a whole strip of regions
int heightsToRead = sectionHeight * (fileWidth * sectionWidth);
bs.ReadBytes( heightsToRead * 4); // because the floats are 4 bytes in the file
currFileYOffset++;
}
for (x = 0; x < retval.Width; x++)
// got to the Y start offset within the file of our region
// so read the file bits associated with our region
int x, y;
// for each Y within our Y offset
for (y = 0; y < sectionHeight; y++)
{
currFileXOffset = 0;
// if our region isn't the first X section of the areas to be landscaped, then
// advance the stream to the X start pos of our section in the file
// i.e. eat X upto where we start
while (currFileXOffset < offsetX)
{
bs.ReadBytes( sectionWidth * 4); // 4 bytes = single
currFileXOffset++;
}
// got to our X offset, so write our regions X line
for (x = 0; x < sectionWidth; x++)
{
// Read a strip and continue
retval[x, y] = bs.ReadSingle();
}
// record that we wrote it
currFileXOffset++;
// if our region isn't the last X section of the areas to be landscaped, then
// advance the stream to the end of this Y column
while (currFileXOffset < fileWidth )
{
// eat the next regions x line
bs.ReadBytes(sectionWidth * 4); // 4 bytes = single
currFileXOffset++;
}
}
bs.Close();

View File

@ -31,6 +31,6 @@ namespace OpenSim.Region.Environment.Modules.Terrain
{
public interface ITerrainEffect
{
void RunEffect(ITerrainChannel map, double strength);
void RunEffect(ITerrainChannel map);
}
}

View File

@ -121,13 +121,12 @@ namespace OpenSim.Region.Environment.Modules.Terrain
{
for (y = 0; y < Constants.RegionSize; y++)
{
//map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 10;
// double spherFac = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize, Constants.RegionSize, 20);
// if (map[x, y] < spherFac)
// {
// map[x, y] = spherFac;
// }
map[x, y] = 26;
map[x, y] = TerrainUtil.PerlinNoise2D(x, y, 3, 0.25) * 10;
double spherFac = TerrainUtil.SphericalFactor(x, y, Constants.RegionSize / 2, Constants.RegionSize / 2, 50) * 0.01;
if (map[x, y] < spherFac)
{
map[x, y] = spherFac;
}
}
}
}

View File

@ -35,10 +35,9 @@ using OpenSim.Region.Environment.Interfaces;
using OpenSim.Region.Environment.Scenes;
using OpenSim.Region.Environment.Modules.ModuleFramework;
namespace OpenSim.Region.Environment.Modules.Terrain
{
public class TerrainModule : IRegionModule , ITerrainTemp, ICommandableModule
public class TerrainModule : IRegionModule, ICommandableModule
{
public enum StandardTerrainEffects : byte
{
@ -47,7 +46,12 @@ namespace OpenSim.Region.Environment.Modules.Terrain
Lower = 2,
Smooth = 3,
Noise = 4,
Revert = 5
Revert = 5,
// Extended brushes
Erode = 255,
Weather = 254,
Olsen = 253
}
private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
@ -74,6 +78,9 @@ namespace OpenSim.Region.Environment.Modules.Terrain
m_painteffects[StandardTerrainEffects.Noise] = new PaintBrushes.NoiseSphere();
m_painteffects[StandardTerrainEffects.Flatten] = new PaintBrushes.FlattenSphere();
m_painteffects[StandardTerrainEffects.Revert] = new PaintBrushes.RevertSphere(m_revert);
m_painteffects[StandardTerrainEffects.Erode] = new PaintBrushes.ErodeSphere();
m_painteffects[StandardTerrainEffects.Weather] = new PaintBrushes.WeatherSphere();
m_painteffects[StandardTerrainEffects.Olsen] = new PaintBrushes.OlsenSphere();
// Area of effect selection effects
m_floodeffects[StandardTerrainEffects.Raise] = new FloodBrushes.RaiseArea();
@ -90,6 +97,11 @@ namespace OpenSim.Region.Environment.Modules.Terrain
m_loaders[".raw"] = new FileLoaders.LLRAW();
m_loaders[".jpg"] = new FileLoaders.JPEG();
m_loaders[".jpeg"] = m_loaders[".jpg"];
m_loaders[".bmp"] = new FileLoaders.BMP();
m_loaders[".png"] = new FileLoaders.PNG();
m_loaders[".gif"] = new FileLoaders.GIF();
m_loaders[".tif"] = new FileLoaders.TIFF();
m_loaders[".tiff"] = m_loaders[".tif"];
}
public void UpdateRevertMap()
@ -139,22 +151,26 @@ namespace OpenSim.Region.Environment.Modules.Terrain
public void LoadFromFile(string filename, int fileWidth, int fileHeight, int fileStartX, int fileStartY)
{
fileStartX -= (int)m_scene.RegionInfo.RegionLocX;
fileStartY -= (int)m_scene.RegionInfo.RegionLocY;
int offsetX = (int)m_scene.RegionInfo.RegionLocX - fileStartX;
int offsetY = (int)m_scene.RegionInfo.RegionLocY - fileStartY;
foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
if (offsetX >= 0 && offsetX < fileWidth && offsetY >= 0 && offsetY < fileHeight)
{
if (filename.EndsWith(loader.Key))
// this region is included in the tile request
foreach (KeyValuePair<string, ITerrainLoader> loader in m_loaders)
{
lock (m_scene)
if (filename.EndsWith(loader.Key))
{
ITerrainChannel channel = loader.Value.LoadFile(filename, fileStartX, fileStartY,
fileWidth, fileHeight, (int)Constants.RegionSize, (int)Constants.RegionSize);
m_scene.Heightmap = channel;
m_channel = channel;
UpdateRevertMap();
lock (m_scene)
{
ITerrainChannel channel = loader.Value.LoadFile(filename, offsetX, offsetY,
fileWidth, fileHeight, (int)Constants.RegionSize, (int)Constants.RegionSize);
m_scene.Heightmap = channel;
m_channel = channel;
UpdateRevertMap();
}
return;
}
return;
}
}
}
@ -181,7 +197,6 @@ namespace OpenSim.Region.Environment.Modules.Terrain
public void Initialise(Scene scene, IConfigSource config)
{
m_scene = scene;
m_scene.RegisterModuleInterface<ITerrainTemp>(this);
m_gConfig = config;
// Install terrain module in the simulator
@ -222,7 +237,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain
private void InterfaceLoadFile(Object[] args)
{
LoadFromFile((string)args[0]);
SendUpdatedLayerData();
CheckForTerrainUpdates();
}
private void InterfaceLoadTileFile(Object[] args)
@ -232,7 +247,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain
(int)args[2],
(int)args[3],
(int)args[4]);
SendUpdatedLayerData();
CheckForTerrainUpdates();
}
private void InterfaceSaveFile(Object[] args)
@ -240,6 +255,48 @@ namespace OpenSim.Region.Environment.Modules.Terrain
SaveToFile((string)args[0]);
}
private void InterfaceBakeTerrain(Object[] args)
{
UpdateRevertMap();
}
private void InterfaceRevertTerrain(Object[] args)
{
int x, y;
for (x = 0; x < m_channel.Width; x++)
for (y = 0; y < m_channel.Height; y++)
m_channel[x, y] = m_revert[x, y];
CheckForTerrainUpdates();
}
private void InterfaceElevateTerrain(Object[] args)
{
int x, y;
for (x = 0; x < m_channel.Width; x++)
for (y = 0; y < m_channel.Height; y++)
m_channel[x, y] += (double)args[0];
CheckForTerrainUpdates();
}
private void InterfaceMultiplyTerrain(Object[] args)
{
int x, y;
for (x = 0; x < m_channel.Width; x++)
for (y = 0; y < m_channel.Height; y++)
m_channel[x, y] *= (double)args[0];
CheckForTerrainUpdates();
}
private void InterfaceLowerTerrain(Object[] args)
{
int x, y;
for (x = 0; x < m_channel.Width; x++)
for (y = 0; y < m_channel.Height; y++)
m_channel[x, y] -= (double)args[0];
CheckForTerrainUpdates();
}
private void InterfaceFillTerrain(Object[] args)
{
int x, y;
@ -247,7 +304,33 @@ namespace OpenSim.Region.Environment.Modules.Terrain
for (x = 0; x < m_channel.Width; x++)
for (y = 0; y < m_channel.Height; y++)
m_channel[x, y] = (double)args[0];
SendUpdatedLayerData();
CheckForTerrainUpdates();
}
private void InterfaceShowDebugStats(Object[] args)
{
double max = Double.MinValue;
double min = double.MaxValue;
double avg = 0;
double sum = 0;
int x, y;
for (x = 0; x < m_channel.Width; x++)
{
for (y = 0; y < m_channel.Height; y++)
{
sum += m_channel[x, y];
if (max < m_channel[x, y])
max = m_channel[x, y];
if (min > m_channel[x, y])
min = m_channel[x, y];
}
}
avg = sum / (m_channel.Height * m_channel.Width);
m_log.Info("Channel " + m_channel.Width + "x" + m_channel.Height);
m_log.Info("max/min/avg/sum: " + max + "/" + min + "/" + avg + "/" + sum);
}
private void InterfaceEnableExperimentalBrushes(Object[] args)
@ -264,6 +347,12 @@ namespace OpenSim.Region.Environment.Modules.Terrain
}
}
private void InterfacePerformEffectTest(Object[] args)
{
Effects.CookieCutter cookie = new OpenSim.Region.Environment.Modules.Terrain.Effects.CookieCutter();
cookie.RunEffect(m_channel);
}
private void InstallInterfaces()
{
// Load / Save
@ -288,15 +377,39 @@ namespace OpenSim.Region.Environment.Modules.Terrain
Command fillRegionCommand = new Command("fill", InterfaceFillTerrain, "Fills the current heightmap with a specified value.");
fillRegionCommand.AddArgument("value", "The numeric value of the height you wish to set your region to.", "Double");
// Brushes
Command elevateCommand = new Command("elevate", InterfaceElevateTerrain, "Raises the current heightmap by the specified amount.");
elevateCommand.AddArgument("amount", "The amount of height to add to the terrain in meters.", "Double");
Command lowerCommand = new Command("lower", InterfaceLowerTerrain, "Lowers the current heightmap by the specified amount.");
lowerCommand.AddArgument("amount", "The amount of height to remove from the terrain in meters.", "Double");
Command multiplyCommand = new Command("multiply", InterfaceMultiplyTerrain, "Multiplies the heightmap by the value specified.");
multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double");
Command bakeRegionCommand = new Command("bake", InterfaceBakeTerrain, "Saves the current terrain into the regions revert map.");
Command revertRegionCommand = new Command("revert", InterfaceRevertTerrain, "Loads the revert map terrain into the regions heightmap.");
// Debug
Command showDebugStatsCommand = new Command("stats", InterfaceShowDebugStats, "Shows some information about the regions heightmap for debugging purposes.");
Command experimentalBrushesCommand = new Command("newbrushes", InterfaceEnableExperimentalBrushes, "Enables experimental brushes which replace the standard terrain brushes. WARNING: This is a debug setting and may be removed at any time.");
experimentalBrushesCommand.AddArgument("Enabled?", "true / false - Enable new brushes", "Boolean");
// Effects
Command effectsTestCommand = new Command("test", InterfacePerformEffectTest, "Performs an effects module test");
m_commander.RegisterCommand("load", loadFromFileCommand);
m_commander.RegisterCommand("load-tile", loadFromTileCommand);
m_commander.RegisterCommand("save", saveToFileCommand);
m_commander.RegisterCommand("fill", fillRegionCommand);
m_commander.RegisterCommand("elevate", elevateCommand);
m_commander.RegisterCommand("lower", lowerCommand);
m_commander.RegisterCommand("multiply", multiplyCommand);
m_commander.RegisterCommand("bake", bakeRegionCommand);
m_commander.RegisterCommand("revert", revertRegionCommand);
m_commander.RegisterCommand("newbrushes", experimentalBrushesCommand);
m_commander.RegisterCommand("test", effectsTestCommand);
m_commander.RegisterCommand("stats", showDebugStatsCommand);
// Add this to our scene so scripts can call these functions
m_scene.RegisterModuleCommander("Terrain", m_commander);
@ -322,7 +435,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain
client.OnModifyTerrain += client_OnModifyTerrain;
}
void SendUpdatedLayerData()
void CheckForTerrainUpdates()
{
bool shouldTaint = false;
float[] serialised = m_channel.GetFloatsSerialised();
@ -333,10 +446,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain
{
if (m_channel.Tainted(x, y))
{
m_scene.ForEachClient(delegate(IClientAPI controller)
{
controller.SendLayerData(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised);
});
SendToClients(serialised, x, y);
shouldTaint = true;
}
}
@ -347,6 +457,14 @@ namespace OpenSim.Region.Environment.Modules.Terrain
}
}
private void SendToClients(float[] serialised, int x, int y)
{
m_scene.ForEachClient(delegate(IClientAPI controller)
{
controller.SendLayerData(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, serialised);
});
}
void client_OnModifyTerrain(float height, float seconds, byte size, byte action, float north, float west, float south, float east, IClientAPI remoteClient)
{
// Not a good permissions check, if in area mode, need to check the entire area.
@ -364,7 +482,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain
if (usingTerrainModule)
{
SendUpdatedLayerData();
CheckForTerrainUpdates();
}
}
else
@ -401,7 +519,7 @@ namespace OpenSim.Region.Environment.Modules.Terrain
if (usingTerrainModule)
{
SendUpdatedLayerData();
CheckForTerrainUpdates();
}
}
else
@ -412,51 +530,6 @@ namespace OpenSim.Region.Environment.Modules.Terrain
}
}
public byte[] WriteJpegImage(string gradientmap)
{
byte[] imageData = null;
try
{
Bitmap bmp = TerrainToBitmap(gradientmap);
imageData = OpenJPEGNet.OpenJPEG.EncodeFromImage(bmp, true);
}
catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke
{
Console.WriteLine("Failed generating terrain map: " + e.ToString());
}
return imageData;
}
private Bitmap TerrainToBitmap(string gradientmap)
{
Bitmap gradientmapLd = new Bitmap(gradientmap);
int pallete = gradientmapLd.Height;
Bitmap bmp = new Bitmap(m_channel.Width, m_channel.Height);
Color[] colours = new Color[pallete];
for (int i = 0; i < pallete; i++)
{
colours[i] = gradientmapLd.GetPixel(0, i);
}
TerrainChannel copy =(TerrainChannel) m_channel.MakeCopy();
for (int y = 0; y < copy.Height; y++)
{
for (int x = 0; x < copy.Width; x++)
{
// 512 is the largest possible height before colours clamp
int colorindex = (int)(Math.Max(Math.Min(1.0, copy[x, y] / 512.0), 0.0) * (pallete - 1));
bmp.SetPixel(x, copy.Height - y - 1, colours[colorindex]);
}
}
return bmp;
}
public void PostInitialise()
{
InstallDefaultEffects();

View File

@ -1916,6 +1916,19 @@ namespace OpenSim.Region.ScriptEngine.Common
m_LSL_Functions.osSetPrimFloatOnWater(floatYN);
}
// Animation Functions
public void osAvatarPlayAnimation(string avatar, string animation)
{
m_LSL_Functions.osAvatarPlayAnimation(avatar, animation);
}
public void osAvatarStopAnimation(string avatar, string animation)
{
m_LSL_Functions.osAvatarStopAnimation(avatar, animation);
}
//Texture Draw functions
public string osMovePen(string drawList, int x, int y)

View File

@ -5119,6 +5119,25 @@ namespace OpenSim.Region.ScriptEngine.Common
}
}
// Adam's super super custom animation functions
public void osAvatarPlayAnimation(string avatar, string animation)
{
if (World.Entities.ContainsKey(avatar) && World.Entities[avatar] is ScenePresence)
{
ScenePresence target = (ScenePresence)World.Entities[avatar];
target.AddAnimation(avatar, 0);
}
}
public void osAvatarStopAnimation(string avatar, string animation)
{
if (World.Entities.ContainsKey(avatar) && World.Entities[avatar] is ScenePresence)
{
ScenePresence target = (ScenePresence)World.Entities[avatar];
target.RemoveAnimation(animation);
}
}
//Texture draw functions
public string osMovePen(string drawList, int x, int y)
{

View File

@ -653,6 +653,10 @@ namespace OpenSim.Region.ScriptEngine.Common
void osSetParcelMediaURL(string url);
void osSetPrimFloatOnWater(int floatYN);
// Animation commands
void osAvatarPlayAnimation(string avatar, string animation);
void osAvatarStopAnimation(string avatar, string animation);
//texture draw functions
string osMovePen(string drawList, int x, int y);
string osDrawLine(string drawList, int startX, int startY, int endX, int endY);