示例#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

            int L = 5;

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

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

            //Numero de patches de 3x3 en cada direccion
            int num1 = (surface.patchHeight - 1) / 2;
            int num2 = (surface.patchWidth - 1) / 2;
            int cantVertices = (L * num1 + 1) * (L * num2 + 1);
            int cantIndices = 2 * (L * num2 + 2) * (L * num1);
                
            //aloco el espacio para los vertices y los indices
            Vector3[] vertices = new Vector3[cantVertices];
            Vector3[] normals = new Vector3[cantVertices];
            Vector2[] textCords = new Vector2[cantVertices];
            Vector2[] textCords2 = new Vector2[cantVertices];
            int[] indices = new int[cantIndices];
            {
                //se cargan las constantes de bezier
                float dt = 1.0f / L;
                float t = 0;
                for (int i = 0; i < L + 1; i++)
                {
                    if (i == L)
                        t = 1.0f;
                    float 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
            int pointsXStrip = L * num2 + 1;
            int pointsXPatch = pointsXStrip * L;
            int indexCount = 0;
            int vertexNum = 0;
            int[] 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 (int j = 0; j < L; j++)
                {
                    for (int 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 (int i2 = 0; i2 < Li; i2++)
                    {
                        vertexNum = i * pointsXPatch + i2 * pointsXStrip + j * L;

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

                            for (int i3 = 0; i3 < 3; i3++)
                            {
                                for (int j3 = 0; j3 < 3; j3++)
                                {
                                    float 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;
                                }
                            }
                        }
                    }
                }
            }


            short[] indexBuffer = new short[3 * cantIndices - 6];
            int cant_ibuffer = 0;
            
            for (int 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
            Mesh mesh = new Mesh(indexBuffer.Length / 3, vertices.Length, MeshFlags.Managed,
                                 TgcSceneLoader.DiffuseMapAndLightmapVertexElements,
                                 GuiController.Instance.D3dDevice);

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

                for (int 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 (IndexBuffer ib = mesh.IndexBuffer)
            {
                ib.SetData(indexBuffer, 0, LockFlags.None);
            }

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

            bspMap.Meshes.Add(tgcMesh);  
        }
示例#2
0
        /// <summary>
        /// Carga todos los meshes
        /// </summary>
        private void CreateMeshes(BspMap bspMap)
        {
            Device device = GuiController.Instance.D3dDevice;

            for (int id = 0; id < bspMap.Data.drawSurfaces.Length; id++)
            {
                QSurface 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

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

                if (cant_vertices <= 0)
                    continue;

                //Mesh de DirectX
                Mesh mesh = new Mesh(cant_indices / 3, cant_vertices, MeshFlags.Managed, TgcSceneLoader.DiffuseMapAndLightmapVertexElements, device);

                //Cargar vertexBuffer
                using (VertexBuffer vb = mesh.VertexBuffer)
                {
                    TgcSceneLoader.DiffuseMapAndLightmapVertex[] vertices = new TgcSceneLoader.DiffuseMapAndLightmapVertex[cant_vertices];
                    
                    int j = 0;
                    for (int 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 (IndexBuffer ib = mesh.IndexBuffer)
                {
                    short[] indices = new short[cant_indices];
                    int j = 0;
                    for (int 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
                TgcMesh tgcMesh = CreateTgcMesh(bspMap, mesh, id);
                bspMap.Meshes.Add(tgcMesh);
            }
        }