Click here to Skip to main content
15,886,806 members
Please Sign up or sign in to vote.
5.00/5 (3 votes)
See more:
Hi all,

I am currently stuck on a personal challenge project. To build a 3D engine in C# using only the GDI (to learn c# & 3d math to go with). I have currently built an engine that can have 3D objects added to it, with basic face drawing (Also has basic lighting using inverse square law :) ). I am stuck at drawing a texture to a given face/triangle.

How could I draw an Image to a parallelogram/triangle such that the corners of the original image match that of a parallelogram? :confused:
(Bare in mind that these are the 2D co-ordinates not the 3D ones they were calculated from)


Thank you all who help me solve this :) :)

example code situation
--------------------------------------

C#
Image Texture;      //From engine source
Point[] DrawPoints; //4 points of parallelogram // 3 points of triangle (either)
Graphics Drawer;

//TODO - Draw Texture to map to the 3/4 points of draw points
Posted
Comments
JOAT-MON 19-Jan-11 16:26pm    
Suggestion: I don't have an answer for you off-hand, I haven't morphed images in this manner, but have you looked at the capabilities of either the GraphicsPath class and/or Matrix class to accomplish this?
Thomas.D Williams 19-Jan-11 16:48pm    
I have looked, however it has not been that useful. I have only found it useful in retrieving a part of an image/texture (e.g a triangle shape) to draw but not actually drawing it 3D. I'm not aware that it can actually transform an image. I may have to research more into paths.
Thank you for the suggestion :) :)

This is going to be a long answer. I post the code, which I think is rather straightforward, but if you feel you need further explanations, I will post comments.

I guess you can accomplish this more easily (and faster) with advanced math, but I bet you'll get the main idea from the simple code below. I warn you that this code is very slow; try it with small images. Due to lack of time this code is not optimized at all, you can easily improve speed by changing a few lines, but I leave it to you :)

protected override void OnPaint(PaintEventArgs e)
{
    if (Texture == null)
    {
        return;
    }

    Bitmap bmp = (Bitmap)Texture;

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

    using (Graphics g = this.CreateGraphics())
    {
        g.Clear(Color.Black);

        Point[] Dwu = this.DivideEdge(DrawPoints[0], DrawPoints[1], width, false);
        Point[] Dwd = this.DivideEdge(DrawPoints[2], DrawPoints[3], width, true);

        Point[] Dhl = this.DivideEdge(DrawPoints[3], DrawPoints[0], height, false);
        Point[] Dhr = this.DivideEdge(DrawPoints[1], DrawPoints[2], height, true);

        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                Point a = GetIntersection(Dwu[x], Dwd[x], Dhl[y], Dhr[y]);
                g.DrawRectangle(new Pen(bmp.GetPixel(x, y)), a.X, a.Y, 1, 1);
            }
        }
    }
}

Point[] DivideEdge(Point a, Point b, int points, bool reverse)
{
    Point[] d = new Point[points + 1];

    for (int i = 0; i <= points; i++)
    {
        d[i] = new Point(a.X + (b.X - a.X) * i / points, a.Y + (b.Y - a.Y) * i / points);
    }

    if (reverse)
    {
        Point[] d2 = new Point[points + 1];
        for (int j = 0; j <= points; j++)
        {
            d2[points - j] = d[j];
        }

        return d2;
    }
    else
    {
        return d;
    }
}

public Point GetIntersection(Point p1, Point p2, Point p3, Point p4)
{
    int x1 = p1.X;int x2 = p2.X;int x3 = p3.X;int x4 = p4.X;
    int y1 = p1.Y;int y2 = p2.Y;int y3 = p3.Y;int y4 = p4.Y;

    float d = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
    if (d == 0f)
    {
        return new Point(0, 0);
    }

    float na = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
    float nb = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3);
    float ua = na / d;
    float ub = nb / d;

    return new Point((int)(x1 + ua * (x2 - x1)), (int)(y1 + ua * (y2 - y1)));
}


Hope this helps, good luck!
 
Share this answer
 
v2
Comments
Thomas.D Williams 20-Jan-11 2:52am    
Thank you. I never thought of doing it like this. From what I can make of your code you re-draw every pixel from a texture to a different location you calculate in 'GetIntersection'. I have already seen I can speed it up in my Engines draw sequence, Mainly by using pre-defined graphics objects. I have found it rather interesting how slow 'CreateGraphics' is.
I will be looking at it later when I get back from college. Thank you so much :) and thank you for the time you put in getting a solution :) :)
I have found a solution to the problem.

I stumbled on this application somewhere on the web
http://www.vcskicks.com/image-distortion.php[^]

The source code in the example does exactly what I asked. I am now implementing a solution :) :) thank you to all those who have helped.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900