コード例 #1
0
        public void Render()
        {
            zTable = new double[DBitmap.Width, DBitmap.Height];
            var surf = new SurfaceInfo {
                Ka = Ka, Kd = Kd, Ks = Ks, N_shiny = N_shiny
            };

            ResetZTable();
            var pMatrix = ProjectionMatrix;
            var vMatrix = SelectedCamera.ViewMatrix;

            foreach (var light in Lights)
            {
                light.Process(vMatrix);
            }
            foreach (var shape in Shapes)
            {
                shape.IsRender = true;
                var mMatrix  = shape.ModelMatrix;
                var vmMatrix = vMatrix.Multiply(mMatrix);
                foreach (var side in shape.SideTriangles)
                {
                    side.Process(vmMatrix);
                    var v = side.Position;
                    var n = side.Normal;
                    if (side.Points[0].Z > 0 && side.Points[1].Z > 0 && side.Points[2].Z > 0)
                    {
                        continue;
                    }
                    if (n[0] * v[0] + n[1] * v[1] + n[2] * v[2] <= 0)
                    {
                        side.DrawSide(DBitmap, pMatrix, DBitmap.Width / 2, zTable, surf, Lights, ShadingMode);
                    }
                }
                shape.IsRender = false;
            }
        }
コード例 #2
0
        public static Color PhongeIllumination(Vector <double> position, Vector <double> normal,
                                               ColorInfo colorInfo, SurfaceInfo surface, List <Light> lights)
        {
            ColorInfo outcome = new ColorInfo {
                R = 0, G = 0, B = 0
            };


            //ambient
            outcome.R += colorInfo.R * surface.Ka;
            outcome.G += colorInfo.G * surface.Ka;
            outcome.B += colorInfo.B * surface.Ka;

            foreach (var light in lights)
            {
                if (!light.IsOn)
                {
                    continue;
                }
                double spotlightFactor = 1;

                var l = light.CalculateLVector(position);

                if (light.IsSpotLight)
                {
                    var cos = (-light.ProcessedDirection).DotProduct(l);
                    if (cos > 0)
                    {
                        spotlightFactor = Math.Pow(cos, light.P);
                    }
                    else
                    {
                        spotlightFactor = 0;
                    }
                }
                //diffuse

                var lightNormalAngle = normal.DotProduct(l);
                var diffuseR         = surface.Kd * lightNormalAngle * spotlightFactor;
                if (lightNormalAngle < 0)
                {
                    continue;
                }

                outcome.R += colorInfo.R * diffuseR;
                outcome.G += colorInfo.G * diffuseR;
                outcome.B += colorInfo.B * diffuseR;


                //sepcular
                var v = (-position).Normalize(2);

                var r = 2 * lightNormalAngle * normal - l;
                r = r.Normalize(2);

                var cameraRAngle = r.DotProduct(v);
                if (cameraRAngle < 0)
                {
                    continue;
                }

                var specularR = surface.Ks * Math.Pow(cameraRAngle, surface.N_shiny) * spotlightFactor;

                outcome.R += specularR;
                outcome.G += specularR;
                outcome.B += specularR;
            }

            if (outcome.R > 1)
            {
                outcome.R = 1;
            }
            if (outcome.G > 1)
            {
                outcome.G = 1;
            }
            if (outcome.B > 1)
            {
                outcome.B = 1;
            }

            return(ColorInfo2Color(outcome));
        }
コード例 #3
0
        public static void Fill(DirectBitmap bitmap, List <Point> points, Color color, List <double> zs, double[,] Ztable,
                                List <Vector <double> > positions, List <Vector <double> > normals, SurfaceInfo surface, List <Light> lights, ShadingMode shadingMode = ShadingMode.Flat)
        {
            int margin = 500;
            var maxY   = points.Max(x => x.Y);

            if (maxY < -margin || maxY > bitmap.Height + margin)
            {
                return;
            }

            var minY = points.Min(x => x.Y);

            if (minY < -margin || minY > bitmap.Height + margin)
            {
                return;
            }

            var maxX = points.Max(x => x.X);

            if (maxX < -margin || maxX > bitmap.Width + margin)
            {
                return;
            }

            var minX = points.Min(x => x.X);

            if (minX < -margin || minX > bitmap.Width + margin)
            {
                return;
            }

            var etTable = new List <EdgeStruct> [maxY - minY + 1];

            var area = GetAreaInv(points[0], points[1], points[2]);

            for (int i = 0; i < points.Count; i++)
            {
                var p1 = points[i];
                var p2 = points[i + 1 == points.Count ? 0 : i + 1];
                if (p1.Y == p2.Y)
                {
                    continue;
                }
                if (p1.Y > p2.Y)
                {
                    var tmp = p2;
                    p2 = p1;
                    p1 = tmp;
                }
                //double slp;
                var str = new EdgeStruct {
                    YMax = p2.Y, X = p1.Y < p2.Y ? p1.X : p2.X, Slope = (double)(p1.X - p2.X) / (p1.Y - p2.Y)
                };
                if (etTable[p1.Y - minY] == null)
                {
                    etTable[p1.Y - minY] = new List <EdgeStruct>();
                }
                etTable[p1.Y - minY].Add(str);
            }

            var aetTable = new List <EdgeStruct>();
            int y        = minY;

            Color shadingCol = color;

            if (shadingMode == ShadingMode.Flat)
            {
                var middle     = positions[0].Add(positions[1]).Add(positions[2]).Multiply(1.0 / 3);
                var sideNormal = normals[0].Add(normals[1]).Add(normals[2]).Normalize(2);
                shadingCol = PhongeIllumination(middle, sideNormal, Color2ColorInfo(color), surface, lights);
            }

            var firstColor  = Color.Blue;
            var secondColor = Color.Red;
            var thirdColor  = Color.Green;

            if (shadingMode == ShadingMode.Gouraud)
            {
                firstColor  = PhongeIllumination(positions[0], normals[0], Color2ColorInfo(color), surface, lights);
                secondColor = PhongeIllumination(positions[1], normals[1], Color2ColorInfo(color), surface, lights);
                thirdColor  = PhongeIllumination(positions[2], normals[2], Color2ColorInfo(color), surface, lights);
            }

            while (y <= maxY)
            {
                if (etTable[y - minY] != null)
                {
                    var tempList = etTable[y - minY];
                    //foreach (var edge in tempList)
                    //{
                    //    //if(edge.Slope < 0)
                    //        edge.X = edge.X - (edge.YMax - y) * edge.Slope;
                    //}

                    aetTable.AddRange(tempList);
                }

                aetTable = aetTable.OrderBy(x => x.X).ToList();
                for (int i = 0; i < aetTable.Count; i += 2)
                {
                    if (aetTable.Count - i == 1)
                    {
                        continue;
                    }
                    var first  = aetTable[i];
                    var second = aetTable[i + 1];

                    for (int j = (int)(first.X); j < second.X; j++)
                    {
                        if (!(j >= 0 && j < bitmap.Width && y >= 0 && y < bitmap.Height))
                        {
                            continue;
                        }

                        var w = GetBaricentricRatio(j, y, points[0], points[1], points[2], area);

                        if (w.Item1 < 0 || w.Item2 < 0 || w.Item3 < 0)
                        {
                            continue;
                        }

                        var z = zs[0] * w.Item1 + zs[1] * w.Item2 + zs[2] * w.Item3;

                        if (z < Ztable[j, y])
                        {
                            Ztable[j, y] = z;

                            if (shadingMode == ShadingMode.Gouraud)
                            {
                                var gR = firstColor.R * w.Item1 + secondColor.R * w.Item2 + thirdColor.R * w.Item3;
                                var gG = firstColor.G * w.Item1 + secondColor.G * w.Item2 + thirdColor.G * w.Item3;
                                var gB = firstColor.B * w.Item1 + secondColor.B * w.Item2 + thirdColor.B * w.Item3;

                                shadingCol = Color.FromArgb((int)gR, (int)gG, (int)gB);
                            }

                            if (shadingMode == ShadingMode.Phong)
                            {
                                var normal = normals[0] * w.Item1 + normals[1] * w.Item2 + normals[2] * w.Item3;
                                normal = normal.Normalize(2);
                                var position = positions[0] * w.Item1 + positions[1] * w.Item2 + positions[2] * w.Item3;
                                shadingCol = PhongeIllumination(position, normal, Color2ColorInfo(color), surface, lights);
                            }

                            bitmap.SetPixel(j, y, shadingCol);
                        }
                    }
                }
                foreach (var edge in aetTable.ToList())
                {
                    if (edge.YMax == y + 1)
                    {
                        aetTable.Remove(edge);
                    }
                    else
                    {
                        edge.X += edge.Slope;
                    }
                }
                y++;
            }
        }
コード例 #4
0
        public void DrawSide(DirectBitmap bitmap, Matrix <double> projectionMatrix, int radius, double [,] zTable, SurfaceInfo surface, List <Light> lights, ShadingMode shadingMode)
        {
            var pos   = GetPositions();
            var norms = GetNormals();

            Process(projectionMatrix, false);
            var convPoints = new List <Point>();
            var zPoints    = new List <double>();



            foreach (var point in Points)
            {
                convPoints.Add(new Point((int)((point.X + 1) * radius), (int)((point.Y + 1) * radius)));

                zPoints.Add(point.Z);
            }

            var sMode = shadingMode;

            if (IsGlowing)
            {
                sMode = ShadingMode.None;
            }

            Helpers.Fill(bitmap, convPoints, paintColor, zPoints, zTable, pos, norms, surface, lights, sMode);;
        }