コード例 #1
0
ファイル: AIMesh.cs プロジェクト: horato/IntWarsSharp
        void fillScanLine(Vertex vertex1, Vertex vertex2)
        {
            // Fills a scanline structure with information about the triangle on this y scanline.

            if (vertex1.y > vertex2.y)
            {
                fillScanLine(vertex2, vertex1);
                return;
            }
            // We need to go from low to high so switch if the other one is higher

            if (vertex2.y < 0 || vertex1.y >= AIMESH_TEXTURE_SIZE)
                return;
            // There's nothing on this line

            var deltaPos = new Vertex();

            deltaPos.x = vertex2.x - vertex1.x;
            deltaPos.y = vertex2.y - vertex1.y;
            deltaPos.z = vertex2.z - vertex1.z;

            float tempWidth = AIMESH_TEXTURE_SIZE;
            float tempHeight = AIMESH_TEXTURE_SIZE;

            float t_DYResp = deltaPos.y == 0 ? 0 : 1.0f / deltaPos.y;
            int startY = (int)vertex1.y, endY = (int)vertex2.y;

            float x = vertex1.x;
            float z = vertex1.z;

            float deltaX = deltaPos.x * t_DYResp;
            float deltaZ = deltaPos.z * t_DYResp;

            float t_Inc = 1.0f - FRACPOS(vertex1.y);

            // subpixel correction
            startY++;
            x += deltaX * t_Inc;
            z += deltaZ * t_Inc;

            if (startY < 0)
            {
                x -= deltaX * startY;
                z -= deltaZ * startY;
                startY = 0;
            }

            // Small fix
            if (endY >= AIMESH_TEXTURE_SIZE) endY = AIMESH_TEXTURE_SIZE - 1;

            // For each scanline that this triangle uses
            for (int y = startY; y <= endY; y++)
            {
                if (x < scanlineLowest[y].x) // If the x is lower than our lowest x
                {
                    scanlineLowest[y].x = (x); // Fill the scanline struct with our info
                    scanlineLowest[y].y = (float)y;
                    scanlineLowest[y].z = z;
                }
                if (x > scanlineHighest[y].x) // If the x is higher than our highest x
                {
                    scanlineHighest[y].x = (x); // Fill the scanline struct with our info
                    scanlineHighest[y].y = (float)y;
                    scanlineHighest[y].z = z;
                }

                // Interpolate
                // Or going to the part of the triangle on the next scanline
                x += deltaX;
                z += deltaZ;
            }
        }
コード例 #2
0
ファイル: AIMesh.cs プロジェクト: horato/IntWarsSharp
        void drawTriangle(Triangle triangle, int width, int height)
        {
            // The heart of the rasterizer

            Vertex[] tempVertex = new Vertex[3];

            tempVertex[0] = new Vertex();
            tempVertex[0].x = triangle.Face.v1[0];
            tempVertex[0].y = triangle.Face.v1[2];
            tempVertex[0].z = triangle.Face.v1[1];

            tempVertex[1] = new Vertex();
            tempVertex[1].x = triangle.Face.v2[0];
            tempVertex[1].y = triangle.Face.v2[2];
            tempVertex[1].z = triangle.Face.v2[1];

            tempVertex[2] = new Vertex();
            tempVertex[2].x = triangle.Face.v3[0];
            tempVertex[2].y = triangle.Face.v3[2];
            tempVertex[2].z = triangle.Face.v3[1];

            fillScanLine(tempVertex[0], tempVertex[1]);
            fillScanLine(tempVertex[1], tempVertex[2]);
            fillScanLine(tempVertex[2], tempVertex[0]);

            float tempWidth = width;
            float tempHeight = height;
            // target width and width

            int startY = (int)Math.Min(tempVertex[0].y, Math.Min(tempVertex[1].y, tempVertex[2].y));
            int endY = (int)Math.Max(tempVertex[0].y, Math.Max(tempVertex[1].y, tempVertex[2].y));
            // Get the scanline where we start drawing and where we stop.

            endY = Math.Min(endY, height - 1);
            startY = Math.Max(0, startY);

            for (int y = startY; y <= endY; y++) // for each scanline
            {
                if (scanlineLowest[y].x < scanlineHighest[y].x) // If we actually have something filled in this scanline
                {
                    int yw = y * height;

                    float z = scanlineLowest[y].z;
                    float u = scanlineLowest[y].u;
                    float v = scanlineLowest[y].v;
                    // The start of the Z, U, and V coordinate.

                    float deltaX = 1.0f / (scanlineHighest[y].x - scanlineLowest[y].x);
                    // Interpolation over X (change in X between the two, then reverse it so it's usable as multiplication
                    // in divisions

                    float deltaZ = (scanlineHighest[y].z - scanlineLowest[y].z) * deltaX;
                    float deltaU = (scanlineHighest[y].u - scanlineLowest[y].u) * deltaX;
                    float deltaV = (scanlineHighest[y].v - scanlineLowest[y].v) * deltaX;
                    // The interpolation in Z, U and V in respect to the interpolation of X	

                    // Sub-texel correction
                    int x = (int)scanlineLowest[y].x;
                    int tx = x + 1;
                    int distInt = (int)(scanlineHighest[y].x) - (int)(scanlineLowest[y].x);
                    if (distInt > 0.0f)
                    {
                        u += (((float)(tx)) - tx) * deltaU;
                        v += (((float)(tx)) - tx) * deltaV;
                        z += (((float)(tx)) - tx) * deltaZ;
                    }

                    if (!(scanlineHighest[y].x < 0 || x >= height))
                        for (int i = 0; x < (int)scanlineHighest[y].x; i++, x++) // for each piece of the scanline
                        {
                            if (x >= height) break; // If we're out of screen, break out this loop

                            if (x < 0)
                            {
                                int inverseX = Math.Abs(x);
                                z += deltaZ * inverseX;
                                u += deltaU * inverseX;
                                v += deltaV * inverseX;
                                x = 0;
                            }


                            {
                                // Get the point on the texture that we need to draw. It basically picks a pixel based on the uv.

                                //a_Target->GetRenderTarget()->Plot(x, tempHeight - y, 255);
                                heightMap[x + (y) * height] = z;
                                xMap[x + (y) * height] = scanlineLowest[y].x + deltaX * i;
                                yMap[x + (y) * height] = scanlineLowest[y].y;
                                if (z < lowestZ) lowestZ = z;
                            }

                            z += deltaZ;
                            u += deltaU;
                            v += deltaV;
                            // interpolate
                        }
                }

                scanlineLowest[y].x = 1e10f;
                scanlineHighest[y].x = -1e10f;
            }
        }