在OpenSim中使用地形

时间:2016-01-04 17:27:50

标签: c#

我想重现亚特兰蒂斯'在OpenSim上学失踪。到目前为止,我只是设法让水升起。我现在希望每次亚特兰蒂斯被置于水下时地形都会下降。这就是我到目前为止:我的代码出了什么问题?

// Place your methods here
private void InterfaceLoadFile(Object[] args)
{
    LoadFromFile((string)args[0]);
}

private void InterfaceLoadTileFile(Object[] args)
{
    LoadFromFile((string)args[0],
                 (int)args[1],
                 (int)args[2],
                 (int)args[3],
                 (int)args[4]);
}

private void InterfaceSaveFile(Object[] args)
{
    SaveToFile((string)args[0]);
}

private void InterfaceSaveTileFile(Object[] args)
{
    SaveToFile((string)args[0],
                 (int)args[1],
                 (int)args[2],
                 (int)args[3],
                 (int)args[4]);
}

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];

}

private void InterfaceFlipTerrain(Object[] args)
{
    String direction = (String)args[0];

    if (direction.ToLower().StartsWith("y"))
    {
        for(int x = 0; x < m_channel.Width; x++)
        {
            for(int y = 0; y < m_channel.Height / 2; y++)
            {
                double height = m_channel[x, y];
                double flippedHeight = m_channel[x, (int)m_channel.Height - 1 - y];
                m_channel[x, y] = flippedHeight;
                m_channel[x, (int)m_channel.Height - 1 - y] = height;

            }
        }
    }
    else if (direction.ToLower().StartsWith("x"))
    {
        for(int y = 0; y < m_channel.Height; y++)
        {
            for(int x = 0; x < m_channel.Width / 2; x++)
            {
                double height = m_channel[x, y];
                double flippedHeight = m_channel[(int)m_channel.Width - 1 - x, y];
                m_channel[x, y] = flippedHeight;
                m_channel[(int)m_channel.Width - 1 - x, y] = height;

            }
        }
    }
    else
    {
        MainConsole.Instance.OutputFormat("ERROR: Unrecognised direction {0} - need x or y", direction);
    }
}

private void InterfaceRescaleTerrain(Object[] args)
{
    double desiredMin = (double)args[0];
    double desiredMax = (double)args[1];

    // determine desired scaling factor
    double desiredRange = desiredMax - desiredMin;
    //m_log.InfoFormat("Desired {0}, {1} = {2}", new Object[] { desiredMin, desiredMax, desiredRange });

    if (desiredRange == 0d)
    {
        // delta is zero so flatten at requested height
        InterfaceFillTerrain(new Object[] { args[1] });
    }
    else
    {
        //work out current heightmap range
        double currMin = double.MaxValue;
        double currMax = double.MinValue;

        int width = m_channel.Width;
        int height = m_channel.Height;

        for(int x = 0; x < width; x++)
        {
            for(int y = 0; y < height; y++)
            {
                double currHeight = m_channel[x, y];
                if (currHeight < currMin)
                {
                    currMin = currHeight;
                }
                else if (currHeight > currMax)
                {
                    currMax = currHeight;
                }
            }
        }

        double currRange = currMax - currMin;
        double scale = desiredRange / currRange;

        //m_log.InfoFormat("Current {0}, {1} = {2}", new Object[] { currMin, currMax, currRange });
        //m_log.InfoFormat("Scale = {0}", scale);

        // scale the heightmap accordingly
        for(int x = 0; x < width; x++)
        {
            for(int y = 0; y < height; y++)
            {
                double currHeight = m_channel[x, y] - currMin;
                m_channel[x, y] = desiredMin + (currHeight * scale);
            }
        }

    }

}

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];
}

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];
}

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];
}

public void InterfaceFillTerrain(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];
}

private void InterfaceMinTerrain(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] = Math.Max((double)args[0], m_channel[x, y]);
        }
    }
}

private void InterfaceMaxTerrain(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] = Math.Min((double)args[0], m_channel[x, y]);
        }
    }
}

private void InterfaceShow(Object[] args)
{
    Vector2 point;

    if (!ConsoleUtil.TryParseConsole2DVector((string)args[0], null, out point))
    {
        Console.WriteLine("ERROR: {0} is not a valid vector", args[0]);
        return;
    }

    double height = m_channel[(int)point.X, (int)point.Y];

    Console.WriteLine("Terrain height at {0} is {1}", point, height);
}

private void InterfaceShowDebugStats(Object[] args)
{
    double max = Double.MinValue;
    double min = double.MaxValue;
    double sum = 0;

    int x;
    for(x = 0; x < m_channel.Width; x++)
    {
        int y;
        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];
        }
    }

    double avg = sum / (m_channel.Height * m_channel.Width);

    MainConsole.Instance.OutputFormat("Channel {0}x{1}", m_channel.Width, m_channel.Height);
    MainConsole.Instance.OutputFormat("max/min/avg/sum: {0}/{1}/{2}/{3}", max, min, avg, sum);
}

private void InterfaceEnableExperimentalBrushes(Object[] args)
{
    if ((bool)args[0])
    {
        m_painteffects[StandardTerrainEffects.Revert] = new WeatherSphere();
        m_painteffects[StandardTerrainEffects.Flatten] = new OlsenSphere();
        m_painteffects[StandardTerrainEffects.Smooth] = new ErodeSphere();
    }
    else
    {
        InstallDefaultEffects();
    }
}

private void InterfaceRunPluginEffect(Object[] args)
{
    string firstArg = (string)args[0];

    if (firstArg == "list")
    {
        MainConsole.Instance.Output("List of loaded plugins");
        foreach(KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects)
        {
            MainConsole.Instance.Output(kvp.Key);
        }
        return;
    }

    if (firstArg == "reload")
    {
        LoadPlugins();
        return;
    }

    if (m_plugineffects.ContainsKey(firstArg))
    {
        m_plugineffects[firstArg].RunEffect(m_channel);
    }
    else
    {
        MainConsole.Instance.Output("WARNING: No such plugin effect {0} loaded.", firstArg);
    }
}

private void InstallInterfaces()
{
    Command loadFromFileCommand =
        new Command("load", CommandIntentions.COMMAND_HAZARDOUS, InterfaceLoadFile, "Loads a terrain from a specified file.");
    loadFromFileCommand.AddArgument("filename",
                                    "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " +
                                    m_supportedFileExtensions, "String");

    Command saveToFileCommand =
        new Command("save", CommandIntentions.COMMAND_NON_HAZARDOUS, InterfaceSaveFile, "Saves the current heightmap to a specified file.");
    saveToFileCommand.AddArgument("filename",
                                  "The destination filename for your heightmap, the file extension determines the format to save in. Supported extensions include: " +
                                  m_supportedFileExtensions, "String");

    Command loadFromTileCommand =
        new Command("load-tile", CommandIntentions.COMMAND_HAZARDOUS, InterfaceLoadTileFile, "Loads a terrain from a section of a larger file.");
    loadFromTileCommand.AddArgument("filename",
                                    "The file you wish to load from, the file extension determines the loader to be used. Supported extensions include: " +
                                    m_supportedFileExtensions, "String");
    loadFromTileCommand.AddArgument("file width", "The width of the file in tiles", "Integer");
    loadFromTileCommand.AddArgument("file height", "The height of the file in tiles", "Integer");
    loadFromTileCommand.AddArgument("minimum X tile", "The X region coordinate of the first section on the file",
                                    "Integer");
    loadFromTileCommand.AddArgument("minimum Y tile", "The Y region coordinate of the first section on the file",
                                    "Integer");

    Command saveToTileCommand =
        new Command("save-tile", CommandIntentions.COMMAND_HAZARDOUS, InterfaceSaveTileFile, "Saves the current heightmap to the larger file.");
    saveToTileCommand.AddArgument("filename",
                                    "The file you wish to save to, the file extension determines the loader to be used. Supported extensions include: " +
                                    m_supportFileExtensionsForTileSave, "String");
    saveToTileCommand.AddArgument("file width", "The width of the file in tiles", "Integer");
    saveToTileCommand.AddArgument("file height", "The height of the file in tiles", "Integer");
    saveToTileCommand.AddArgument("minimum X tile", "The X region coordinate of the first section on the file",
                                    "Integer");
    saveToTileCommand.AddArgument("minimum Y tile", "The Y region coordinate of the first tile on the file\n"
                                  + "= Example =\n"
                                  + "To save a PNG file for a set of map tiles 2 regions wide and 3 regions high from map co-ordinate (9910,10234)\n"
                                  + "        # terrain save-tile ST06.png 2 3 9910 10234\n",
                                  "Integer");

    // Terrain adjustments
    Command fillRegionCommand =
        new Command("fill", CommandIntentions.COMMAND_HAZARDOUS, 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");

    Command elevateCommand =
        new Command("elevate", CommandIntentions.COMMAND_HAZARDOUS, 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", CommandIntentions.COMMAND_HAZARDOUS, 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", CommandIntentions.COMMAND_HAZARDOUS, InterfaceMultiplyTerrain, "Multiplies the heightmap by the value specified.");
    multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double");

    Command bakeRegionCommand =
        new Command("bake", CommandIntentions.COMMAND_HAZARDOUS, InterfaceBakeTerrain, "Saves the current terrain into the regions revert map.");
    Command revertRegionCommand =
        new Command("revert", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRevertTerrain, "Loads the revert map terrain into the regions heightmap.");

    Command flipCommand =
        new Command("flip", CommandIntentions.COMMAND_HAZARDOUS, InterfaceFlipTerrain, "Flips the current terrain about the X or Y axis");
    flipCommand.AddArgument("direction", "[x|y] the direction to flip the terrain in", "String");

    Command rescaleCommand =
        new Command("rescale", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRescaleTerrain, "Rescales the current terrain to fit between the given min and max heights");
    rescaleCommand.AddArgument("min", "min terrain height after rescaling", "Double");
    rescaleCommand.AddArgument("max", "max terrain height after rescaling", "Double");

    Command minCommand = new Command("min", CommandIntentions.COMMAND_HAZARDOUS, InterfaceMinTerrain, "Sets the minimum terrain height to the specified value.");
    minCommand.AddArgument("min", "terrain height to use as minimum", "Double");

    Command maxCommand = new Command("max", CommandIntentions.COMMAND_HAZARDOUS, InterfaceMaxTerrain, "Sets the maximum terrain height to the specified value.");
    maxCommand.AddArgument("min", "terrain height to use as maximum", "Double");


    // Debug
    Command showDebugStatsCommand =
        new Command("stats", CommandIntentions.COMMAND_STATISTICAL, InterfaceShowDebugStats,
                    "Shows some information about the regions heightmap for debugging purposes.");

    Command showCommand =
        new Command("show", CommandIntentions.COMMAND_NON_HAZARDOUS, InterfaceShow,
                    "Shows terrain height at a given co-ordinate.");
    showCommand.AddArgument("point", "point in <x>,<y> format with no spaces (e.g. 45,45)", "String");

    Command experimentalBrushesCommand =
        new Command("newbrushes", CommandIntentions.COMMAND_HAZARDOUS, 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");

    // Plugins
    Command pluginRunCommand =
        new Command("effect", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRunPluginEffect, "Runs a specified plugin effect");
    pluginRunCommand.AddArgument("name", "The plugin effect you wish to run, or 'list' to see all plugins", "String");



    m_commander.RegisterCommand("multiply", multiplyCommand);

    m
    // Add this to our scene so scripts can call these functions
    m_scene.RegisterModuleCommander(m_commander);

    // Add Modify command to Scene, since Command object requires fixed-length arglists
    m_scene.AddCommand("Terrain", this, "terrain modify",
                       "terrain modify <operation> <value> [<area>] [<taper>]",
                       "Modifies the terrain as instructed." +
                       "\nEach operation can be limited to an area of effect:" +
                       "\n * -ell=x,y,rx[,ry] constrains the operation to an ellipse centred at x,y" +
                       "\n * -rec=x,y,dx[,dy] constrains the operation to a rectangle based at x,y" +
                       "\nEach operation can have its effect tapered based on distance from centre:" +
                       "\n * elliptical operations taper as cones" +
                       "\n * rectangular operations taper as pyramids"
                       ,
                       ModifyCommand);

}

public 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];
}

private void InstallInterfaces()
{


    Command multiplyCommand =
        new Command("multiply", CommandIntentions.COMMAND_HAZARDOUS, InterfaceMultiplyTerrain, "Multiplies the heightmap by the value specified.");
    multiplyCommand.AddArgument("value", "The value to multiply the heightmap by.", "Double");



    // Debug
    Command showDebugStatsCommand =
        new Command("stats", CommandIntentions.COMMAND_STATISTICAL, InterfaceShowDebugStats,
                    "Shows some information about the regions heightmap for debugging purposes.");


    // Plugins
    Command pluginRunCommand =
        new Command("effect", CommandIntentions.COMMAND_HAZARDOUS, InterfaceRunPluginEffect, "Runs a specified plugin effect");
    pluginRunCommand.AddArgument("name", "The plugin effect you wish to run, or 'list' to see all plugins", "String");



    m_commander.RegisterCommand("multiply", multiplyCommand);


    // Add this to our scene so scripts can call these functions
    m_scene.RegisterModuleCommander(m_commander);

    // Add Modify command to Scene, since Command object requires fixed-length arglists
    m_scene.AddCommand("Terrain", this, "terrain modify",
                       "terrain modify <operation> <value> [<area>] [<taper>]",
                       "Modifies the terrain as instructed." +
                       "\nEach operation can be limited to an area of effect:" +
                       "\n * -ell=x,y,rx[,ry] constrains the operation to an ellipse centred at x,y" +
                       "\n * -rec=x,y,dx[,dy] constrains the operation to a rectangle based at x,y" +
                       "\nEach operation can have its effect tapered based on distance from centre:" +
                       "\n * elliptical operations taper as cones" +
                       "\n * rectangular operations taper as pyramids"
                       ,
                       ModifyCommand);

}

public void UpdateTerrainWithTide()
{
            InterfaceMultiplyTerrain(0.95);
            multiplyCommand = 0.95;
            multiplyCommand(0.95);
   }

public void ModifyCommand(string module, string[] cmd)
{
    string result;
    Scene scene = SceneManager.Instance.CurrentScene;
    if ((scene != null) && (scene != m_scene))
    {
        result = String.Empty;
    }
    else if (cmd.Length > 2)
    {
        string operationType = cmd[2];


        ITerrainModifier operation;
        if (!m_modifyOperations.TryGetValue(operationType, out operation))
        {
            result = String.Format("Terrain Modify \"{0}\" not found.", operationType);
        }
        else if ((cmd.Length > 3) && (cmd[3] == "usage"))
        {
            result = "Usage: " + operation.GetUsage();
        }
        else
        {
            result = operation.ModifyTerrain(m_channel, cmd);
        }

        if (result == String.Empty)
        {
            result = "Modified terrain";
            m_log.DebugFormat("Performed terrain operation {0}", operationType);
        }
    }
    else
    {
        result = "Usage: <operation-name> <arg1> <arg2>...";
    }
    if (result != String.Empty)
    {
        MainConsole.Instance.Output(result);
    }
}




public void TideUpdate ()
{
    ulong timeStamp;
    double cyclePos; //cycles from 0.0000000001 to 0.999999999999
    double cycleRadians;
    double tideRange;
    double tideMiddle;
    string tideLevelMsg;

    if (((m_frame++ % m_frameUpdateRate) != 0) || !m_ready) {
        return;
    }
    timeStamp = (ulong) (DateTime.Now.Ticks);

    cyclePos = (double)(timeStamp % (m_cycleTime * TICKS_PER_SECOND)) / (m_cycleTime * TICKS_PER_SECOND);
    cycleRadians = cyclePos * Math.PI * 2;

    if (cyclePos < 0.5) m_tideDirection = false; else m_tideDirection = true;

    if (m_tideDirection != m_lastTideDirection)
    { //if the tide changes re-calculate the tide times
        if (cyclePos < 0.5)
        { // tide just changed to be high->low
            m_lowTideTime = DateTime.Now.AddSeconds((double)(m_cycleTime * (0.5 - cyclePos)));
            m_highTideTime = m_lowTideTime.AddSeconds((double)(m_cycleTime / 2));
            m_tideAnnounceMsg = "High Tide";
        }
        else
        {   //tide just changed to be low->high
            m_highTideTime = DateTime.Now.AddSeconds((double)(m_cycleTime * (1.0 - cyclePos)));
            m_lowTideTime = m_highTideTime.AddSeconds((double)(m_cycleTime / 2));
            m_tideAnnounceMsg = "Low Tide";
        }
        m_lastTideDirection = m_tideDirection;
    }
    tideRange = (double) (m_highTide - m_lowTide) / 2;
    tideMiddle = (double) m_lowTide + tideRange;
    m_tideLevel = (float) (Math.Cos(cycleRadians) * tideRange + tideMiddle);

    tideLevelMsg = "Current Server Time: " + DateTime.Now.ToString("T") + "\n";
    tideLevelMsg += "Current Tide Level: " + m_tideLevel.ToString() + "\n";
    tideLevelMsg += "Low Tide Time: " + m_lowTideTime.ToString("T") + "\n";
    tideLevelMsg += "Low Tide Level: " + m_lowTide.ToString() + "\n";
    tideLevelMsg += "High Tide Time: " + m_highTideTime.ToString("T") + "\n";
    tideLevelMsg += "High Tide Level: " + m_highTide.ToString() + "\n";
    tideLevelMsg += "Tide Direction: " + ((m_tideDirection) ? "Coming In" : "Going Out") + "\n";
    tideLevelMsg += "Cycle Position: " + cyclePos.ToString() + "\n";
    if (m_tideAnnounceMsg != "")
    {
        if (m_tideAnnounceCounter++ > m_tideAnnounceCount)
        {
            m_tideAnnounceCounter = 0;
            m_tideAnnounceMsg = "";
        }
        else
        {
            tideLevelMsg += "Tide Warning: " + m_tideAnnounceMsg + "\n";
        }
    }

    if (m_tideInfoDebug) m_log.InfoFormat("[{0}]: Sea Level currently at {1}m in Region: {2}", m_name, m_tideLevel, m_scene.RegionInfo.RegionName);

    if (m_tideInfoBroadcast && m_tideDirection)
    {
        m_scene.SimChatBroadcast(Utils.StringToBytes(tideLevelMsg), ChatTypeEnum.Region, m_tideInfoChannel, m_shoutPos, "TIDE", UUID.Zero, false);
        m_scene.SimChatBroadcast(Utils.StringToBytes(m_tideLevel.ToString()), ChatTypeEnum.Region, m_tideLevelChannel, m_shoutPos, "TIDE", UUID.Zero, false);
    }
    if (m_tideInfoDebug) m_log.InfoFormat("[{0}]: Updating Region: {1}", m_name, m_scene.RegionInfo.RegionName);

    m_scene.RegionInfo.RegionSettings.WaterHeight = m_tideLevel;
    m_scene.EventManager.TriggerRequestChangeWaterHeight(m_tideLevel);
    m_scene.EventManager.TriggerTerrainTick();

    if (m_tideInfoBroadcast && !m_tideDirection)
    {
        m_scene.SimChatBroadcast(Utils.StringToBytes(tideLevelMsg), ChatTypeEnum.Region, m_tideInfoChannel, m_shoutPos, "TIDE", UUID.Zero, false);
        m_scene.SimChatBroadcast(Utils.StringToBytes(m_tideLevel.ToString()), ChatTypeEnum.Region, m_tideLevelChannel, m_shoutPos, "TIDE", UUID.Zero, false);
    }
}

1 个答案:

答案 0 :(得分:0)

建议 - 开始搜索ossl实现的代码,然后对它们进行反向工程以确定地形如何工作。基本上它是修改位图(我认为)然后当刷新时差异被流式传输到客户端。

https://github.com/opensim/opensim/search?utf8=%E2%9C%93&q=osSetTerrainHeight

脚本版本:

default
 {
   touch_start()
   {
    osSetTerrainHeight(40, 101, 21.4);
    osTerrainFlush();
    }
 }