再びP3Dを使わずに三次元の物体の描画に挑戦してみました。
[ 実行結果 ]
[ プログラム ]
wasdで移動、tfghで立方体を回転できます。
final int Width_Window = 600; final int Height_Window = 600; final HashMap<Character, Boolean> InputMap = new HashMap<Character, Boolean>() {{ put('w', false); put('s', false); put('d', false); put('a', false); put('t', false); put('g', false); put('h', false); put('f', false); }}; final int FrameRate = 60; final int FieldOfView = 60; final int MoveAmount = 3; final int RotateAmount = 10; Cube3D Cube3D_ = new Cube3D(new Vector3(0, 0, 100), new Vector3(0, 0, 0), 15, color(0, 127, 255, 255)); void settings() { size(Width_Window, Height_Window); } void setup() { frameRate(FrameRate); } void draw() { background(255); Cube3D_.Draw(); if(InputMap.get('w')) { Cube3D_.Add_Pos(new Vector3(0, -MoveAmount, 0)); } if(InputMap.get('s')) { Cube3D_.Add_Pos(new Vector3(0, MoveAmount, 0)); } if(InputMap.get('d')) { Cube3D_.Add_Pos(new Vector3(MoveAmount, 0, 0)); } if(InputMap.get('a')) { Cube3D_.Add_Pos(new Vector3(-MoveAmount, 0, 0)); } if(InputMap.get('t')) { Cube3D_.Add_Rot(new Vector3(-RotateAmount, 0, 0)); } if(InputMap.get('g')) { Cube3D_.Add_Rot(new Vector3(RotateAmount, 0, 0)); } if(InputMap.get('h')) { Cube3D_.Add_Rot(new Vector3(0, -RotateAmount, 0)); } if(InputMap.get('f')) { Cube3D_.Add_Rot(new Vector3(0, RotateAmount, 0)); } for (Character key : InputMap.keySet()) { InputMap.replace(key, false); } } Vector2[] Get_Verts2D(Vector3[] _Verts3D) { final Vector2[] Verts2D = new Vector2[_Verts3D.length]; for (int i = 0; i < _Verts3D.length; i++) { final float Fov = 1 / tan(radians(FieldOfView / 2)); final float Size = (Width_Window > Height_Window ? Width_Window : Height_Window) / 2; final Vector3 CuurentVert2D = _Verts3D[i].Copy(); Vector2 NewVert2D = new Vector2(0, 0); NewVert2D.X += (CuurentVert2D.X / CuurentVert2D.Z) * Fov * Size; NewVert2D.X += Width_Window / 2; NewVert2D.Y += (CuurentVert2D.Y / CuurentVert2D.Z) * Fov * Size; NewVert2D.Y += Height_Window / 2; Verts2D[i] = NewVert2D; } return Verts2D; } void keyPressed() { if(InputMap.containsKey(key)) { InputMap.replace(key, true); } } class Vector2 { float X = 0; float Y = 0; Vector2(float _X, float _Y) { X = _X; Y = _Y; } Vector2 Add(Vector2 _Vector2) { return new Vector2(X + _Vector2.X, Y + _Vector2.Y); } Vector2 Minus() { return new Vector2(-X, -Y); } Vector2 Copy() { return new Vector2(X, Y); } } class Vector3 { float X = 0; float Y = 0; float Z = 0; Vector3(float _X, float _Y, float _Z) { X = _X; Y = _Y; Z = _Z; } Vector3 Add(Vector3 _Vector3) { return new Vector3(X + _Vector3.X, Y + _Vector3.Y, Z + _Vector3.Z); } Vector3 Mult(float _Value) { return new Vector3(X * _Value, Y * _Value, Z * _Value); } Vector3 Cross(Vector3 _Vector3) { return new Vector3(Y * _Vector3.Z - Z * _Vector3.Y, Z * _Vector3.X - X * _Vector3.Z, X * _Vector3.Y - Y * _Vector3.X); } Vector3 Minus() { return new Vector3(-X, -Y, -Z); } Vector3 Copy() { return new Vector3(X, Y, Z); } float Dot(Vector3 _Vector3) { return X * _Vector3.X + Y * _Vector3.Y + Z * _Vector3.Z; } } class Cube3D { Vector3 Pos = new Vector3(0, 0, 0); Vector3 Rot = new Vector3(0, 0, 0); float Scale = 1; color Color = color(0); Vector3[] Verts3D = new Vector3[] { new Vector3(-0.5, -0.5, 0.5), new Vector3(0.5, -0.5, 0.5), new Vector3(-0.5, 0.5, 0.5), new Vector3(0.5, 0.5, 0.5), new Vector3(-0.5, -0.5, -0.5), new Vector3(0.5, -0.5, -0.5), new Vector3(-0.5, 0.5, -0.5), new Vector3(0.5, 0.5, -0.5), }; int[][] Polygons = new int[][] { new int[]{1, 3, 7}, new int[]{1, 7, 5}, new int[]{0, 4, 6}, new int[]{0, 6, 2}, new int[]{0, 1, 4}, new int[]{1, 5, 4}, new int[]{2, 6, 3}, new int[]{3, 6, 7}, new int[]{0, 3, 1}, new int[]{0, 2, 3}, new int[]{4, 5, 7}, new int[]{4, 7, 6}, }; Cube3D(Vector3 _Pos, Vector3 _Rot, float _Scale, color _Color) { Color = _Color; Add_Pos(_Pos); Add_Rot(_Rot); Set_Scale(_Scale); } void Draw() { for (int i = 0; i < Polygons.length; i++) { final int[] Polygon = Polygons[i]; final Vector3[] Verts3D_Polygon = new Vector3[]{Verts3D[Polygon[0]], Verts3D[Polygon[1]], Verts3D[Polygon[2]]}; final Vector3 Vec1 = Verts3D_Polygon[1].Add(Verts3D_Polygon[0].Minus()); final Vector3 Vec2 = Verts3D_Polygon[2].Add(Verts3D_Polygon[0].Minus()); final Vector3 Normal_Polygon = Vec1.Cross(Vec2); final float Dot = Verts3D_Polygon[0].Dot(Normal_Polygon); if(Dot <= 0) { continue; } final Vector2[] Verts2D_Polygon = Get_Verts2D(Verts3D_Polygon); fill(Color); noStroke(); triangle(Verts2D_Polygon[0].X, Verts2D_Polygon[0].Y, Verts2D_Polygon[1].X, Verts2D_Polygon[1].Y, Verts2D_Polygon[2].X, Verts2D_Polygon[2].Y); } } void Add_Pos(Vector3 _Pos) { for (int i = 0; i < Verts3D.length; i++) { final Vector3 CurrentVert3D = Verts3D[i].Copy(); final Vector3 NewVert3D = CurrentVert3D.Copy().Add(_Pos); Verts3D[i] = NewVert3D; } Pos = Pos.Add(_Pos); } void Add_Rot(Vector3 _Rot) { if(_Rot.X != 0) { final float Radian = radians(_Rot.X); final float Sin = sin(Radian); final float Cos = cos(Radian); for (int i = 0; i < Verts3D.length; i++) { final Vector3 CurrentVert3D = Verts3D[i].Copy(); Vector3 NewVert3D = new Vector3(0, 0, 0); NewVert3D.X = CurrentVert3D.X; NewVert3D.Y = Pos.Y + (CurrentVert3D.Y - Pos.Y) * Cos - (CurrentVert3D.Z - Pos.Z) * Sin; NewVert3D.Z = Pos.Z + (CurrentVert3D.Y - Pos.Y) * Sin + (CurrentVert3D.Z - Pos.Z) * Cos; Verts3D[i] = NewVert3D; } } if(_Rot.Y != 0) { final float Radian = radians(_Rot.Y); final float Sin = sin(Radian); final float Cos = cos(Radian); for (int i = 0; i < Verts3D.length; i++) { final Vector3 CurrentVert3D = Verts3D[i].Copy(); Vector3 NewVert3D = new Vector3(0, 0, 0); NewVert3D.X = Pos.X + (CurrentVert3D.Z - Pos.Z) * Sin + (CurrentVert3D.X - Pos.X) * Cos; NewVert3D.Y = CurrentVert3D.Y; NewVert3D.Z = Pos.Z + (CurrentVert3D.Z - Pos.Z) * Cos - (CurrentVert3D.X - Pos.X) * Sin; Verts3D[i] = NewVert3D; } } if(_Rot.Z != 0) { final float Radian = radians(_Rot.Z); final float Sin = sin(Radian); final float Cos = cos(Radian); for (int i = 0; i < Verts3D.length; i++) { final Vector3 CurrentVert3D = Verts3D[i].Copy(); Vector3 NewVert3D = new Vector3(0, 0, 0); NewVert3D.X = Pos.X + (CurrentVert3D.Y - Pos.Y) * Sin + (CurrentVert3D.X - Pos.X) * Cos; NewVert3D.Y = Pos.Y + (CurrentVert3D.Y - Pos.Y) * Cos - (CurrentVert3D.X - Pos.X) * Sin; NewVert3D.Z = CurrentVert3D.Z; Verts3D[i] = NewVert3D; } } Rot = Rot.Add(_Rot); } void Set_Scale(float _Scale) { for (int i = 0; i < Verts3D.length; i++) { final Vector3 CurrentVert3D = Verts3D[i].Copy(); final Vector3 NewVert3D = CurrentVert3D.Copy().Add(Pos.Minus()).Mult(_Scale / Scale).Add(Pos); Verts3D[i] = NewVert3D; } Scale = _Scale; } }