Как вы делаете 3D-преобразование (перспектива) в C # или VB.Net? - PullRequest
0 голосов
/ 07 сентября 2011

То, что я хочу сделать, звучит очень просто, но нигде в Интернете я не нашел способа сделать это в DotNet и не нашел сторонний компонент, который делает это тоже (не тратя тысячи на совершенно ненужные функции),Вот так:

У меня есть jpeg напольной плитки (фактическая фотография), с которой я создаю рисунок шахматной доски.В dotnet легко вращать и сшивать фотографии и сохранять конечное изображение в формате JPEG.

Далее я хочу сделать это окончательное изображение и создать вид, будто «плитки» лежат напол для общей "комнаты сцены".По сути, добавляем трехмерную перспективу, чтобы она выглядела так, как будто она на самом деле находится на сцене комнаты.

Вот сайт, который делает нечто похожее на ковровое покрытие, однако мне нужно сделать это в приложении WinForms: Веб-сайт Flor

По сути, мне нужно создать трехмерную перспективу jpeg, а затем сохранить ее как новый jpeg (тогда я могу наложить наложение общей сцены комнаты).

Кто-нибудь знает, где взять сторонний модуль обработки изображений DotNet, который может выполнить эту, казалось бы, простую задачу?

Ответы [ 2 ]

4 голосов
/ 07 сентября 2011

Это не так просто, потому что вам нужно 3D-преобразование, которое является более сложным и вычислительно дорогим, чем простое 2D-преобразование, такое как вращение, масштабирование или сдвиг. Чтобы вы имели представление о разнице в математике, для двумерных преобразований требуется матрица 2 на 2, тогда как для проекционного преобразования (которое сложнее других трехмерных преобразований) требуется матрица 4 на 4 ...

Что вам нужно, так это какой-то движок 3D-рендеринга, в котором вы можете рисовать полигоны (в перспективе), и они покрывают их текстурой (например, ковром). Для .Net 2.0 я бы порекомендовал использовать SlimDX, который является портом DirectX, который позволит вам визуализировать полигоны, но есть некоторая кривая обучения. Если вы используете WPF (.Net 3.0 и выше), есть встроенный 3D-холст, который позволяет рисовать текстурированные полигоны в перспективе. Это может быть легче / лучше для изучения, чем SlimDX для ваших целей. Я уверен, что есть способ перенаправить вывод 3D-холста в формате JPEG ...

Вы могли бы значительно упростить задачу, если вам не требуется высокая производительность и если вы ограничиваете ориентацию текстуры (например, всегда горизонтальный пол или всегда вертикальная стена). Если это так, вы, вероятно, могли бы сделать это самостоятельно с помощью простого цикла рисования в .Net 2.0.

3 голосов
/ 07 сентября 2011

Если вы просто хотите простой пол, ваш код будет выглядеть следующим образом.ПРЕДУПРЕЖДЕНИЕ. Получение желаемых результатов потребует значительного времени и усилий, особенно если вы не очень хорошо знаете математику.Но с другой стороны, всегда интересно играть с кодом этого типа ... (:

Найдите примеры изображений ниже.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace floorDrawer
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        ResizeRedraw = DoubleBuffered = true;

        Width = 800;
        Height = 600;

        Paint += new PaintEventHandler(Form1_Paint);

    }

    void Form1_Paint(object sender, PaintEventArgs e)
    {

        // a few parameters that control the projection transform
        // these are the parameters that you can modify to change 
        // the output

        double cz = 10; // distortion
        double m = 1000; // magnification, usually around 1000 (the pixel width of the monitor)

        double y0 = -100; // floor height

        string texturePath = @"c:\pj\Hydrangeas.jpg";//@"c:\pj\Chrysanthemum.jpg";


        // screen size
        int height = ClientSize.Height;
        int width = ClientSize.Width;

        // center of screen
        double cx = width / 2;
        double cy = height / 2;



        // render destination
        var dst = new Bitmap(width, height);

        // source texture

        var src = Bitmap.FromFile(texturePath) as Bitmap;

        // texture dimensions
        int tw = src.Width;
        int th = src.Height;

        for (int y = 0; y < height; y++)
            for (int x = 0; x < width; x++)
            {
                double v = m * y0 / (y - cy) - cz;
                double u = (x - cx) * (v + cz) / m;

                int uu = ((int)u % tw + tw) % tw;
                int vv = ((int)v % th + th) % th;
                // The following .SetPixel() and .GetPixel() are painfully slow
                // You can replace this whole loop with an equivalent implementation
                // using pointers inside unsafe{} code to make it much faster.
                // Note that by casting u and v into integers, we are performing
                // a nearest pixel interpolation...  It's sloppy but effective.

                dst.SetPixel(x, y, src.GetPixel(uu, vv));
            }

        // draw result on the form
        e.Graphics.DrawImage(dst, 0, 0);
    }

}
}

This is a sample output using one of Windows 7 sample images.

Another example using another Windows 7 sample picture.

...