Пример #1
0
        /// <summary>
        /// box testaus. onko laatikko edes osittain ruudulla. jos on, palauta true.
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="z"></param>
        /// <param name="bb"></param>
        /// <returns></returns>
        public static bool BoxInFrustum(float x, float y, float z, BoundingVolume bb)
        {
            int q;
            for (q = 0; q < 6; q++)
            {
                if ((frustum[q, 0] * (x + bb.Min.X)) + (frustum[q, 1] * (y + bb.Min.Y)) + (frustum[q, 2] * (z + bb.Min.Z)) + frustum[q, 3] > 0)
                {
                    continue;
                }

                if ((frustum[q, 0] * (x + bb.Max.X)) + (frustum[q, 1] * (y + bb.Min.Y)) + (frustum[q, 2] * (z + bb.Min.Z)) + frustum[q, 3] > 0)
                {
                    continue;
                }

                if ((frustum[q, 0] * (x + bb.Max.X)) + (frustum[q, 1] * (y + bb.Min.Y)) + (frustum[q, 2] * (z + bb.Max.Z)) + frustum[q, 3] > 0)
                {
                    continue;
                }

                if ((frustum[q, 0] * (x + bb.Min.X)) + (frustum[q, 1] * (y + bb.Min.Y)) + (frustum[q, 2] * (z + bb.Max.Z)) + frustum[q, 3] > 0)
                {
                    continue;
                }

                if ((frustum[q, 0] * (x + bb.Min.X)) + (frustum[q, 1] * (y + bb.Max.Y)) + (frustum[q, 2] * (z + bb.Min.Z)) + frustum[q, 3] > 0)
                {
                    continue;
                }

                if ((frustum[q, 0] * (x + bb.Max.X)) + (frustum[q, 1] * (y + bb.Max.Y)) + (frustum[q, 2] * (z + bb.Min.Z)) + frustum[q, 3] > 0)
                {
                    continue;
                }

                if ((frustum[q, 0] * (x + bb.Max.X)) + (frustum[q, 1] * (y + bb.Max.Y)) + (frustum[q, 2] * (z + bb.Max.Z)) + frustum[q, 3] > 0)
                {
                    continue;
                }

                if ((frustum[q, 0] * (x + bb.Min.X)) + (frustum[q, 1] * (y + bb.Max.Y)) + (frustum[q, 2] * (z + bb.Max.Z)) + frustum[q, 3] > 0)
                {
                    continue;
                }

                // jos päästään tänne, objekti ei ole frustumissa
                return false;
            }

            // vertex ruudulla, objekti on näkyvä
            return true;
        }
 public static bool ObjectInFrustum(Vector3 position, BoundingVolume bound)
 {
     return(ObjectInFrustum(position.X, position.Y, position.Z, bound));
 }
Пример #3
0
        /// <summary>
        /// lataa mesh tiedosto
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="xs"></param>
        /// <param name="ys"></param>
        /// <param name="zs"></param>
        public void Load(string fileName, float xs, float ys, float zs)
        {
            pathData.Clear();
            ObjModel       mesh    = null;
            List <Vector3> _vertex = new List <Vector3>();
            List <Vector3> _normal = new List <Vector3>();
            List <Vector2> _uv     = new List <Vector2>();

            string dir = Settings.DataDir;

            if (fileName.Contains("\\"))
            {
                int l = fileName.LastIndexOf("\\");
                dir = dir + fileName.Substring(0, l + 1);
            }
            else if (fileName.Contains("/"))
            {
                int l = fileName.LastIndexOf("/");
                dir = dir + fileName.Substring(0, l + 1);
            }

            fileName = Settings.DataDir + fileName;
            bool path = false; // jos reitti

            using (System.IO.StreamReader file = new System.IO.StreamReader(fileName))
            {
                // tiedosto muistiin
                string data = file.ReadToEnd();
                data = data.Replace('\r', ' ');

                // pilko se
                string[] lines = data.Split('\n');

                int numOfFaces = 0;
                for (int q = 0; q < lines.Length; q++)
                {
                    string[] ln = lines[q].Split(' '); // pilko datat
                    if (ln[0] == "f")
                    {
                        numOfFaces++;
                    }
                }

                // lue kaikki datat objektiin ja indexit mesheihin
                for (int q = 0; q < lines.Length; q++)
                {
                    string line = lines[q];
                    if (line.StartsWith("#"))
                    {
                        continue;
                    }
                    string[] ln = line.Split(' '); // pilko datat
                    if (ln[0] == "v")              // vertex x y z
                    {
                        float x = (Util.GetFloat(ln[1]) - mesh.Position.X) * xs;
                        float y = (Util.GetFloat(ln[2]) - mesh.Position.Y) * ys;
                        float z = (Util.GetFloat(ln[3]) - mesh.Position.Z) * zs;

                        if (path)
                        {
                            pathData.Add(new Vector3(x, y, z));
                        }
                        else
                        {
                            _vertex.Add(new Vector3(x, y, z));
                        }

                        continue;
                    }

                    if (ln[0] == "vn") // normal x y z
                    {
                        _normal.Add(new Vector3(Util.GetFloat(ln[1]), Util.GetFloat(ln[2]), Util.GetFloat(ln[3])));
                        continue;
                    }

                    if (ln[0] == "vt") // texcoord U V
                    {
                        _uv.Add(new Vector2(Util.GetFloat(ln[1]), Util.GetFloat(ln[2])));
                        continue;
                    }

                    // uusi objekti
                    if (ln[0] == "o" || ln[0] == "g")
                    {
                        if (mesh != null)
                        {
                            meshes.Add(mesh);               // talteen
                        }
                        mesh          = new ObjModel(ln[1]);
                        mesh.material = material;

                        // Nimessä voi olla ohjeita mitä muuta halutaan, esim:
                        // * Path_reitti1  jolloin ei ladata objektia mutta reitti jota pitkin kamera/objektit voi kulkea.
                        // * BBox_nimi/BSphere_nimi jolloin tämä onkin nimi-objektin bounding box/sphere.
                        if (mesh.Name.Contains("Path_"))
                        {
                            path = true;
                        }
                        else if (mesh.Name.Contains("BBox_") || mesh.Name.Contains("BSphere_"))
                        {
                            // TODO: bbox_ bsphere_
                        }

                        continue;
                    }

                    // materiaali
                    if (ln[0] == "usemtl")
                    {
                        // jos kesken meshin materiaali vaihtuu, luodaan uusi obu johon loput facet
                        if (lines[q - 1].StartsWith("f"))
                        {
                            meshes.Add(mesh);
                            Vector3 tmpPos = mesh.Position;

                            mesh          = new ObjModel(mesh.Name);
                            mesh.material = material;
                            mesh.Position = tmpPos; // samaa objektia, niin sama Position
                        }

                        mesh.MaterialName = ln[1];
                        continue;
                    }

                    if (ln[0] == "f")
                    {
                        // ota talteen  f rivi:
                        // f vertex/uv/normal vertex/uv/normal vertex/uv/normal
                        // eli esim: f 4/4/2 5/5/3 7/2/4
                        // tarkistetaan jos ilman texcoordei eli f 4/4 5/4 6/4  tai f 2//3 jne tai ilman / merkkejä.
                        int dv = 0;
                        for (int t = 0; t < line.Length; t++)
                        {
                            if (line[t] == '/')
                            {
                                dv++;
                            }
                        }
                        if (line.Contains("//"))
                        {
                            dv = 0;                      // ei ole texindexei
                        }
                        line = line.Replace("//", " ");
                        line = line.Replace("/", " ");
                        string[] _ln = line.Split(' ');

                        if (dv == 0 || dv == 3) // luultavasti nyt ei ole texturecoordinaatteja
                        {
                            mesh._vertexInd.Add(Int32.Parse(_ln[1]) - 1);
                            mesh._vertexInd.Add(Int32.Parse(_ln[3]) - 1);
                            mesh._vertexInd.Add(Int32.Parse(_ln[5]) - 1);

                            mesh._normalInd.Add(Int32.Parse(_ln[2]) - 1);
                            mesh._normalInd.Add(Int32.Parse(_ln[4]) - 1);
                            mesh._normalInd.Add(Int32.Parse(_ln[6]) - 1);
                        }
                        else // kaikki mukana
                        {
                            mesh._vertexInd.Add(Int32.Parse(_ln[1]) - 1);
                            mesh._vertexInd.Add(Int32.Parse(_ln[4]) - 1);
                            mesh._vertexInd.Add(Int32.Parse(_ln[7]) - 1);

                            mesh._uvInd.Add(Int32.Parse(_ln[2]) - 1);
                            mesh._uvInd.Add(Int32.Parse(_ln[5]) - 1);
                            mesh._uvInd.Add(Int32.Parse(_ln[8]) - 1);

                            mesh._normalInd.Add(Int32.Parse(_ln[3]) - 1);
                            mesh._normalInd.Add(Int32.Parse(_ln[6]) - 1);
                            mesh._normalInd.Add(Int32.Parse(_ln[9]) - 1);
                        }
                        continue;
                    }

                    // materiaalitiedosto
                    if (ln[0] == "mtllib")
                    {
                        try
                        {
                            // ladataan objektille materiaalitiedot (mesheille otetaan talteen materialname joka viittaa sitten näihin materiaaleihin)
                            material = new Material();
                            material.Load(dir + ln[1], Texture.LoadTextures);
                        }
                        catch (Exception e)
                        {
                            Log.WriteDebugLine(e.ToString());
                        }
                    }
                }

                if (mesh != null)
                {
                    meshes.Add(mesh);
                }

                // pathille ei luoda objektia, se on vain kasa vertexejä
                if (path == false)
                {
                    int cc = 0;

                    vertices = new Vertex[numOfFaces * 3];
                    for (int m = 0; m < meshes.Count; m++)
                    {
                        meshes[m].vertices = new Vertex[meshes[m]._vertexInd.Count];

                        for (int q = 0; q < meshes[m]._vertexInd.Count; q++)
                        {
                            // mesh datat
                            meshes[m].vertices[q].vertex = _vertex[meshes[m]._vertexInd[q]];
                            meshes[m].vertices[q].normal = _normal[meshes[m]._normalInd[q]];
                            if (meshes[m]._uvInd.Count != 0)
                            {
                                meshes[m].vertices[q].uv_or_color = new Vector4(_uv[meshes[m]._uvInd[q]].X, _uv[meshes[m]._uvInd[q]].Y,
                                                                                _uv[meshes[m]._uvInd[q]].X, _uv[meshes[m]._uvInd[q]].Y);
                            }

                            // pistetään myös objektille kaikki vertexit yhteen klimppiin.

//TODO Miks? vie vaa muistia nii paljo, mesheissä kumminki nuo datat säilytetään.
// jos tää on VAIN collisionia varten, siihe ny o helppo tehdä se et se menee objektin puun läpi
// ni sit ei tartte tätä
                            vertices[cc].vertex = _vertex[meshes[m]._vertexInd[q]];
                            vertices[cc].normal = _normal[meshes[m]._normalInd[q]];
                            if (meshes[m]._uvInd.Count != 0)
                            {
                                vertices[cc].uv_or_color = new Vector4(_uv[meshes[m]._uvInd[q]].X, _uv[meshes[m]._uvInd[q]].Y,
                                                                       _uv[meshes[m]._uvInd[q]].X, _uv[meshes[m]._uvInd[q]].Y);
                            }
                            cc++;
                        }

                        // index taulukko
                        meshes[m].indices = new int[meshes[m]._vertexInd.Count];
                        for (int q = 0; q < meshes[m]._vertexInd.Count; q++)
                        {
                            meshes[m].indices[q] = q;
                        }

                        meshes[m].vbo = new VBO();
                        meshes[m].vbo.DataToVBO(meshes[m].vertices, meshes[m].indices);

                        // meshin bounding volume
                        meshes[m].Boundings = new BoundingVolume();
                        meshes[m].Boundings.CreateBoundingVolume(meshes[m]);

                        // lataa glsl koodit
                        string shader = material.GetMaterial(meshes[m].MaterialName).ShaderName;
                        if (shader != "")
                        {
                            mesh.Shader = new GLSL();
                            mesh.Shader.Load(shader + ".vert", shader + ".frag");
                        }
                        if (material.GetMaterial(meshes[m].MaterialName).Dissolve < 1.0f)
                        {
                            IsTranslucent = true;
                        }
                    }

                    // koko objektin bounding volume
                    IsRendObj = false; // childeissä rendattavat objektit, tässä ei ole rendattavaa, vain paikka
                    Boundings = new BoundingVolume();
                    Boundings.CreateBoundingVolume(this);

                    // lisätään objektille meshit childeiks
                    for (int q = 0; q < meshes.Count; q++)
                    {
                        Add(meshes[q]);
                    }

                    Log.WriteDebugLine("Object: " + Name + "  meshes: " + meshes.Count);
                }

                _vertex.Clear();
                _normal.Clear();
                _uv.Clear();
                for (int q = 0; q < meshes.Count; q++)
                {
                    meshes[q]._vertexInd.Clear();
                    meshes[q]._normalInd.Clear();
                    meshes[q]._uvInd.Clear();
                }
            }
        }
Пример #4
0
        public static bool ObjectInFrustum(float x, float y, float z, BoundingVolume bound)
        {
            if (bound == null) return true;

            switch (bound.Mode)
            {
                case BoundingVolume.TestMode.Box: // box
                    if (BoxInFrustum(x, y, z, bound) == false) return false;
                    break;

                case BoundingVolume.TestMode.Sphere: // sphere
                    if (SphereInFrustum(x, y, z, bound.R) == 0) return false;
                    break;
            }
            return true;
        }
Пример #5
0
 public static bool ObjectInFrustum(Vector3 position, BoundingVolume bound)
 {
     return ObjectInFrustum(position.X, position.Y, position.Z, bound);
 }
Пример #6
0
        /// <summary>
        /// lataa md5-animaatio.
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="anim"></param>
        public override void LoadAnim(string animName, string fileName)
        {
            if (fileName == null || fileName == "") return;

            Animation anim = new Animation();
            anim.animName = animName;

            Buffer t = new Buffer();
            MD5JointInfo[] jointInfos = null;
            MD5BaseFrameJoint[] baseFrame = null;
            float[] animFrameData = null;
            int numAnimatedComponents = 0;
            int frame_index;
            int i;

            using (System.IO.StreamReader file = new System.IO.StreamReader(Settings.DataDir + fileName))
            {
                string line;
                while ((line = file.ReadLine()) != null)
                {
                    if (line == "") continue;

                    // Read number of joints
                    if (ParseLine(ref t, line, "numFrames %d"))
                    {
                        /* Allocate memory for skeleton frames and bounding boxes */
                        anim.numFrames = t.ibuffer[0];
                        if (anim.numFrames > 0)
                        {
                            anim.bboxes = new MD5BoundingBox[anim.numFrames];
                        }
                    }

                    if (ParseLine(ref t, line, "numJoints %d"))
                    {
                        /* Allocate memory for joints of each frame */
                        anim.numJoints = t.ibuffer[0];
                        if (anim.numJoints > 0)
                        {
                            /* Allocate temporary memory for building skeleton frames */
                            jointInfos = new MD5JointInfo[anim.numJoints];
                            baseFrame = new MD5BaseFrameJoint[anim.numJoints];
                        }
                        anim.skelFrames = new MD5Joint[anim.numFrames, anim.numJoints];
                    }

                    if (ParseLine(ref t, line, "frameRate %d"))
                    {
                        anim.frameRate = t.ibuffer[0];
                    }

                    if (ParseLine(ref t, line, "numAnimatedComponents %d"))
                    {
                        numAnimatedComponents = t.ibuffer[0];
                        if (numAnimatedComponents > 0)
                        {
                            /* Allocate memory for animation frame data */
                            animFrameData = new float[numAnimatedComponents];
                        }

                    }

                    if (line.Equals("hierarchy {"))
                    {
                        for (i = 0; i < anim.numJoints; ++i)
                        {
                            /* Read whole line */
                            line = file.ReadLine();
                            Cleanstring(ref line);

                            /* Read joint info */
                            ParseLine(ref t, line, "%s %d %d %d");
                            jointInfos[i].name = t.sbuffer;
                            jointInfos[i].parent = t.ibuffer[0];
                            jointInfos[i].flags = t.ibuffer[1];
                            jointInfos[i].startIndex = t.ibuffer[2];
                        }
                    }

                    if (line.Equals("bounds {"))
                    {
                        for (i = 0; i < anim.numFrames; ++i)
                        {
                            /* Read whole line */
                            line = file.ReadLine();
                            Cleanstring(ref line);

                            /* Read bounding box */
                            ParseLine(ref t, line, "( %f %f %f ) ( %f %f %f )");
                            anim.bboxes[i].min.X = t.fbuffer[0];
                            anim.bboxes[i].min.Y = t.fbuffer[1];
                            anim.bboxes[i].min.Z = t.fbuffer[2];
                            anim.bboxes[i].max.X = t.fbuffer[3];
                            anim.bboxes[i].max.Y = t.fbuffer[4];
                            anim.bboxes[i].max.Z = t.fbuffer[5];
                        }
                    }

                    if (line.Equals("baseframe {"))
                    {
                        for (i = 0; i < anim.numJoints; ++i)
                        {
                            /* Read whole line */
                            line = file.ReadLine();
                            Cleanstring(ref line);

                            /* Read base frame joint */
                            ParseLine(ref t, line, "( %f %f %f ) ( %f %f %f )");

                            if (t.fbuffer.Length == 6)
                            {
                                baseFrame[i].pos.X = t.fbuffer[0];
                                baseFrame[i].pos.Y = t.fbuffer[1];
                                baseFrame[i].pos.Z = t.fbuffer[2];
                                baseFrame[i].orient.X = t.fbuffer[3];
                                baseFrame[i].orient.Y = t.fbuffer[4];
                                baseFrame[i].orient.Z = t.fbuffer[5];

                                /* Compute the w component */
                                MathExt.ComputeW(ref baseFrame[i].orient);

                            }
                        }
                    }

                    if (ParseLine(ref t, line, "frame %d"))
                    {
                        frame_index = t.ibuffer[0];

                        /* Read frame data */
                        for (i = 0; i < numAnimatedComponents; )
                        {
                            line = file.ReadLine();
                            if (line[0] == '}') break;
                            Cleanstring(ref line);
                            string[] splt = line.Split(' ');

                            for (int ww = 0; ww < splt.Length; ww++)
                            {
                                animFrameData[i++] = float.Parse(splt[ww]);
                            }
                        }

                        /* Build frame skeleton from the collected data */
                        BuildFrameSkeleton(ref jointInfos, ref baseFrame, ref animFrameData, frame_index, anim.numJoints, ref anim);
                    }
                }

                anim.curFrame = 0;
                anim.nextFrame = 1;

                anim.lastTime = 0;
                anim.maxTime = 1.0f / anim.frameRate;

                /* Allocate memory for animated skeleton */
                skeleton = new MD5Joint[anim.numJoints];
                animated = true;

                Vector3 min = new Vector3(9999, 9999, 9999);
                Vector3 max = new Vector3(-9999, -9999, -9999);

                // laske bboxit
                for (int q = 0; q < anim.numFrames; q++)
                {
                    if (anim.bboxes[q].min.X < min.X) min.X = anim.bboxes[q].min.X;
                    if (anim.bboxes[q].min.Y < min.Y) min.Y = anim.bboxes[q].min.Y;
                    if (anim.bboxes[q].min.Z < min.Z) min.Z = anim.bboxes[q].min.Z;

                    if (anim.bboxes[q].max.X > max.X) max.X = anim.bboxes[q].max.X;
                    if (anim.bboxes[q].max.Y > max.Y) max.Y = anim.bboxes[q].max.Y;
                    if (anim.bboxes[q].max.Z > max.Z) max.Z = anim.bboxes[q].max.Z;
                }

                Boundings = new BoundingVolume();
                Boundings.CreateBoundingVolume(this, min, max);

                Update(0);
                animations.Add(anim);

                Log.WriteDebugLine("Animation: " + fileName);

                UseAnimation(animName);
            }
        }
Пример #7
0
        /// <summary>
        /// lataa mesh tiedosto
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="xs"></param>
        /// <param name="ys"></param>
        /// <param name="zs"></param>
        public void Load(string fileName, float xs, float ys, float zs)
        {
            pathData.Clear();
            ObjModel mesh = null;
            List<Vector3> _vertex = new List<Vector3>();
            List<Vector3> _normal = new List<Vector3>();
            List<Vector2> _uv = new List<Vector2>();

            string dir = Settings.DataDir;
            if (fileName.Contains("\\"))
            {
                int l = fileName.LastIndexOf("\\");
                dir = dir + fileName.Substring(0, l + 1);
            }
            else if (fileName.Contains("/"))
            {
                int l = fileName.LastIndexOf("/");
                dir = dir + fileName.Substring(0, l + 1);
            }

            fileName = Settings.DataDir + fileName;
            bool path = false; // jos reitti

            using (System.IO.StreamReader file = new System.IO.StreamReader(fileName))
            {
                // tiedosto muistiin
                string data = file.ReadToEnd();
                data = data.Replace('\r', ' ');

                // pilko se
                string[] lines = data.Split('\n');

                int numOfFaces = 0;
                for (int q = 0; q < lines.Length; q++)
                {
                    string[] ln = lines[q].Split(' '); // pilko datat
                    if (ln[0] == "f") numOfFaces++;
                }

                // lue kaikki datat objektiin ja indexit mesheihin
                for (int q = 0; q < lines.Length; q++)
                {
                    string line = lines[q];
                    if (line.StartsWith("#")) continue;
                    string[] ln = line.Split(' '); // pilko datat
                    if (ln[0] == "v") // vertex x y z
                    {
                        float x = (Util.GetFloat(ln[1]) - mesh.Position.X) * xs;
                        float y = (Util.GetFloat(ln[2]) - mesh.Position.Y) * ys;
                        float z = (Util.GetFloat(ln[3]) - mesh.Position.Z) * zs;

                        if (path) pathData.Add(new Vector3(x, y, z));
                        else _vertex.Add(new Vector3(x, y, z));

                        continue;
                    }

                    if (ln[0] == "vn") // normal x y z
                    {
                        _normal.Add(new Vector3(Util.GetFloat(ln[1]), Util.GetFloat(ln[2]), Util.GetFloat(ln[3])));
                        continue;
                    }

                    if (ln[0] == "vt") // texcoord U V
                    {
                        _uv.Add(new Vector2(Util.GetFloat(ln[1]), Util.GetFloat(ln[2])));
                        continue;
                    }

                    // uusi objekti
                    if (ln[0] == "o" || ln[0] == "g")
                    {
                        if (mesh != null) meshes.Add(mesh); // talteen
                        mesh = new ObjModel(ln[1]);
                        mesh.material = material;

                        // Nimessä voi olla ohjeita mitä muuta halutaan, esim:
                        // * Path_reitti1  jolloin ei ladata objektia mutta reitti jota pitkin kamera/objektit voi kulkea.
                        // * BBox_nimi/BSphere_nimi jolloin tämä onkin nimi-objektin bounding box/sphere.
                        if (mesh.Name.Contains("Path_"))
                        {
                            path = true;
                        }
                        else if (mesh.Name.Contains("BBox_") || mesh.Name.Contains("BSphere_"))
                        {
                            // TODO: bbox_ bsphere_
                        }

                        continue;
                    }

                    // materiaali
                    if (ln[0] == "usemtl")
                    {
                        // jos kesken meshin materiaali vaihtuu, luodaan uusi obu johon loput facet
                        if (lines[q - 1].StartsWith("f"))
                        {
                            meshes.Add(mesh);
                            Vector3 tmpPos = mesh.Position;

                            mesh = new ObjModel(mesh.Name);
                            mesh.material = material;
                            mesh.Position = tmpPos; // samaa objektia, niin sama Position

                        }

                        mesh.MaterialName = ln[1];
                        continue;
                    }

                    if (ln[0] == "f")
                    {
                        // ota talteen  f rivi:
                        // f vertex/uv/normal vertex/uv/normal vertex/uv/normal
                        // eli esim: f 4/4/2 5/5/3 7/2/4
                        // tarkistetaan jos ilman texcoordei eli f 4/4 5/4 6/4  tai f 2//3 jne tai ilman / merkkejä.
                        int dv = 0;
                        for (int t = 0; t < line.Length; t++) if (line[t] == '/') dv++;
                        if (line.Contains("//")) dv = 0; // ei ole texindexei

                        line = line.Replace("//", " ");
                        line = line.Replace("/", " ");
                        string[] _ln = line.Split(' ');

                        if (dv == 0 || dv == 3) // luultavasti nyt ei ole texturecoordinaatteja
                        {
                            mesh._vertexInd.Add(Int32.Parse(_ln[1]) - 1);
                            mesh._vertexInd.Add(Int32.Parse(_ln[3]) - 1);
                            mesh._vertexInd.Add(Int32.Parse(_ln[5]) - 1);

                            mesh._normalInd.Add(Int32.Parse(_ln[2]) - 1);
                            mesh._normalInd.Add(Int32.Parse(_ln[4]) - 1);
                            mesh._normalInd.Add(Int32.Parse(_ln[6]) - 1);
                        }
                        else // kaikki mukana
                        {
                            mesh._vertexInd.Add(Int32.Parse(_ln[1]) - 1);
                            mesh._vertexInd.Add(Int32.Parse(_ln[4]) - 1);
                            mesh._vertexInd.Add(Int32.Parse(_ln[7]) - 1);

                            mesh._uvInd.Add(Int32.Parse(_ln[2]) - 1);
                            mesh._uvInd.Add(Int32.Parse(_ln[5]) - 1);
                            mesh._uvInd.Add(Int32.Parse(_ln[8]) - 1);

                            mesh._normalInd.Add(Int32.Parse(_ln[3]) - 1);
                            mesh._normalInd.Add(Int32.Parse(_ln[6]) - 1);
                            mesh._normalInd.Add(Int32.Parse(_ln[9]) - 1);
                        }
                        continue;
                    }

                    // materiaalitiedosto
                    if (ln[0] == "mtllib")
                    {
                        try
                        {
                            // ladataan objektille materiaalitiedot (mesheille otetaan talteen materialname joka viittaa sitten näihin materiaaleihin)
                            material = new Material();
                            material.Load(dir + ln[1], Texture.LoadTextures);
                        }
                        catch (Exception e)
                        {
                            Log.WriteDebugLine(e.ToString());
                        }
                    }
                }

                if (mesh != null) meshes.Add(mesh);

                // pathille ei luoda objektia, se on vain kasa vertexejä
                if (path == false)
                {
                    int cc = 0;

                    vertices = new Vertex[numOfFaces * 3];
                    for (int m = 0; m < meshes.Count; m++)
                    {
                        meshes[m].vertices = new Vertex[meshes[m]._vertexInd.Count];

                        for (int q = 0; q < meshes[m]._vertexInd.Count; q++)
                        {
                            // mesh datat
                            meshes[m].vertices[q].vertex = _vertex[meshes[m]._vertexInd[q]];
                            meshes[m].vertices[q].normal = _normal[meshes[m]._normalInd[q]];
                            if (meshes[m]._uvInd.Count != 0)
                                meshes[m].vertices[q].uv_or_color = new Vector4(_uv[meshes[m]._uvInd[q]].X, _uv[meshes[m]._uvInd[q]].Y,
                                                                                _uv[meshes[m]._uvInd[q]].X, _uv[meshes[m]._uvInd[q]].Y);

                            // pistetään myös objektille kaikki vertexit yhteen klimppiin.

            //TODO Miks? vie vaa muistia nii paljo, mesheissä kumminki nuo datat säilytetään.
            // jos tää on VAIN collisionia varten, siihe ny o helppo tehdä se et se menee objektin puun läpi
            // ni sit ei tartte tätä
                            vertices[cc].vertex = _vertex[meshes[m]._vertexInd[q]];
                            vertices[cc].normal = _normal[meshes[m]._normalInd[q]];
                            if (meshes[m]._uvInd.Count != 0)
                                vertices[cc].uv_or_color = new Vector4(_uv[meshes[m]._uvInd[q]].X, _uv[meshes[m]._uvInd[q]].Y,
                                                                                _uv[meshes[m]._uvInd[q]].X, _uv[meshes[m]._uvInd[q]].Y);
                            cc++;
                        }

                        // index taulukko
                        meshes[m].indices = new int[meshes[m]._vertexInd.Count];
                        for (int q = 0; q < meshes[m]._vertexInd.Count; q++) meshes[m].indices[q] = q;

                        meshes[m].vbo = new VBO();
                        meshes[m].vbo.DataToVBO(meshes[m].vertices, meshes[m].indices);

                        // meshin bounding volume
                        meshes[m].Boundings = new BoundingVolume();
                        meshes[m].Boundings.CreateBoundingVolume(meshes[m]);

                        // lataa glsl koodit
                        string shader = material.GetMaterial(meshes[m].MaterialName).ShaderName;
                        if (shader != "")
                        {
                            mesh.Shader = new GLSL();
                            mesh.Shader.Load(shader + ".vert", shader + ".frag");
                        }
                        if (material.GetMaterial(meshes[m].MaterialName).Dissolve < 1.0f) IsTranslucent = true;

                    }

                    // koko objektin bounding volume
                    IsRendObj = false; // childeissä rendattavat objektit, tässä ei ole rendattavaa, vain paikka
                    Boundings = new BoundingVolume();
                    Boundings.CreateBoundingVolume(this);

                    // lisätään objektille meshit childeiks
                    for (int q = 0; q < meshes.Count; q++)
                    {
                        Add(meshes[q]);
                    }

                    Log.WriteDebugLine("Object: " + Name + "  meshes: " + meshes.Count);
                }

                _vertex.Clear();
                _normal.Clear();
                _uv.Clear();
                for (int q = 0; q < meshes.Count; q++)
                {
                    meshes[q]._vertexInd.Clear();
                    meshes[q]._normalInd.Clear();
                    meshes[q]._uvInd.Clear();
                }

            }
        }
        /// <summary>
        /// lataa md5-animaatio.
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="anim"></param>
        public override void LoadAnim(string animName, string fileName)
        {
            if (fileName == null || fileName == "")
            {
                return;
            }

            Animation anim = new Animation();

            anim.animName = animName;

            Buffer t = new Buffer();

            MD5JointInfo[]      jointInfos    = null;
            MD5BaseFrameJoint[] baseFrame     = null;
            float[]             animFrameData = null;
            int numAnimatedComponents         = 0;
            int frame_index;
            int i;

            using (System.IO.StreamReader file = new System.IO.StreamReader(Settings.DataDir + fileName))
            {
                string line;
                while ((line = file.ReadLine()) != null)
                {
                    if (line == "")
                    {
                        continue;
                    }

                    // Read number of joints
                    if (ParseLine(ref t, line, "numFrames %d"))
                    {
                        /* Allocate memory for skeleton frames and bounding boxes */
                        anim.numFrames = t.ibuffer[0];
                        if (anim.numFrames > 0)
                        {
                            anim.bboxes = new MD5BoundingBox[anim.numFrames];
                        }
                    }

                    if (ParseLine(ref t, line, "numJoints %d"))
                    {
                        /* Allocate memory for joints of each frame */
                        anim.numJoints = t.ibuffer[0];
                        if (anim.numJoints > 0)
                        {
                            /* Allocate temporary memory for building skeleton frames */
                            jointInfos = new MD5JointInfo[anim.numJoints];
                            baseFrame  = new MD5BaseFrameJoint[anim.numJoints];
                        }
                        anim.skelFrames = new MD5Joint[anim.numFrames, anim.numJoints];
                    }

                    if (ParseLine(ref t, line, "frameRate %d"))
                    {
                        anim.frameRate = t.ibuffer[0];
                    }

                    if (ParseLine(ref t, line, "numAnimatedComponents %d"))
                    {
                        numAnimatedComponents = t.ibuffer[0];
                        if (numAnimatedComponents > 0)
                        {
                            /* Allocate memory for animation frame data */
                            animFrameData = new float[numAnimatedComponents];
                        }
                    }

                    if (line.Equals("hierarchy {"))
                    {
                        for (i = 0; i < anim.numJoints; ++i)
                        {
                            /* Read whole line */
                            line = file.ReadLine();
                            Cleanstring(ref line);

                            /* Read joint info */
                            ParseLine(ref t, line, "%s %d %d %d");
                            jointInfos[i].name       = t.sbuffer;
                            jointInfos[i].parent     = t.ibuffer[0];
                            jointInfos[i].flags      = t.ibuffer[1];
                            jointInfos[i].startIndex = t.ibuffer[2];
                        }
                    }

                    if (line.Equals("bounds {"))
                    {
                        for (i = 0; i < anim.numFrames; ++i)
                        {
                            /* Read whole line */
                            line = file.ReadLine();
                            Cleanstring(ref line);

                            /* Read bounding box */
                            ParseLine(ref t, line, "( %f %f %f ) ( %f %f %f )");
                            anim.bboxes[i].min.X = t.fbuffer[0];
                            anim.bboxes[i].min.Y = t.fbuffer[1];
                            anim.bboxes[i].min.Z = t.fbuffer[2];
                            anim.bboxes[i].max.X = t.fbuffer[3];
                            anim.bboxes[i].max.Y = t.fbuffer[4];
                            anim.bboxes[i].max.Z = t.fbuffer[5];
                        }
                    }

                    if (line.Equals("baseframe {"))
                    {
                        for (i = 0; i < anim.numJoints; ++i)
                        {
                            /* Read whole line */
                            line = file.ReadLine();
                            Cleanstring(ref line);

                            /* Read base frame joint */
                            ParseLine(ref t, line, "( %f %f %f ) ( %f %f %f )");

                            if (t.fbuffer.Length == 6)
                            {
                                baseFrame[i].pos.X    = t.fbuffer[0];
                                baseFrame[i].pos.Y    = t.fbuffer[1];
                                baseFrame[i].pos.Z    = t.fbuffer[2];
                                baseFrame[i].orient.X = t.fbuffer[3];
                                baseFrame[i].orient.Y = t.fbuffer[4];
                                baseFrame[i].orient.Z = t.fbuffer[5];

                                /* Compute the w component */
                                MathExt.ComputeW(ref baseFrame[i].orient);
                            }
                        }
                    }

                    if (ParseLine(ref t, line, "frame %d"))
                    {
                        frame_index = t.ibuffer[0];

                        /* Read frame data */
                        for (i = 0; i < numAnimatedComponents;)
                        {
                            line = file.ReadLine();
                            if (line[0] == '}')
                            {
                                break;
                            }
                            Cleanstring(ref line);
                            string[] splt = line.Split(' ');

                            for (int ww = 0; ww < splt.Length; ww++)
                            {
                                animFrameData[i++] = float.Parse(splt[ww]);
                            }
                        }

                        /* Build frame skeleton from the collected data */
                        BuildFrameSkeleton(ref jointInfos, ref baseFrame, ref animFrameData, frame_index, anim.numJoints, ref anim);
                    }
                }

                anim.curFrame  = 0;
                anim.nextFrame = 1;

                anim.lastTime = 0;
                anim.maxTime  = 1.0f / anim.frameRate;

                /* Allocate memory for animated skeleton */
                skeleton = new MD5Joint[anim.numJoints];
                animated = true;

                Vector3 min = new Vector3(9999, 9999, 9999);
                Vector3 max = new Vector3(-9999, -9999, -9999);

                // laske bboxit
                for (int q = 0; q < anim.numFrames; q++)
                {
                    if (anim.bboxes[q].min.X < min.X)
                    {
                        min.X = anim.bboxes[q].min.X;
                    }
                    if (anim.bboxes[q].min.Y < min.Y)
                    {
                        min.Y = anim.bboxes[q].min.Y;
                    }
                    if (anim.bboxes[q].min.Z < min.Z)
                    {
                        min.Z = anim.bboxes[q].min.Z;
                    }

                    if (anim.bboxes[q].max.X > max.X)
                    {
                        max.X = anim.bboxes[q].max.X;
                    }
                    if (anim.bboxes[q].max.Y > max.Y)
                    {
                        max.Y = anim.bboxes[q].max.Y;
                    }
                    if (anim.bboxes[q].max.Z > max.Z)
                    {
                        max.Z = anim.bboxes[q].max.Z;
                    }
                }

                Boundings = new BoundingVolume();
                Boundings.CreateBoundingVolume(this, min, max);

                Update(0);
                animations.Add(anim);

                Log.WriteDebugLine("Animation: " + fileName);

                UseAnimation(animName);
            }
        }