Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C#4.0
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 Smile | :) ). 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 | :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 Smile | :) Smile | :)
 
example code situation
--------------------------------------
 
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 19-Jan-11 6:23am
Comments
JOAT-MON at 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 at 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 :) :)
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

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 Smile | :)
 
 
        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!
  Permalink  
v2
Comments
Thomas.D Williams at 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 :) :)
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

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 Smile | :) Smile | :) thank you to all those who have helped.
  Permalink  

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



Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 20 Jan 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100