コード例 #1
0
        /// <summary>
        ///     Toma una curva de Quake 3 y la convierte a un TgcMesh, mediante el proceso de Tessellation
        /// </summary>
        private void tessellatePatch(BspMap bspMap, int surfaceId)
        {
            // los patch de quake 3 estan formados por curvas de bezier
            // todos los patch tienen 9 puntos que son los puntos de control para la curva
            // Esos puntos hay que tesselarlos para conseguir los triangulos

            var L = 5;

            var surface = bspMap.Data.drawSurfaces[surfaceId];
            var offVert = surface.firstVert;

            // coeficientes de bezier
            var B = new float[L + 1, 3];

            //Numero de patches de 3x3 en cada direccion
            var num1         = (surface.patchHeight - 1) / 2;
            var num2         = (surface.patchWidth - 1) / 2;
            var cantVertices = (L * num1 + 1) * (L * num2 + 1);
            var cantIndices  = 2 * (L * num2 + 2) * L * num1;

            //aloco el espacio para los vertices y los indices
            var vertices   = new Vector3[cantVertices];
            var normals    = new Vector3[cantVertices];
            var textCords  = new Vector2[cantVertices];
            var textCords2 = new Vector2[cantVertices];
            var indices    = new int[cantIndices];
            {
                //se cargan las constantes de bezier
                var   dt = 1.0f / L;
                float t  = 0;
                for (var i = 0; i < L + 1; i++)
                {
                    if (i == L)
                    {
                        t = 1.0f;
                    }
                    var mt = 1 - t;

                    B[i, 0] = mt * mt;
                    B[i, 1] = 2 * mt * t;
                    B[i, 2] = t * t;

                    t += dt;
                }
            }

            //Calculo de los bicubic bezier patch para cada strip
            var pointsXStrip = L * num2 + 1;
            var pointsXPatch = pointsXStrip * L;
            var indexCount   = 0;
            var vertexNum    = 0;
            var controls     = new int[3]; // subindices a los vertices de puntos de control

            // por cada patch
            for (int i = 0, Li = L; i < num1; i++)
            {
                if (i == num1 - 1)
                {
                    Li = L + 1;
                }

                // seteo los indices
                for (var j = 0; j < L; j++)
                {
                    for (var k = 0; k < pointsXStrip; k++)
                    {
                        indices[indexCount++] = i * pointsXPatch + j * pointsXStrip + k;
                        indices[indexCount++] = i * pointsXPatch + (j + 1) * pointsXStrip + k;
                    }

                    //repito primer y ultimo indice
                    indices[indexCount++] = i * pointsXPatch + (j + 2) * pointsXStrip - 1;
                    indices[indexCount++] = i * pointsXPatch + (j + 1) * pointsXStrip;
                }

                //Ahora van los puntos de control y los vertices
                for (int j = 0, Lj = L; j < num2; j++)
                {
                    if (j == num2 - 1)
                    {
                        Lj = L + 1;
                    }

                    // calculo de los puntos de control para este patch
                    // controls[fila] = indice del primer vertice de la fila de este patch

                    controls[0] = offVert + i * 2 * (2 * num2 + 1) + j * 2;
                    controls[1] = offVert + (i * 2 + 1) * (2 * num2 + 1) + j * 2;
                    controls[2] = offVert + (i * 2 + 2) * (2 * num2 + 1) + j * 2;

                    //por cada punto en el patch
                    for (var i2 = 0; i2 < Li; i2++)
                    {
                        vertexNum = i * pointsXPatch + i2 * pointsXStrip + j * L;

                        for (var j2 = 0; j2 < Lj; j2++, vertexNum++)
                        {
                            vertices[vertexNum]   = new Vector3();
                            normals[vertexNum]    = new Vector3();
                            textCords[vertexNum]  = new Vector2();
                            textCords2[vertexNum] = new Vector2();

                            for (var i3 = 0; i3 < 3; i3++)
                            {
                                for (var j3 = 0; j3 < 3; j3++)
                                {
                                    var blendFactor = B[i2, i3] * B[j2, j3];
                                    vertices[vertexNum]   += bspMap.Data.drawVerts[controls[i3] + j3].xyz * blendFactor;
                                    normals[vertexNum]    += bspMap.Data.drawVerts[controls[i3] + j3].normal * blendFactor;
                                    textCords[vertexNum]  += bspMap.Data.drawVerts[controls[i3] + j3].st * blendFactor;
                                    textCords2[vertexNum] += bspMap.Data.drawVerts[controls[i3] + j3].lightmap *
                                                             blendFactor;
                                }
                            }
                        }
                    }
                }
            }

            var indexBuffer  = new short[3 * cantIndices - 6];
            var cant_ibuffer = 0;

            for (var i = 2; i < cantIndices; i++)
            {
                if (i % 2 == 0)
                {
                    indexBuffer[cant_ibuffer++] = (short)indices[i - 2];
                    indexBuffer[cant_ibuffer++] = (short)indices[i - 1];
                    indexBuffer[cant_ibuffer++] = (short)indices[i];
                }
                else
                {
                    indexBuffer[cant_ibuffer++] = (short)indices[i];
                    indexBuffer[cant_ibuffer++] = (short)indices[i - 1];
                    indexBuffer[cant_ibuffer++] = (short)indices[i - 2];
                }
            }

            //Mesh de DirectX
            var mesh = new Mesh(indexBuffer.Length / 3, vertices.Length, MeshFlags.Managed,
                                TgcSceneLoader.DiffuseMapAndLightmapVertexElements, D3DDevice.Instance.Device);

            //Cargar vertexBuffer
            using (var vb = mesh.VertexBuffer)
            {
                var vertex =
                    new TgcSceneLoader.DiffuseMapAndLightmapVertex[vertices.Length];

                for (var i = 0; i < vertices.Length; i++)
                {
                    vertex[i] = new TgcSceneLoader.DiffuseMapAndLightmapVertex();

                    vertex[i].Position = vertices[i];
                    vertex[i].Normal   = normals[i];           //drawVerts[offVert].normal;
                    vertex[i].Tu0      = textCords[i].X;       //drawVerts[offVert].st.X;
                    vertex[i].Tv0      = textCords[i].Y;       //drawVerts[offVert].st.Y;
                    vertex[i].Tu1      = textCords2[i].X;      //drawVerts[offVert].lightmap.X;
                    vertex[i].Tv1      = textCords2[i].Y;      //drawVerts[offVert].lightmap.Y;
                    vertex[i].Color    = Color.White.ToArgb(); //drawVerts[i].color;

                    vb.SetData(vertex, 0, LockFlags.None);
                }
            }

            //IndexBuffer
            using (var ib = mesh.IndexBuffer)
            {
                ib.SetData(indexBuffer, 0, LockFlags.None);
            }

            //Crea el tgcMesh
            var tgcMesh = CreateTgcMesh(bspMap, mesh, surfaceId);

            bspMap.Meshes.Add(tgcMesh);
        }
コード例 #2
0
        /// <summary>
        ///     Carga todos los meshes
        /// </summary>
        private void CreateMeshes(BspMap bspMap)
        {
            for (var id = 0; id < bspMap.Data.drawSurfaces.Length; id++)
            {
                var surface = bspMap.Data.drawSurfaces[id];

                //Crear Patch (curva=
                if (surface.surfaceType == QMapSurfaceType.Patch)
                {
                    tessellatePatch(bspMap, id);
                    continue;
                }

                /* billboards, no soportados actualmente
                 * if (surface.surfaceType == QMapSurfaceType.Flare)
                 * {
                 * }
                 */

                //Superficies no soportadas
                if (surface.surfaceType != QMapSurfaceType.Planar && surface.surfaceType != QMapSurfaceType.TriangleSoup)
                {
                    //Agregar null para no mover todos los índices
                    bspMap.Meshes.Add(null);
                    continue;
                }

                //Cargar superficies soportadas: de tipo QMapSurfaceType.Planar o QMapSurfaceType.TriangleSoup

                var cant_indices  = surface.numIndexes;
                var cant_vertices = surface.numVerts;

                if (cant_vertices <= 0)
                {
                    continue;
                }

                //Mesh de DirectX
                var mesh = new Mesh(cant_indices / 3, cant_vertices, MeshFlags.Managed,
                                    TgcSceneLoader.DiffuseMapAndLightmapVertexElements, D3DDevice.Instance.Device);

                //Cargar vertexBuffer
                using (var vb = mesh.VertexBuffer)
                {
                    var vertices = new TgcSceneLoader.DiffuseMapAndLightmapVertex[cant_vertices];

                    var j = 0;
                    for (var i = surface.firstVert; i < surface.firstVert + surface.numVerts; i++, j++)
                    {
                        vertices[j] = new TgcSceneLoader.DiffuseMapAndLightmapVertex();

                        vertices[j].Position = bspMap.Data.drawVerts[i].xyz;
                        vertices[j].Normal   = bspMap.Data.drawVerts[i].normal;
                        vertices[j].Tu0      = bspMap.Data.drawVerts[i].st.X;
                        vertices[j].Tv0      = bspMap.Data.drawVerts[i].st.Y;
                        vertices[j].Tu1      = bspMap.Data.drawVerts[i].lightmap.X;
                        vertices[j].Tv1      = bspMap.Data.drawVerts[i].lightmap.Y;
                        vertices[j].Color    = Color.White.ToArgb(); //drawVerts[i].color;
                    }

                    vb.SetData(vertices, 0, LockFlags.None);
                }

                using (var ib = mesh.IndexBuffer)
                {
                    var indices = new short[cant_indices];
                    var j       = 0;
                    for (var i = surface.firstIndex; i < surface.firstIndex + surface.numIndexes; i++, j++)
                    {
                        indices[j] = (short)bspMap.Data.drawIndexes[i];
                    }
                    ib.SetData(indices, 0, LockFlags.None);
                }

                //Crea el tgcMesh
                var tgcMesh = CreateTgcMesh(bspMap, mesh, id);
                bspMap.Meshes.Add(tgcMesh);
            }
        }