使用 WPF 和 C# 绘制覆盖有阴影高度图的 3D 表面

此示例使用 C# 和 XAML 绘制覆盖有阴影高度图的 3D 表面。示例释了如何在三维表面上覆盖图像。此示例执行的操作类似。但是,它不是简单地使用包含网格的现有图像,而是生成一个阴影图像以显示表面的高度。

下面的CreateAltitudeMap方法生成纹理位图。

该方法首先计算所绘制区域的表面函数值。它计算将要创建的图像中每个像素的值,在本例中为 512×512 像素图像。然后,代码使用 LINQ Min和Max方法获取数组中的最大值和最小值。

然后,代码会创建一个BitmapPixelMaker对象。它会循环遍历图像中的像素,并使用相应的函数值来确定像素的颜色。代码使用MapRainbowColor方法(稍后介绍)将每个函数值映射到适当的颜色。

该方法最后调用BitmapPixelMaker对象的MakeBitmap方法来创建WriteableBitmap,然后使用位图的Save扩展方法将结果保存到文件中。

MapRainbowColor 方法使用以下代码将给定边界之间的值映射到颜色。

cs 复制代码
// Map a value to a rainbow color.
private void MapRainbowColor(double value,
    double min_value, double max_value,
    out byte red, out byte green, out byte blue)
{
    // Convert into a value between 0 and 1023.
    int int_value = (int)(1023 * (value - min_value) /
        (max_value - min_value));

    // Map different color bands.
    if (int_value < 256)
    {
        // Red to yellow. (255, 0, 0) to (255, 255, 0).
        red = 255;
        green = (byte)int_value;
        blue = 0;
    }
    else if (int_value < 512)
    {
        // Yellow to green. (255, 255, 0) to (0, 255, 0).
        int_value -= 256;
        red = (byte)(255 - int_value);
        green = 255;
        blue = 0;
    }
    else if (int_value < 768)
    {
        // Green to aqua. (0, 255, 0) to (0, 255, 255).
        int_value -= 512;
        red = 0;
        green = 255;
        blue = (byte)int_value;
    }
    else
    {
        // Aqua to blue. (0, 255, 255) to (0, 0, 255).
        int_value -= 768;
        red = 0;
        green = (byte)(255 - int_value);
        blue = 255;
    }
}

代码首先缩放该值,使其范围从 0 到 1023。根据值是 0 - 255、256 - 511、512 - 767 还是 768 - 1023 范围,代码将颜色转换为彩虹的不同部分。

将网格映射到表面上的程序 类似。以下代码显示了此示例如何使用CreateAltitudeMap方法保存的纹理图像来创建表面的材质。

cs 复制代码
// Create the altitude map texture bitmap.
private void CreateAltitudeMap()
{
    // Calculate the function's value over the area.
    const int xwidth = 512;
    const int zwidth = 512;
    const double dx = (xmax - xmin) / xwidth;
    const double dz = (zmax - zmin) / zwidth;
    double[,] values = new double[xwidth, zwidth];
    for (int ix = 0; ix < xwidth; ix++)
    {
        double x = xmin + ix * dx;
        for (int iz = 0; iz < zwidth; iz++)
        {
            double z = zmin + iz * dz;
            values[ix, iz] = F(x, z);
        }
    }

    // Get the upper and lower bounds on the values.
    var get_values =
        from double value in values
        select value;
    double ymin = get_values.Min();
    double ymax = get_values.Max();

    // Make the BitmapPixelMaker.
    BitmapPixelMaker bm_maker =
        new BitmapPixelMaker(xwidth, zwidth);

    // Set the pixel colors.
    for (int ix = 0; ix < xwidth; ix++)
    {
        for (int iz = 0; iz < zwidth; iz++)
        {
            byte red, green, blue;
            MapRainbowColor(values[ix, iz], ymin, ymax,
                out red, out green, out blue);
            bm_maker.SetPixel(ix, iz, red, green, blue, 255);
        }
    }

    // Convert the BitmapPixelMaker into a WriteableBitmap.
    WriteableBitmap wbitmap = bm_maker.MakeBitmap(96, 96);

    // Save the bitmap into a file.
    wbitmap.Save("Texture.png");
}
cs 复制代码
// Make the surface's material using an image brush.
ImageBrush texture_brush = new ImageBrush();
texture_brush.ImageSource =
    new BitmapImage(new Uri("Texture.png", UriKind.Relative));
DiffuseMaterial surface_material =
    new DiffuseMaterial(texture_brush);

源码:

https://download.csdn.net/download/ljygood2/90120994

相关推荐
他是龙5512 分钟前
70:Python安全 & SSTI模板注入 & Jinja2引擎 & 利用绕过 & 工具实战
开发语言·python·安全
我是唐青枫7 分钟前
C#.NET MemoryMarshal 深入解析:零拷贝内存重解释、二进制读写与使用边界
c#·.net
人道领域8 分钟前
【LeetCode刷题日记】239.滑动窗口最大值:单调队列解法(困难)
java·开发语言·算法
果汁华11 分钟前
Claude Agent SDK Python:构建自主 AI 代理的官方引擎
开发语言·人工智能·python
常利兵12 分钟前
安卓启动页Logo适配秘籍:告别“奇形怪状”的展示
android·java·开发语言
txz203516 分钟前
2,使用功能包组织C++节点
开发语言·c++·ros
知识分享小能手19 分钟前
R语言入门学习教程,从入门到精通,R语言网格绘图系统(ggplot2)- 完整知识点与案例代码(3)
开发语言·学习·r语言
ifuleyou166820 分钟前
《Inter问题》
android·开发语言·kotlin
WL_Aurora21 分钟前
Python基础知识点全解析:从入门到精通
开发语言·python
AI人工智能+电脑小能手21 分钟前
【大白话说Java面试题】【Java基础篇】第17题:HashMap的加载因子为什么是0.75而不是1或0.5
java·开发语言·算法·哈希算法·散列表