Пример #1
0
        public Sfera(float radius, uint subdivisions, Vec4 color)
        {
            Mesh        ico20 = BuildIcosahedron(radius, color);
            Queue <Tri> tris  = new Queue <Tri>();

            foreach (var item in ico20)
            {
                tris.Enqueue(item);
            }

            uint j = 0;

            while (subdivisions > j)
            {
                for (int i = 0; i < 20 * Math.Pow(4, j); i++)
                {
                    Tri         t     = tris.Dequeue();
                    Wierzcholek newV0 = ComputeHalfVertex(t.W0, t.W1, radius);
                    Wierzcholek newV1 = ComputeHalfVertex(t.W1, t.W2, radius);
                    Wierzcholek newV2 = ComputeHalfVertex(t.W2, t.W0, radius);

                    tris.Enqueue(new Tri(t.W0, newV0, newV2, t.KS, t.KD, t.N));
                    tris.Enqueue(new Tri(t.W1, newV1, newV0, t.KS, t.KD, t.N));
                    tris.Enqueue(new Tri(t.W2, newV2, newV1, t.KS, t.KD, t.N));
                    tris.Enqueue(new Tri(newV0, newV1, newV2, t.KS, t.KD, t.N));
                }
                j++;
            }
            foreach (var item in tris)
            {
                Trojkaty.Add(item);
            }
        }
Пример #2
0
 public Tri(Tri t)
 {
     W0 = t.W0;
     W1 = t.W1;
     W2 = t.W2;
     KS = t.KS;
     KD = t.KD;
     N  = t.N;
 }
        private void RysujTrojkat(Tri triangle, PrimitiveType primitiveType)
        {
            if (primitiveType == PrimitiveType.Triangles)
            {
                void uzupelnijdol(Wierzcholek v1, Wierzcholek v2, Wierzcholek v3)
                {
                    float invslope1 = (v2.Position.X - v1.Position.X) / (v2.Position.Y - v1.Position.Y);
                    float invslope2 = (v3.Position.X - v1.Position.X) / (v3.Position.Y - v1.Position.Y);

                    float curx1 = v1.Position.X;
                    float curx2 = v1.Position.X;

                    for (int scanlineY = (int)v1.Position.Y; scanlineY <= v2.Position.Y; scanlineY++)
                    {
                        float z1   = v1.Position.Z + ((float)(scanlineY - v1.Position.Y) / (float)(v2.Position.Y - v1.Position.Y)) * (v2.Position.Z - v1.Position.Z);
                        float z2   = v1.Position.Z + ((float)(scanlineY - v1.Position.Y) / (float)(v3.Position.Y - v1.Position.Y)) * (v3.Position.Z - v1.Position.Z);
                        Vec4  c1   = v1.Color + ((float)(scanlineY - v1.Position.Y) / (float)(v2.Position.Y - v1.Position.Y)) * (v2.Color - v1.Color);
                        Vec4  c2   = v1.Color + ((float)(scanlineY - v1.Position.Y) / (float)(v3.Position.Y - v1.Position.Y)) * (v3.Color - v1.Color);
                        Vec3  from = new Vec3((float)Math.Round(curx1), scanlineY, z1);
                        Vec3  to   = new Vec3((float)Math.Round(curx2), scanlineY, z2);
                        UstawLinie(from.X, from.Z, c1, to.X, to.Z, c2, scanlineY);
                        curx1 += invslope1;
                        curx2 += invslope2;
                    }
                }

                void uzupelnijgore(Wierzcholek v1, Wierzcholek v2, Wierzcholek v3)
                {
                    float invslope1 = (v3.Position.X - v1.Position.X) / (v3.Position.Y - v1.Position.Y);
                    float invslope2 = (v3.Position.X - v2.Position.X) / (v3.Position.Y - v2.Position.Y);

                    float curx1 = v3.Position.X;
                    float curx2 = v3.Position.X;

                    for (int scanlineY = (int)v3.Position.Y; scanlineY > v1.Position.Y; scanlineY--)
                    {
                        float z1   = v3.Position.Z + ((float)(scanlineY - v3.Position.Y) / (float)(v1.Position.Y - v3.Position.Y)) * (v1.Position.Z - v3.Position.Z);
                        float z2   = v3.Position.Z + ((float)(scanlineY - v3.Position.Y) / (float)(v2.Position.Y - v3.Position.Y)) * (v2.Position.Z - v3.Position.Z);
                        Vec3  from = new Vec3((float)Math.Round(curx1), scanlineY, z1);
                        Vec3  to   = new Vec3((float)Math.Round(curx2), scanlineY, z2);
                        Vec4  c1   = v3.Color + ((float)(scanlineY - v3.Position.Y) / (float)(v1.Position.Y - v3.Position.Y)) * (v1.Color - v3.Color);
                        Vec4  c2   = v3.Color + ((float)(scanlineY - v3.Position.Y) / (float)(v2.Position.Y - v3.Position.Y)) * (v2.Color - v3.Color);
                        UstawLinie(from.X, from.Z, c1, to.X, to.Z, c2, scanlineY);
                        curx1 -= invslope1;
                        curx2 -= invslope2;
                    }
                }

                List <Wierzcholek> sortedVecs = new List <Wierzcholek>
                {
                    triangle[0],
                    triangle[1],
                    triangle[2],
                };
                sortedVecs = sortedVecs.OrderBy(i => i.Position.Y).ToList();
                Wierzcholek A = sortedVecs[0];
                Wierzcholek B = sortedVecs[1];
                Wierzcholek C = sortedVecs[2];
                A.Position = new Vec3((int)A.Position.X, (int)A.Position.Y, A.Position.Z);
                B.Position = new Vec3((int)B.Position.X, (int)B.Position.Y, B.Position.Z);
                C.Position = new Vec3((int)C.Position.X, (int)C.Position.Y, C.Position.Z);

                if (B.Position.Y == C.Position.Y)
                {
                    uzupelnijdol(A, B, C);
                }
                else if (A.Position.Y == B.Position.Y)
                {
                    uzupelnijgore(A, B, C);
                }
                else
                {
                    float z  = A.Position.Z + ((float)(B.Position.Y - A.Position.Y) / (float)(C.Position.Y - A.Position.Y)) * (C.Position.Z - A.Position.Z);
                    Vec4  c  = A.Color + ((float)(B.Position.Y - A.Position.Y) / (float)(C.Position.Y - A.Position.Y)) * (C.Color - A.Color);
                    Vec3  v4 = new Vec3(
                        (int)(A.Position.X + ((float)(B.Position.Y - A.Position.Y) / (float)(C.Position.Y - A.Position.Y)) * (C.Position.X - A.Position.X)),
                        B.Position.Y,
                        z
                        );
                    Wierzcholek v = new Wierzcholek(v4, c);

                    uzupelnijdol(A, B, v);
                    uzupelnijgore(B, v, C);
                }
            }
        }
        private List <Tri> Clipowanie(Vec3 planePoint, Vec3 planeNormal, Tri tri)
        {
            planeNormal = planeNormal.Normal();

            float dist(Vec3 point)
            {
                return(planeNormal.Dot(point) - planeNormal.Dot(planePoint));
            }

            Wierzcholek[] insidePoints = new Wierzcholek[3]; int nInsidePointCount = 0;
            Wierzcholek[] outsidePoints = new Wierzcholek[3]; int nOutsidePointCount = 0;

            float d0 = dist(tri[0].Position);
            float d1 = dist(tri[1].Position);
            float d2 = dist(tri[2].Position);

            if (d0 >= 0)
            {
                insidePoints[nInsidePointCount++] = tri[0];
            }
            else
            {
                outsidePoints[nOutsidePointCount++] = tri[0];
            }
            if (d1 >= 0)
            {
                insidePoints[nInsidePointCount++] = tri[1];
            }
            else
            {
                outsidePoints[nOutsidePointCount++] = tri[1];
            }
            if (d2 >= 0)
            {
                insidePoints[nInsidePointCount++] = tri[2];
            }
            else
            {
                outsidePoints[nOutsidePointCount++] = tri[2];
            }

            if (nInsidePointCount == 0)
            {
                return(new List <Tri>());
            }
            if (nInsidePointCount == 1 && nOutsidePointCount == 2)
            {
                Wierzcholek v0 = insidePoints[0];
                Wierzcholek v1 = Linia(planePoint, planeNormal, v0, outsidePoints[0]);
                Wierzcholek v2 = Linia(planePoint, planeNormal, v0, outsidePoints[1]);

                Tri t = new Tri(tri)
                {
                    W0 = v0, W1 = v1, W2 = v2
                };
                if (tri.NormalVector.Z * t.NormalVector.Z < 0)
                {
                    Wierzcholek tmp = t[1];
                    t[1] = t[2];
                    t[2] = tmp;
                }
                return(new List <Tri>
                {
                    t,
                });
            }
            if (nInsidePointCount == 2 && nOutsidePointCount == 1)
            {
                Wierzcholek v00 = insidePoints[0];
                Wierzcholek v01 = insidePoints[1];
                Wierzcholek v02 = Linia(planePoint, planeNormal, v00, outsidePoints[0]);

                Wierzcholek v10 = insidePoints[1];
                Wierzcholek v11 = v02;
                Wierzcholek v12 = Linia(planePoint, planeNormal, v10, outsidePoints[0]);

                Tri t1 = new Tri(tri)
                {
                    W0 = v00, W1 = v01, W2 = v02
                };
                Tri t2 = new Tri(tri)
                {
                    W0 = v10, W1 = v11, W2 = v12
                };
                if (tri.NormalVector.Z * t1.NormalVector.Z < 0)
                {
                    Wierzcholek tmp = t1[1];
                    t1[1] = t1[2];
                    t1[2] = tmp;
                }
                if (tri.NormalVector.Z * t2.NormalVector.Z < 0)
                {
                    Wierzcholek tmp = t2[1];
                    t2[1] = t2[2];
                    t2[2] = tmp;
                }
                return(new List <Tri>
                {
                    t1,
                    t2,
                });
            }
            if (nInsidePointCount == 3)
            {
                return(new List <Tri>
                {
                    tri,
                });
            }
            return(new List <Tri>());
        }
        //rysowanie trojkatow skierowanych do mnie z cieniem i przycieciem
        public void RenderowanieSceny(Scena scene, RenderTarget target, RenderStates states)
        {
            uint width  = target.Size.X;
            uint height = target.Size.Y;

            Buffer = new float[width, height];
            Bitmap = new Color[width, height];

            Transformacja cameraInvMatrixAndWorld = scene.mainCamera.InverseTransform * scene.worldTransform;
            Transformacja matView = Transformacja.Identity.Translate(new Vec3(1, 1, 0)).Scale(new Vec3(width / 2, height / 2, 1));

            float fAspectRatio = height / (float)width;
            float fFovRad      = 1.0f / (float)Math.Tan(scene.mainCamera.Fov * 0.5f / 180.0f * Math.PI);

            float[,] m = new float[4, 4];
            m[0, 0]    = fAspectRatio * fFovRad;
            m[1, 1]    = fFovRad;
            m[2, 2]    = scene.mainCamera.Daleko / (scene.mainCamera.Daleko - scene.mainCamera.Blisko);
            m[3, 2]    = (-scene.mainCamera.Daleko * scene.mainCamera.Blisko) / (scene.mainCamera.Daleko - scene.mainCamera.Blisko);
            m[2, 3]    = 1.0f;
            m[3, 3]    = 0.0f;
            Transformacja matProj = new Transformacja(m);

            Transformacja matProjAndView = matView * matProj;

            Queue <Tri> sceneTriangles = new Queue <Tri>();

            foreach (Rysowalne drawable in scene.drawables)
            {
                Mesh mesh = drawable.GetMesh();
                foreach (Tri tri in mesh)
                {
                    sceneTriangles.Enqueue(mesh.Transform * tri);
                }
            }
            int c = sceneTriangles.Count;

            for (int i = 0; i < c; i++)
            {
                Tri t = sceneTriangles.Dequeue();
                sceneTriangles.Enqueue(cameraInvMatrixAndWorld * t);
            }
            for (int i = 0; i < c; i++)
            {
                Tri        t   = sceneTriangles.Dequeue();
                List <Tri> clt = Clipowanie(new Vec3(0, 0, scene.mainCamera.Blisko), new Vec3(0, 0, 1), t);
                foreach (var clippedTriangle in clt)
                {
                    sceneTriangles.Enqueue(clippedTriangle);
                }
            }
            c = sceneTriangles.Count;
            for (int i = 0; i < c; i++)
            {
                Tri t = sceneTriangles.Dequeue();
                if (t.NormalVector.Dot(t[0].Position) < 0)
                {
                    sceneTriangles.Enqueue(t);
                }
            }
            c = sceneTriangles.Count;
            for (int i = 0; i < c; i++)
            {
                Tri     t  = sceneTriangles.Dequeue();
                float[] Is = new float[3] {
                    0, 0, 0
                };
                Vec3  N  = t.NormalVector;
                float kd = t.KD;
                float ks = t.KS;
                float n  = t.N;
                foreach (ZrodloSwiatla lsrc in scene.Lampy)
                {
                    Vec3 lightPos = cameraInvMatrixAndWorld * lsrc.Position;
                    for (int j = 0; j < 3; j++)
                    {
                        Vec3  V     = (-t[j].Position).Normal();
                        Vec3  L     = (lightPos - t[j].Position).Normal();
                        Vec3  R     = (-L - 2 * N.Dot(-L) * N).Normal();
                        float minus = (V.Dot(R) < 0) ? -1 : 1;
                        float I     = lsrc.Intensywnosc * (kd * N.Dot(L) + ks * minus * (float)Math.Pow(V.Dot(R), n));
                        Math.Max(I, 0);
                        Is[j] += I;
                    }
                }
                for (int j = 0; j < 3; j++)
                {
                    Is[j] = Math.Max(Is[j], 0.2f);
                }
                Vec4 color0 = new Vec4(t[0].Color.R * Is[0], t[0].Color.G * Is[0], t[0].Color.B * Is[0], t[0].Color.A);
                Vec4 color1 = new Vec4(t[1].Color.R * Is[1], t[1].Color.G * Is[1], t[1].Color.B * Is[1], t[1].Color.A);
                Vec4 color2 = new Vec4(t[2].Color.R * Is[2], t[2].Color.G * Is[2], t[2].Color.B * Is[2], t[2].Color.A);

                Wierzcholek vert0 = new Wierzcholek(t[0].Position, color0);
                Wierzcholek vert1 = new Wierzcholek(t[1].Position, color1);
                Wierzcholek vert2 = new Wierzcholek(t[2].Position, color2);
                sceneTriangles.Enqueue(new Tri(vert0, vert1, vert2, t.KS, t.KD, t.N));
            }
            for (int i = 0; i < c; i++)
            {
                Tri t = sceneTriangles.Dequeue();
                sceneTriangles.Enqueue(matProjAndView * t);
            }
            for (int i = 0; i < c; i++)
            {
                Tri         t     = sceneTriangles.Dequeue();
                Queue <Tri> qTris = new Queue <Tri>();
                qTris.Enqueue(t);
                int nNewTriangles = 1;

                for (int p = 0; p < 4; p++)
                {
                    while (nNewTriangles > 0)
                    {
                        Tri t2 = qTris.Dequeue();
                        nNewTriangles--;

                        List <Tri> clippedTriangles = new List <Tri>();
                        switch (p)
                        {
                        case 0:
                            clippedTriangles = Clipowanie(new Vec3(), new Vec3(0, 1, 0), t2);
                            break;

                        case 1:
                            clippedTriangles = Clipowanie(new Vec3(0, height - 1, 0), new Vec3(0, -1, 0), t2);
                            break;

                        case 2:
                            clippedTriangles = Clipowanie(new Vec3(), new Vec3(1, 0, 0), t2);
                            break;

                        case 3:
                            clippedTriangles = Clipowanie(new Vec3(width - 1, 0, 0), new Vec3(-1, 0, 0), t2);
                            break;
                        }
                        foreach (var item in clippedTriangles)
                        {
                            qTris.Enqueue(item);
                        }
                    }
                    nNewTriangles = qTris.Count;
                }
                foreach (var item in qTris)
                {
                    sceneTriangles.Enqueue(item);
                }
            }
            while (sceneTriangles.Count > 0)
            {
                Tri t = sceneTriangles.Dequeue();
                RysujTrojkat(t, PrimitiveType.Triangles);
            }
            foreach (ZrodloSwiatla light in scene.Lampy)
            {
                Vec3 lpos = cameraInvMatrixAndWorld * light.Position;
                if (lpos.Z > 0)
                {
                    Vec3 lPosOnScreen = matProjAndView * lpos;
                    UstawPixel(lPosOnScreen, (Vec4)Color.White);
                    UstawPixel(lPosOnScreen + new Vec3(0, 1), (Vec4)Color.White);
                    UstawPixel(lPosOnScreen + new Vec3(1, 0), (Vec4)Color.White);
                    UstawPixel(lPosOnScreen + new Vec3(1, 1), (Vec4)Color.White);
                }
            }
            Image   img     = new Image(Bitmap);
            Texture texture = new Texture(img);
            Sprite  s       = new Sprite(texture);

            target.Draw(s, states);
            s.Dispose();
            texture.Dispose();
            img.Dispose();
        }