C# 3D 프로그래밍, GDI+ Euler Rotation 표현

C# 3D 프로그래밍, GDI+ Euler Rotation 표현



C Sharp - GDI+ Euler Rotation[C# 3D 프로그래밍] GDI 표현, Euler Rotation


C#에서 3D 구현을 위해 GDI+를 사용하기 위한 기본 구성은 다음과 같습니다.


- X, Y, Z의 값을 갖는 클래스를 한 개 생성해야 합니다.

- 3D 변환을 위한 공식에 대입될 값들을 조절할 줄 알아야 합니다.

- 시점을 설정할 카메라 클래스도 설정해야 합니다.

- X, Y, X에 몇 가지 공식을 대입해야 합니다.


직접 2D에서 3D로 변환할 방법은 구체적으론 없지만, 평면에서 이를 조절하는 방안과(Z축의 위치 계산 등) 24개로 이루어진 각 점(정면, 후면, 좌, 우, 상, 하 등 각 4점)의 위치 계산 및 고정을 위한 배열 활용이 중요합니다.


아래는 주요 소스입니다.

Cube 그리기 부분


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public Bitmap drawCube(Point drawOrigin)
{
    //FRONT FACE
    //Top Left - 7
    //Top Right - 4
    //Bottom Left - 6
    //Bottom Right - 5
 
    //Vars
    //Will be actual 2D drawing points
    PointF[] point3D = new PointF[24]; 
    Point tmpOrigin = new Point(00);
 
    //Used for reference
    Math3D.Point3D point0 = new Math3D.Point3D(000);
 
    // Zoom factor is set with the monitor width to 
    // keep the cube from being distorted
    double zoom = (double)Screen.PrimaryScreen.Bounds.Width / 1.5;
 
    //Set up the cube
    Math3D.Point3D[] cubePoints = fillCubeVertices(width, height, depth);
 
    //Calculate the camera Z position to stay constant despite rotation    
    //anchor point
    Math3D.Point3D anchorPoint = (Math3D.Point3D)cubePoints[4]; 
 
    double cameraZ = 
        -(((anchorPoint.X - cubeOrigin.X) * zoom)
        / cubeOrigin.X) + anchorPoint.Z;
 
    camera1.Position = new Math3D.Point3D(cubeOrigin.X, cubeOrigin.Y, cameraZ);
 
    //Apply Rotations, moving the cube to a corner then back to middle
    cubePoints = Math3D.Translate(cubePoints, cubeOrigin, point0);
    cubePoints = Math3D.RotateX(cubePoints, xRotation); //The order of these
    cubePoints = Math3D.RotateY(cubePoints, yRotation); //rotations is the source
    cubePoints = Math3D.RotateZ(cubePoints, zRotation); //of Gimbal Lock
    cubePoints = Math3D.Translate(cubePoints, point0, cubeOrigin);
 
    //Convert 3D Points to 2D
    Math3D.Point3D vec;
 
    for (int i = 0; i < point3D.Length; i++)
    {
        vec = cubePoints[i];
 
        if (vec.Z - camera1.Position.Z >= 0)
        {
            point3D[i].X = (int)
                ((double)-(vec.X - camera1.Position.X) /
                (-0.1f) * zoom) + drawOrigin.X;
 
            point3D[i].Y = (int)
                ((double)(vec.Y - camera1.Position.Y) /
                (-0.1f) * zoom) + drawOrigin.Y;
        }
        else
        {
            tmpOrigin.X = (int)((double)(
                cubeOrigin.X - camera1.Position.X) / 
                (double)(
                cubeOrigin.Z - camera1.Position.Z) * zoom) + 
                drawOrigin.X;
 
            tmpOrigin.Y = (int)((double)
                -(cubeOrigin.Y - camera1.Position.Y) / 
                (double)(
                cubeOrigin.Z - camera1.Position.Z) * zoom) +
                drawOrigin.Y;
 
            point3D[i].X = (float)((vec.X - camera1.Position.X) /
                       (vec.Z - camera1.Position.Z) * zoom + drawOrigin.X);
 
            point3D[i].Y = (float)(-(vec.Y - camera1.Position.Y) /
                       (vec.Z - camera1.Position.Z) * zoom + drawOrigin.Y);
 
            point3D[i].X = (int)point3D[i].X;
            point3D[i].Y = (int)point3D[i].Y;
        }
    }
cs


C# 3D 프로그래밍, GDI+ Euler Rotation 표현[C# 3D 프로그래밍] GDI 표현, Euler Rotation


좌표 변환 X


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static Point3D RotateX(Point3D point3D, double degrees)
{
    //Here we use Euler's matrix formula for
    // rotating a 3D point x degrees around the x-axis
 
    //[ a  b  c ] [ x ]   [ x*a + y*b + z*c ]
    //[ d  e  f ] [ y ] = [ x*d + y*e + z*f ]
    //[ g  h  i ] [ z ]   [ x*g + y*h + z*i ]
 
    //[ 1    00   ]
    //[ 0   cos(x)  sin(x)]
    //[ 0   -sin(x) cos(x)]
 
    //Convert degrees to radian for .Net Cos/Sin functions
    double cDegrees = (Math.PI * degrees) / 180.0f; 
    double cosDegrees = Math.Cos(cDegrees);
    double sinDegrees = Math.Sin(cDegrees);
 
    double y = (point3D.Y * cosDegrees) + (point3D.Z * sinDegrees);
    double z = (point3D.Y * -sinDegrees) + (point3D.Z * cosDegrees);
 
    return new Point3D(point3D.X, y, z);
}
cs


C# 3D 프로그래밍, GDI+ Euler Rotation 표현

댓글(2)

  • hong
    2018.01.10 18:26

    c#에 있는 DrawLine으로 간단히 3D를 구현하려고 찾아왔는데 좋은 예제를 찾은거 같네요.
    근데, 코드를 보고나니 그냥 OpenGL(OpenTK) 사용하는게 정신건강에 좋을거같다는 생각이 드는군요 ㅠㅠ
    시간되시면 OpenGL 기초 예제도 부탁드립니다.

    • 2018.01.18 08:36 신고

      OpenGL은 블로그에 있습니다.
      그리고 말씀처럼 그래픽 다루는 경우엔 오픈지엘이 좋죠.... 무리할 필요가 없네요.

Designed by JB FACTORY