public static double[,] ConvertToCamera(double[,] pontos, Vector VRP, Vector P) { Vector bigN = new Vector(); bigN.X = VRP.X - P.X; bigN.Y = VRP.Y - P.Y; bigN.Z = VRP.Z - P.Z; Vector vectorN = NormalizeVector(bigN); Vector Y = new Vector(0, 1, 0); Vector n1 = new Vector(); double aux = DotProduct(Y, vectorN); n1.X = aux*vectorN.X; n1.Y = aux*vectorN.Y; n1.Z = aux*vectorN.Z; Vector v = new Vector(Y.X - n1.X, Y.Y - n1.Y, Y.Z - n1.Z); v = NormalizeVector(v); Vector u = new Vector(); u = CrossProduct(v, vectorN); double[,] M = new double[,] { {u.X, u.Y, u.Z, -1*DotProduct(VRP, u)}, {v.X, v.Y, v.Z, -1*DotProduct(VRP, v)}, {vectorN.X, vectorN.Y, vectorN.Z, -1*DotProduct(VRP, vectorN)}, {0, 0, 0, 1} }; return MatrixMultiplication(M, pontos); }
public static Vector CrossProduct(Vector a, Vector b) { var x = new Vector(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - b.Z * a.X, a.X * b.Y - a.Y * b.X); x = NormalizeVector(x); return x; }
public Solid() { //cria um solido padrao _points = new double[,] { {0,0,50,1}, {50,0,50,1}, {50,50,50,1}, {0,50,50,1}, {0,0,0,1}, {50,0,0,1}, {50,50,0,1}, {0,50,0,1}, {25,25,25,1} }; _edges = new[,] { {0,1}, {1,2}, {2,3}, {3,0}, {1,5}, {5,6}, {6,2}, {5,4}, {4,7}, {7,6}, {4,0}, {3,7} }; Faces = new[,] { {0,1,2,3}, {1,5,6,2}, {5,4,7,6}, {0,3,7,4}, {3,2,6,7}, {0,4,5,1} }; FlatColor = new Vector[6]; _points = MathOperations.TransposeMatrix(_points); _ka = new Vector(0.3, 0.5, 0.2); _ks = new Vector(0.9, 0.4, 0.1); _kd = new Vector(0.1, 0.8, 0.3); n = 4; }
public static double DotProduct(Vector a, Vector b) { return a.X * b.X + a.Y * b.Y + a.Z * b.Z; }
public static Vector NormalizeVector(Vector x) { var module = Math.Sqrt(x.X * x.X + x.Y * x.Y + x.Z * x.Z); return new Vector(x.X / module, x.Y / module, x.Z / module); }
private void MainView_Load(object sender, EventArgs e) { solidsList = new List<List<Solid>>(); //Aloca a lista de solido perspectiveSolidList = new List<List<Solid>>(); selectedGuy = -1; //configura o solido selecionado para: nenhum selectedSolids = new List<int>(); amIRotating = false; P = new Vector(30, 20, 50); VRP = new Vector(300, 500, 3000); Y = new Vector(0, 1, 0); VRPiso = new Vector(300, 300, 300); alpha = 110; L = new Vector(100, 10, 150); iL = new Vector(150, 100, 250); iLa = new Vector(20, 80, 50); xMin = yMin = 0; xMax = yMax = 315; }
public void ComputeVisibility(Vector vrp, Vector P =null) { //processa cada face e determina sua visibilidade var n = new Vector(); //vetor vrp - p n.X = vrp.X - (P == null?Points[0, 8]:P.X); n.Y = vrp.Y - (P == null?Points[1, 8]:P.Y); n.Z = vrp.Z - (P == null?Points[2, 8]:P.Z); n = MathOperations.NormalizeVector(n); for (int i = 0; i < 6; i++) { //processa as faces uma a uma var vec1 = new Vector(_points[0, Faces[i, 1]] - _points[0, Faces[i, 0]], _points[1, Faces[i, 1]] - _points[1, Faces[i, 0]], _points[2, Faces[i, 1]] - _points[2, Faces[i, 0]]); //vetor 1 da face var vec2 = new Vector(_points[0, Faces[i, 2]] - _points[0, Faces[i, 1]], _points[1, Faces[i, 2]] - _points[1, Faces[i, 1]], _points[2, Faces[i, 2]] - _points[2, Faces[i, 1]]); //vetor 2 da face var face = MathOperations.CrossProduct(vec1, vec2); //vetor normal a face face = MathOperations.NormalizeVector(face); var visibilityK = MathOperations.DotProduct(face, n); //coeficiente de visibilidade if (visibilityK > 0) { _visibleFaces[i] = true; normalFaces[i] = face; } else { _visibleFaces[i] = false; normalFaces[i] = face; } } }
private void PerspectiveTransformation() { #region Camera Transformations perspectiveSolidList = solidsList.Clone(); var bigN = new Vector { X = VRP.X - P.X, Y = VRP.Y - P.Y, Z = VRP.Z - P.Z }; var n = MathOperations.NormalizeVector(bigN); var n1 = new Vector(); var aux = MathOperations.DotProduct(Y, n); n1.X = aux * n.X; n1.Y = aux * n.Y; n1.Z = aux * n.Z; var v = new Vector(Y.X - n1.X, Y.Y - n1.Y, Y.Z - n1.Z); v = MathOperations.NormalizeVector(v); var u = new Vector(); u = MathOperations.CrossProduct(v, n); var M = new double[,] { {u.X, u.Y, u.Z, -1*MathOperations.DotProduct(VRP, u)}, {v.X, v.Y, v.Z, -1*MathOperations.DotProduct(VRP, v)}, {n.X, n.Y, n.Z, -1*MathOperations.DotProduct(VRP, n)}, {0,0,0,1} }; foreach (var solid in perspectiveSolidList.SelectMany(t => t)) { solid.Points = M.Multiply(solid.Points); } #endregion var dp = Math.Sqrt(Math.Pow(VRP.X - P.X, 2) + Math.Pow(VRP.Y - P.Y, 2) + Math.Pow(VRP.Z - P.Z, 2)); //Transformacao perspectiva var perspecMatrix = new double[,] { {1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,-1/(dp*alpha/100.0),0}, }; foreach (var solid in perspectiveSolidList.SelectMany(t => t)) { solid.Points = MathOperations.MatrixMultiplication(perspecMatrix, solid.Points); for (var i = 0; i < solid.Points.GetLength(0); i++) { for (var j = 0; j < solid.Points.GetLength(1); j++) { solid.Points[i, j] /= solid.Points[solid.Points.GetLength(0) - 1, j]; } } } }
public int DecideMid(Vector ponto1, Vector ponto2, Vector ponto3, Vector ponto4) { Vector[] aux = new Vector[]{ponto1, ponto2, ponto3, ponto4}; int menor = (int)aux[0].Y; int j = 0; //Pega o menor for (int i = 0; i < 4; i++) { if (aux[i].Y < menor) { menor = (int)aux[i].Y; j = i; } } //Teste se alguem eh igual for (int i = 0; i < 4; i++) { if (aux[i].Y == menor && j != i) { if (aux[i].X < aux[j].X) return i; } } return j; /*if (ponto1.Y.CompareTo(ponto2.Y) <= 0) { if (ponto3.Y.CompareTo(ponto4) <= 0) { return ponto1.Y <= ponto3.Y ? 0 : 2; } return ponto1.Y <= ponto4.Y ? 0 : 3; } if (ponto3.Y.CompareTo(ponto4) <= 0) { return ponto2.Y <= ponto3.Y ? 1 : 2; } return ponto2.Y <= ponto4.Y ? 1 : 3;*/ }
public void ZBuffer(int view, PictureBox pc) { switch (view) { case 0 : //Top view MapToScreen(0); break; case 1 : //Front view MapToScreen(1); #region Truncamento foreach (var list in perspectiveSolidList) { foreach (var solid in list) { for (int i = 0; i < solid.Points.GetLength(0); i++) { for (int j = 0; j < solid.Points.GetLength(1); j++) { solid.Points[i, j] = (int) solid.Points[i, j]; } } } } #endregion foreach (var solid in perspectiveSolidList.SelectMany(solidList => solidList)) { solid.ComputeVisibility(new Vector(solid.Points[0, 8], solid.Points[1, 8], 1)); for (int i = 0; i < 6; i++) { if (!solid.VisibleFaces[i]) continue; int yMenor = DecideMid( new Vector(solid.Points[0, solid.Faces[i, 0]], solid.Points[1, solid.Faces[i, 0]], solid.Points[2, solid.Faces[i, 0]]), new Vector(solid.Points[0, solid.Faces[i, 1]], solid.Points[1, solid.Faces[i, 1]], solid.Points[2, solid.Faces[i, 1]]), new Vector(solid.Points[0, solid.Faces[i, 2]], solid.Points[1, solid.Faces[i, 2]], solid.Points[2, solid.Faces[i, 2]]), new Vector(solid.Points[0, solid.Faces[i, 3]], solid.Points[1, solid.Faces[i, 3]], solid.Points[2, solid.Faces[i, 3]])); Vector mid = new Vector((int)solid.Points[0, solid.Faces[i, yMenor]], (int)solid.Points[1, solid.Faces[i, yMenor]], (int)solid.Points[2, solid.Faces[i, yMenor]]); Vector prev = new Vector((int)solid.Points[0, solid.Faces[i, (yMenor + 1) % 4]], (int)solid.Points[1, solid.Faces[i, (yMenor + 1) % 4]], (int)solid.Points[2, solid.Faces[i, (yMenor + 1) % 4]]); Vector next = new Vector((int)solid.Points[0, solid.Faces[i, (yMenor - 1 < 0 ? 3 : yMenor - 1)]], (int)solid.Points[1, solid.Faces[i, (yMenor - 1 < 0 ? 3 : yMenor - 1)]], (int)solid.Points[2, solid.Faces[i, (yMenor - 1 < 0 ? 3 : yMenor - 1)]]); Vector end = new Vector((int)solid.Points[0, solid.Faces[i, (yMenor + 2) % 4]], (int)solid.Points[1, solid.Faces[i, (yMenor + 2) % 4]], (int)solid.Points[2, solid.Faces[i, (yMenor + 2) % 4]]); double deltaX1 = 0; double deltaX2 = 0; double deltaZ1 = 0; double deltaZ2 = 0; if (!(mid.Y == prev.Y)) { deltaX1 = GetDelta(mid.X, prev.X, mid.Y, prev.Y); deltaZ1 = GetDelta(mid.Z, prev.Z, mid.Y, prev.Y); } if (!(mid.Y == next.Y)) { deltaX2 = GetDelta(mid.X, next.X, mid.Y, next.Y); deltaZ2 = GetDelta(mid.Z, next.Z, mid.Y, next.Y); } Console.WriteLine("Delta x1: {0}", deltaX1); Console.WriteLine("Delta z1: {0}", deltaZ1); Console.WriteLine("Delta x2: {0}", deltaX2); Console.WriteLine("Delta z2: {0}", deltaZ2); int k1 = 1; int k2 = 1; for (int w = 0; w < (int)(end.Y-mid.Y); w++) { Vector ponto1 = new Vector(mid.X+k1*deltaX1, mid.Y+k1, mid.Z+k1*deltaZ1); //MID TO PREV Vector ponto2 = new Vector(mid.X+k2*deltaX2, mid.Y+k2, mid.Z+k2*deltaZ2); //MID TO NEXT if (prev.Y - mid.Y == k1) { k1 = 0; deltaX1 = GetDelta(end.X, prev.X, end.Y, prev.Y); deltaZ1 = GetDelta(end.Z, prev.Z, end.Y, prev.Y); } if (next.Y - mid.Y == k2) { k2 = 0; deltaX2 = GetDelta(end.X, next.X, end.Y, next.Y); deltaZ2 = GetDelta(end.Z, next.Z, end.Y, next.Y); } double a = ponto1.X; double b = ponto2.X; Console.Write("Ponto1 "); Console.WriteLine(a); Console.Write("Ponto2 "); Console.WriteLine(b); Console.Write("Distancia "); double distancia = a - b; Console.WriteLine(distancia); for (int j = (int)(ponto1.X - ponto2.X); j >= 0; j--) { Vector pontoCur = new Vector(ponto2.X+j, mid.Y+w, ((ponto1.Z - ponto2.Z)/(ponto1.X - ponto2.X)) * j + ponto2.Z); var g = Graphics.FromImage(pc.Image); g.SmoothingMode = SmoothingMode.AntiAlias; g.FillRectangle(new SolidBrush(Color.FromArgb(j,0,0)), (int)pontoCur.X, (int)pontoCur.Y, 1, 1); } k1++; k2++; } } } break; case 2 : //Left view MapToScreen(2); break; case 3 : //Perspective MapToScreen(3); break; } }
public void FlatShading(Solid solid, PictureBox pc) { Vector iT; Vector iA; Vector iD; Vector iS; Vector R; Vector S; Vector Pm; for (int i = 0; i < 6; i++) { iA = new Vector(); iA.X = iLa.X * solid.Ka.X; iA.Y = iLa.Y * solid.Ka.Y; iA.Z = iLa.Z * solid.Ka.Z; if (solid.VisibleFaces[i] == false) { solid.FlatColor[i] = null; continue; } iD = new Vector(0, 0, 0); iS = new Vector(0, 0, 0); Vector N = solid.NormalFaces[i]; Pm = new Vector(); Pm.X = (solid.Points[0, solid.Faces[i, 0]] + solid.Points[0, solid.Faces[i, 2]]) / 2; Pm.Y = (solid.Points[1, solid.Faces[i, 0]] + solid.Points[1, solid.Faces[i, 2]]) / 2; Pm.Z = (solid.Points[2, solid.Faces[i, 0]] + solid.Points[2, solid.Faces[i, 2]]) / 2; L = new Vector(L.X - Pm.X, L.Y - Pm.Y, L.Z - Pm.Z); L = MathOperations.NormalizeVector(L); double value = MathOperations.DotProduct(N, L); if (value > 0) { iD.X = iL.X * solid.Kd.X * value; iD.Y = iL.Y * solid.Kd.Y * value; iD.Z = iL.Z * solid.Kd.Z * value; R = new Vector(); R.X = (2 * value * N.X) - L.X; R.Y = (2 * value * N.Y) - L.Y; R.Z = (2 * value * N.Z) - L.Z; S = new Vector(); S.X = VRP.X - Pm.X; S.Y = VRP.Y - Pm.Y; S.Z = VRP.Z - Pm.Z; S = MathOperations.NormalizeVector(S); double value2 = Math.Pow(MathOperations.DotProduct(R, S), solid.N); iS.X = iL.X * solid.Ks.X * value2; iS.Y = iL.Y * solid.Ks.Y * value2; iS.Z = iL.Z * solid.Ks.Z * value2; } iT = new Vector(); iT.X = iA.X + iD.X + iS.X; iT.Y = iA.Y + iD.Y + iS.Y; iT.Z = iA.Z + iD.Z + iS.Z; solid.FlatColor[i] = new Vector(iT.X, iT.Y, iT.Z); } }
private void IsometricTransformation() { //Coordenadas de tela perspectiveSolidList = solidsList.Clone(); Vector bigN = new Vector(); bigN.X = VRPiso.X; bigN.Y = VRPiso.Y; bigN.Z = VRPiso.Z; Vector n = MathOperations.NormalizeVector(bigN); Vector Y = new Vector(0, 1, 0); Vector n1 = new Vector(); double aux = MathOperations.DotProduct(Y, n); n1.X = aux * n.X; n1.Y = aux * n.Y; n1.Z = aux * n.Z; Vector v = new Vector(Y.X - n1.X, Y.Y - n1.Y, Y.Z - n1.Z); v = MathOperations.NormalizeVector(v); Vector u = new Vector(); u = MathOperations.CrossProduct(v, n); double[,] M = new double[,] { {u.X, u.Y, u.Z, -1*MathOperations.DotProduct(VRPiso, u)}, {v.X, v.Y, v.Z, -1*MathOperations.DotProduct(VRPiso, v)}, {n.X, n.Y, n.Z, -1*MathOperations.DotProduct(VRPiso, n)}, {0,0,0,1} }; foreach (var solid in perspectiveSolidList.SelectMany(t => t)) { solid.Points = MathOperations.MatrixMultiplication(M, solid.Points); } }