コード例 #1
0
        public kd_node createKDTreeNode(Vector3 pmin, Vector3 pmax, int deep, int cant_f, int [] p_list)
        {
            kd_node p_node = new kd_node();

            p_node.deep  = deep;
            p_node.p_min = pmin;
            p_node.p_max = pmax;

            // creo un nodo leaf
            p_node.cant_f = cant_f;
            p_node.p_list = p_list;

            // si la cantidad de primitivas en el nodo es mayor a cierto limite y el deep no supera el maximo, pruebo dividir el nodo
            if (cant_f >= MAX_FACE_X_NODE && deep < max_deep)
            {
                // divido el nodo en 2:
                Vector3 dim = pmax - pmin;
                Vector3 Lmin, Lmax, Rmin, Rmax;
                int     eje;
                float   s;

                // version eje fijo: selecciono el eje en base a la direccion que mas extension tiene
                {
                    if (MathF.Abs(dim.Z) >= MathF.Abs(dim.X) && MathF.Abs(dim.Z) >= MathF.Abs(dim.Y))
                    {
                        eje = 2;                                    // split Z
                        s   = (pmin.Z + pmax.Z) * 0.5f;
                    }
                    else
                    if (MathF.Abs(dim.X) >= MathF.Abs(dim.Z) && MathF.Abs(dim.X) >= MathF.Abs(dim.Y))
                    {
                        eje = 0;                                    // splite X
                        s   = (pmin.X + pmax.X) * 0.5f;
                    }
                    else
                    {
                        eje = 1;                                    // split Y
                        s   = (pmin.Y + pmax.Y) * 0.5f;
                    }

                    //s = best_split(eje,p_node);
                }

                /*
                 * else
                 * {
                 *      // version que prueba los 3 ejes:
                 *      eje = best_split(p_node, &s);
                 * }
                 */


                p_node.split       = s;
                p_node.split_plane = eje;
                Rmin = Lmin = pmin;
                Rmax = Lmax = pmax;

                switch (eje)
                {
                case 0:
                    Lmax.X = s;
                    Rmin.X = s;
                    break;

                case 1:
                    Lmax.Y = s;
                    Rmin.Y = s;
                    break;

                case 2:
                    Lmax.Z = s;
                    Rmin.Z = s;
                    break;
                }

                // clasifico las primitivas
                int cant_L = 0;
                int cant_R = 0;

                int[] list_L = new int[cant_f];
                int[] list_R = new int[cant_f];

                for (int i = 0; i < cant_f; ++i)
                {
                    bsp_face f = F[p_list[i]];
                    if (box_overlap(f.pmin, f.pmax, Lmin, Lmax))
                    {
                        list_L[cant_L++] = p_list[i];
                    }
                    if (box_overlap(f.pmin, f.pmax, Rmin, Rmax))
                    {
                        list_R[cant_R++] = p_list[i];
                    }
                }

                // hago el nodo interior:
                // libero la memoria original

                /*
                 * if (p_node.p_list)
                 * {
                 *      delete[] p_node.p_list;
                 *      p_node.p_list = NULL;
                 * }*/
                p_node.p_list = null;

                // creo los 2 nodos hijos
                p_node.p_left  = createKDTreeNode(Lmin, Lmax, deep + 1, cant_L, list_L);
                p_node.p_right = createKDTreeNode(Rmin, Rmax, deep + 1, cant_R, list_R);
            }

            return(p_node);
        }
コード例 #2
0
        public CBspFile(string fname, GraphicsDevice p_device, ContentManager p_content)
        {
            device     = p_device;
            Content    = p_content;
            Effect     = Content.Load <Effect>("Effects/PhongShader");
            EffectMesh = Content.Load <Effect>("Effects/BasicShader");

            var fp        = new FileStream(map_folder + fname + ".tgc", FileMode.Open, FileAccess.Read);
            var arrayByte = new byte[(int)fp.Length];

            fp.Read(arrayByte, 0, (int)fp.Length);
            fp.Close();
            initMeshFromData(arrayByte);
            texture_default = Content.Load <Texture2D>("Textures/barrier");
            // cargo las entidades
            cargarEntidades(fname);
            createSpriteQuad();

            // experimento kdtree con toda la escena + los mesh
            g_cant_faces = cant_faces;
            for (int i = 0; i < cant_modelos; ++i)
            {
                g_cant_faces += mesh_pool.meshes[modelos[i].nro_mesh].cant_faces;
            }
            g_faces      = new bsp_face[g_cant_faces];
            g_cant_faces = 0;
            for (var i = 0; i < cant_faces; ++i)
            {
                g_faces[g_cant_faces++] = faces[i];
            }


            VertexPosition[] bb_vertices = new VertexPosition[cant_modelos * 36];
            var t = 0;

            for (int i = 0; i < cant_modelos; ++i)
            {
                var m = mesh_pool.meshes[modelos[i].nro_mesh];
                // TODO: determino si me conviene usar todo el mesh a nivel triangulos
                // o solo el bounding box

                /*var dx = m.p_max.X - m.p_min.X;
                 * var dy = m.p_max.Y - m.p_min.Y;
                 * var dz = m.p_max.Z - m.p_min.Z;
                 */
                if (true)
                {
                    // todos los triangulos
                    for (var j = 0; j < m.cant_faces; ++j)
                    {
                        var face = g_faces[g_cant_faces++] = new bsp_face();
                        for (var k = 0; k < 3; ++k)
                        {
                            face.v[k]       = Vector3.Transform(m.faces[j].v[k], modelos[i].world());
                            face.nro_modelo = i;
                        }
                    }
                }
                else
                {
                    // solo el bounding box oobb
                    var x0 = m.p_min.X;
                    var y0 = m.p_min.Y;
                    var z0 = m.p_min.Z;
                    var x1 = m.p_max.X;
                    var y1 = m.p_max.Y;
                    var z1 = m.p_max.Z;

                    Vector3[] p = new Vector3[8];
                    p[0] = new Vector3(x0, y0, z0);
                    p[1] = new Vector3(x1, y0, z0);
                    p[2] = new Vector3(x1, y1, z0);
                    p[3] = new Vector3(x0, y1, z0);

                    p[4] = new Vector3(x0, y0, z1);
                    p[5] = new Vector3(x1, y0, z1);
                    p[6] = new Vector3(x1, y1, z1);
                    p[7] = new Vector3(x0, y1, z1);

                    for (var j = 0; j < 8; ++j)
                    {
                        p[j] = Vector3.Transform(p[j], modelos[i].world());
                    }


                    int[] ndx =
                    {
                        0, 1, 2, 0, 2, 3,                                               // abajo
                        4, 5, 6, 4, 6, 7,                                               // arriba
                        1, 2, 6, 1, 6, 5,                                               // derecha
                        0, 3, 7, 0, 7, 4,                                               // izquierda
                        3, 2, 6, 3, 6, 7,                                               // adelante
                        0, 1, 5, 0, 5, 4                                                // atras
                    };

                    for (int j = 0; j < 36; ++j)
                    {
                        bb_vertices[t++] = new VertexPosition(p[ndx[j]]);
                    }
                }
            }

            cant_debug_bb = t;
            if (cant_debug_bb > 0)
            {
                bbVertexBuffer = new VertexBuffer(device, VertexPosition.VertexDeclaration, t, BufferUsage.WriteOnly);
                bbVertexBuffer.SetData(bb_vertices, 0, t);
            }

            // armo el kdtree
            //kd_tree = new KDTree(cant_faces, faces);
            kd_tree = new KDTree(g_cant_faces, g_faces);
            kd_tree.createKDTree();


            // imagenes
            images[cant_images++] = cargarImagen("sprites\\redglow4");
            images[cant_images++] = cargarImagen("sprites\\dot");
            images[cant_images++] = cargarImagen("sprites\\orangecore1");
            images[cant_images++] = cargarImagen("sprites\\laserdot");


            // decals
            createDecals();
        }
コード例 #3
0
        public void initMeshFromData(byte[] arrayByte)
        {
            var   t      = 0;
            int   cant_v = (int)BitConverter.ToInt32(arrayByte, t); t += 4;
            float min_x  = 1000000;
            float min_y  = 1000000;
            float min_z  = 1000000;
            float max_x  = -1000000;
            float max_y  = -1000000;
            float max_z  = -1000000;


            ValveVertex[] vertices = new ValveVertex[cant_v];
            for (var i = 0; i < cant_v; ++i)
            {
                var x = BitConverter.ToSingle(arrayByte, t); t += 4;
                var z = BitConverter.ToSingle(arrayByte, t); t += 4;
                var y = BitConverter.ToSingle(arrayByte, t); t += 4;

                vertices[i].Position.X = x;
                vertices[i].Position.Y = y;
                vertices[i].Position.Z = z;

                if (x < min_x)
                {
                    min_x = x;
                }
                if (y < min_y)
                {
                    min_y = y;
                }
                if (z < min_z)
                {
                    min_z = z;
                }
                if (x > max_x)
                {
                    max_x = x;
                }
                if (y > max_y)
                {
                    max_y = y;
                }
                if (z > max_z)
                {
                    max_z = z;
                }

                vertices[i].TextureCoordinate.X = BitConverter.ToSingle(arrayByte, t); t += 4;
                vertices[i].TextureCoordinate.Y = BitConverter.ToSingle(arrayByte, t); t += 4;

                vertices[i].LightmapCoordinate.X = -BitConverter.ToSingle(arrayByte, t); t += 4;
                vertices[i].LightmapCoordinate.Y = BitConverter.ToSingle(arrayByte, t); t += 4;
            }

            // actualizo el bounding box
            p_min = new Vector3(min_x, min_y, min_z);
            p_max = new Vector3(max_x, max_y, max_z);
            size  = new Vector3(max_x - min_x, max_y - min_y, max_z - min_z);
            cg    = p_min + size * 0.5f;


            // computo la normal y de paso actualizo la geoemtria
            int cant_tri = cant_v / 3;



            for (int i = 0; i < cant_tri; ++i)
            {
                Vector3 v0 = vertices[3 * i].Position;
                Vector3 v1 = vertices[3 * i + 1].Position;
                Vector3 v2 = vertices[3 * i + 2].Position;

                Vector3 N = Vector3.Cross(v1 - v0, v2 - v0);
                N.Normalize();
                vertices[3 * i].Normal = vertices[3 * i + 1].Normal = vertices[3 * i + 2].Normal = N;
            }


            VertexBuffer = new VertexBuffer(device, ValveVertex.VertexDeclaration, cant_v, BufferUsage.WriteOnly);
            VertexBuffer.SetData(vertices);


            // estructura de subsets
            cant_subsets = (int)BitConverter.ToInt32(arrayByte, t); t += 4;
            subset       = new bsp_subset[cant_subsets];
            texture      = new Texture2D[cant_subsets];

            for (int i = 0; i < cant_subsets; ++i)
            {
                subset[i]            = new bsp_subset();
                subset[i].cant_items = (int)BitConverter.ToInt32(arrayByte, t); t += 4;
                string name = getString(arrayByte, t, 256); t += 256;
                name = name.ToUpper();
                subset[i].image_name = name = que_tga_name(name);
                var tga = tex_folder + name + ".tga";
                texture[i] = null;
                if (File.Exists(tga))
                {
                    texture[i] = CTextureLoader.Load(device, tga);
                }

                if (texture[i] == null)
                {
                    Debug.WriteLine(i + "-" + subset[i].image_name);
                }
            }

            // como mucho hay cant_tri faces a los efectos de colision, anulo las que son TOOLS
            faces      = new bsp_face[cant_tri];
            cant_faces = 0;
            var pos = 0;

            for (var i = 0; i < cant_subsets; i++)
            {
                if (!subset[i].image_name.StartsWith("TOOLS"))
                {
                    for (int j = 0; j < subset[i].cant_items; ++j)
                    {
                        var     k  = pos + 3 * j;
                        Vector3 v0 = vertices[k].Position;
                        Vector3 v1 = vertices[k + 1].Position;
                        Vector3 v2 = vertices[k + 2].Position;
                        faces[cant_faces]            = new bsp_face();
                        faces[cant_faces].v[0]       = v0;
                        faces[cant_faces].v[1]       = v1;
                        faces[cant_faces].v[2]       = v2;
                        faces[cant_faces].nro_modelo = -1 - i;                                  // escenario
                        cant_faces++;
                    }
                }
                pos += subset[i].cant_items * 3;
            }


            // leo el lightmap
            lightmap = new Texture2D(device, 2048, 2048);
            int lm_size = 2048 * 2048;

            Color[] data = new Color[lm_size];
            for (int pixel = 0; pixel < lm_size; pixel++)
            {
                data[pixel].R = arrayByte[t++];
                data[pixel].G = arrayByte[t++];
                data[pixel].B = arrayByte[t++];
                data[pixel].A = (byte)(arrayByte[t++] + 128);
            }
            lightmap.SetData(data);
        }
コード例 #4
0
        public bool cargar_smd(String fname)
        {
            var fp = new System.IO.StreamReader(fname);

            var buffer = fp.ReadLine().TrimStart();

            while (!buffer.StartsWith("nodes"))
            {
                buffer = fp.ReadLine().TrimStart();
            }

            // huesos
            buffer = fp.ReadLine().TrimStart();
            while (!buffer.StartsWith("end"))
            {
                // 0 "L_Armdummy" -1
                string[] tokens = buffer.Split(' ');
                bones[cant_bones]        = new smd_bone();
                bones[cant_bones].id     = int.Parse(tokens[0]);
                bones[cant_bones].name   = tokens[1];
                bones[cant_bones].parent = int.Parse(tokens[2]);
                ++cant_bones;
                buffer = fp.ReadLine().TrimStart();
            }

            // skeleton
            fp.ReadLine().TrimStart();
            // time 0
            fp.ReadLine().TrimStart();
            buffer = fp.ReadLine().TrimStart();
            while (!buffer.StartsWith("end"))
            {
                string[] tokens = buffer.Split(' ');
                int      id     = int.Parse(tokens[0]);
                if (id >= 0 && id < cant_bones)
                {
                    bones[id].startPosition.X = atof(tokens[1]);
                    bones[id].startPosition.Y = atof(tokens[2]);
                    bones[id].startPosition.Z = atof(tokens[3]);
                    bones[id].startRotation.X = atof(tokens[4]);
                    bones[id].startRotation.Y = atof(tokens[5]);
                    bones[id].startRotation.Z = atof(tokens[6]);
                }
                buffer = fp.ReadLine().TrimStart();
            }

            // triangles y subsets
            cant_subsets = 0;
            subset       = new smd_subset[100];
            smd_vertex[] vertices = new smd_vertex[65535];
            int          cant_v   = 0;
            float        min_x    = 1000000;
            float        min_y    = 1000000;
            float        min_z    = 1000000;
            float        max_x    = -1000000;
            float        max_y    = -1000000;
            float        max_z    = -1000000;

            fp.ReadLine().TrimStart();
            buffer = fp.ReadLine().TrimStart();
            smd_subset cur_subset = null;

            while (!buffer.StartsWith("end"))
            {
                // material
                var mat = Path.GetFileNameWithoutExtension(buffer);
                if (que_subset(mat) == -1)
                {
                    // agrego el subset
                    cur_subset = subset[cant_subsets++] = new smd_subset(mat);
                }


                // 3 vertices
                // 35 4.564999 -13.692499 -4.852700 -0.237700 0.289800 0.927100 0.498400 0.279000
                for (int i = 0; i < 3; ++i)
                {
                    buffer = fp.ReadLine().TrimStart();
                    string[] tokens = buffer.Split(' ');
                    int      id     = int.Parse(tokens[0]);

                    Vector3 P = transform(new Vector3(atof(tokens[1]), atof(tokens[2]), atof(tokens[3])), Metric);
                    Vector3 N = transform(new Vector3(atof(tokens[4]), atof(tokens[5]), atof(tokens[6])), Metric);

                    vertices[cant_v].Position.X          = P.X;
                    vertices[cant_v].Position.Y          = P.Y;
                    vertices[cant_v].Position.Z          = P.Z;
                    vertices[cant_v].Normal.X            = N.X;
                    vertices[cant_v].Normal.Y            = N.Y;
                    vertices[cant_v].Normal.Z            = N.Z;
                    vertices[cant_v].TextureCoordinate.X = atof(tokens[7]);
                    vertices[cant_v].TextureCoordinate.Y = -atof(tokens[8]);
                    vertices[cant_v].BlendIndices.X      = id;
                    vertices[cant_v].BlendWeight.X       = 1;
                    ++cant_v;

                    if (P.X < min_x)
                    {
                        min_x = P.X;
                    }
                    if (P.Y < min_y)
                    {
                        min_y = P.Y;
                    }
                    if (P.Z < min_z)
                    {
                        min_z = P.Z;
                    }
                    if (P.X > max_x)
                    {
                        max_x = P.X;
                    }
                    if (P.Y > max_y)
                    {
                        max_y = P.Y;
                    }
                    if (P.Z > max_z)
                    {
                        max_z = P.Z;
                    }
                }
                cur_subset.cant_items++;
                buffer = fp.ReadLine().TrimStart();
            }
            fp.Close();
            setupBones();

            // actualizo el bounding box
            p_min = new Vector3(min_x, min_y, min_z);
            p_max = new Vector3(max_x, max_y, max_z);
            size  = new Vector3(max_x - min_x, max_y - min_y, max_z - min_z);
            cg    = p_min + size * 0.5f;

            // Creo el vertex buffer
            VertexBuffer = new VertexBuffer(device, smd_vertex.VertexDeclaration, cant_v, BufferUsage.WriteOnly);
            VertexBuffer.SetData(vertices, 0, cant_v);

            // almaceno los faces a los efectos de colision
            faces      = new bsp_face[cant_v / 3];
            cant_faces = 0;
            var pos = 0;

            for (var i = 0; i < cant_subsets; i++)
            {
                for (int j = 0; j < subset[i].cant_items; ++j)
                {
                    var     k  = pos + 3 * j;
                    Vector3 v0 = vertices[k].Position;
                    Vector3 v1 = vertices[k + 1].Position;
                    Vector3 v2 = vertices[k + 2].Position;
                    faces[cant_faces]      = new bsp_face();
                    faces[cant_faces].v[0] = v0;
                    faces[cant_faces].v[1] = v1;
                    faces[cant_faces].v[2] = v2;
                    cant_faces++;
                }
                pos += subset[i].cant_items * 3;
            }

            initTextures();

            // actualizo la pos de cada subset
            pos = 0;
            for (var i = 0; i < cant_subsets; i++)
            {
                subset[i].pos = pos;
                pos          += subset[i].cant_items * 3;
            }
            return(true);
        }