C# 3D 프로그래밍, GDI+ Euler Rotation 표현
- 코딩 팁
- 2017. 6. 20.
C# 3D 프로그래밍, GDI+ Euler Rotation 표현
프로젝트 - WindowsApplication2.zip
C#에서 3D 구현을 위해 GDI+를 사용하기 위한 기본 구성은 다음과 같습니다.
- X, Y, Z의 값을 갖는 클래스를 한 개 생성해야 합니다.
- 3D 변환을 위한 공식에 대입될 값들을 조절할 줄 알아야 합니다.
- 시점을 설정할 카메라 클래스도 설정해야 합니다.
- X, Y, X에 몇 가지 공식을 대입해야 합니다.
직접 2D에서 3D로 변환할 방법은 구체적으론 없지만, 평면에서 이를 조절하는 방안과(Z축의 위치 계산 등) 24개로 이루어진 각 점(정면, 후면, 좌, 우, 상, 하 등 각 4점)의 위치 계산 및 고정을 위한 배열 활용이 중요합니다.
2D <-> 3D간 변환 공식은 아래 사이트를 참고하세요.
아래는 주요 소스입니다.
Cube 그리기 부분
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 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 pointsPointF[] point3D = new PointF[24];Point tmpOrigin = new Point(0, 0);//Used for referenceMath3D.Point3D point0 = new Math3D.Point3D(0, 0, 0);// Zoom factor is set with the monitor width to// keep the cube from being distorteddouble zoom = (double)Screen.PrimaryScreen.Bounds.Width / 1.5;//Set up the cubeMath3D.Point3D[] cubePoints = fillCubeVertices(width, height, depth);//Calculate the camera Z position to stay constant despite rotation//anchor pointMath3D.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 middlecubePoints = Math3D.Translate(cubePoints, cubeOrigin, point0);cubePoints = Math3D.RotateX(cubePoints, xRotation); //The order of thesecubePoints = Math3D.RotateY(cubePoints, yRotation); //rotations is the sourcecubePoints = Math3D.RotateZ(cubePoints, zRotation); //of Gimbal LockcubePoints = Math3D.Translate(cubePoints, point0, cubeOrigin);//Convert 3D Points to 2DMath3D.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
좌표 변환 X
1234567891011121314151617181920212223 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 functionsdouble 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 표현
-
hong2018.01.10 18:26
c#에 있는 DrawLine으로 간단히 3D를 구현하려고 찾아왔는데 좋은 예제를 찾은거 같네요.
근데, 코드를 보고나니 그냥 OpenGL(OpenTK) 사용하는게 정신건강에 좋을거같다는 생각이 드는군요 ㅠㅠ
시간되시면 OpenGL 기초 예제도 부탁드립니다.-
2018.01.18 08:36 신고
OpenGL은 블로그에 있습니다.
그리고 말씀처럼 그래픽 다루는 경우엔 오픈지엘이 좋죠.... 무리할 필요가 없네요.
-
-
2022.01.07 15:55 신고
3D 에서 2D 변환하는 부분이 어려운데.. 공식을 참조할 곳이나 설명부탁드려도 될까요?
-
2022.01.08 10:23 신고
안녕하세요. 본문에 공식 참고할 사이트 추가했습니다.
-