Exemplo n.º 1
0
        public RaycastResult?Raycast(Vector3 start, Vector3 dir)
        {
            float   tFirst    = (float)double.PositiveInfinity;
            Vector3?currPoint = null;
            Vector3?currNorm  = null;

            foreach (OctreeNode octbox in OctreeNode.m_List)
            {
                //The condition glitches at times and since a stage model has less than
                //about 2500 polygons, it's not worth fixing right now.
                if (true /*octbox.IntersectsRay(ref start, ref dir)*/)
                {
                    for (int i = 0; i < octbox.m_PlaneList.Count; ++i)
                    {
                        if (octbox.m_PlaneList[i] >= m_Planes.Count)
                        {
                            continue;
                        }
                        ColFace tri = m_Planes[octbox.m_PlaneList[i]];

                        //Find point of intersection
                        float dot = Vector3.Dot(tri.normal, dir);
                        if (dot >= 0)
                        {
                            continue;           //Either they don't intersect or they graze. No grazes allowed here!
                        }
                        float t = Vector3.Dot(tri.normal, tri.point1 - start) / dot;
                        if (t < 0 || t > 1 || t >= tFirst)
                        {
                            continue;                                //Nope! Gotta hit the plane! (or too far back)
                        }
                        //Find out if the intersection point is inside the triangle.
                        Vector3 intersection  = dir * t + start;
                        Vector3 basisX        = tri.point2 - tri.point1,
                                basisY        = tri.point3 - tri.point1,
                                intFromPoint1 = intersection - tri.point1;

                        //OpenTK got rid of a function that multiplies a matrix3 by a vector3
                        Matrix3 planeBasis = new Matrix3(basisX.X, basisY.X, tri.normal.X,
                                                         basisX.Y, basisY.Y, tri.normal.Y,
                                                         basisX.Z, basisY.Z, tri.normal.Z).Inverted();
                        Vector3 resultant = planeBasis.Column0 * intFromPoint1.X +
                                            planeBasis.Column1 * intFromPoint1.Y +
                                            planeBasis.Column2 * intFromPoint1.Z;

                        if (resultant.X >= 0 && resultant.Y >= 0 && (resultant.X + resultant.Y) <= 1)
                        {
                            currPoint = intersection;
                            currNorm  = tri.normal;
                            tFirst    = t;
                        }
                    }
                }
            }

            return(currPoint != null ? (RaycastResult?)new RaycastResult((Vector3)currPoint, (Vector3)currNorm, tFirst) : null);
        }
Exemplo n.º 2
0
        public KCL(NitroFile file)
        {
            m_File = file;

            m_Planes = new List <ColFace>();

            m_PointsSectionOffset  = m_File.Read32(0x00);
            m_NormalsSectionOffset = m_File.Read32(0x04);
            m_PlanesSectionOffset  = m_File.Read32(0x08);
            m_OctreeSectionOffset  = m_File.Read32(0x0C);

            int planeid = 0;

            for (uint offset = m_PlanesSectionOffset + 0x10; offset < m_OctreeSectionOffset; offset += 0x10)
            {
                uint length = m_File.Read32(offset);

                ushort pt_id = m_File.Read16(offset + 0x04);
                int    pt_x  = (int)m_File.Read32((uint)(m_PointsSectionOffset + (pt_id * 12)));
                int    pt_y  = (int)m_File.Read32((uint)(m_PointsSectionOffset + (pt_id * 12) + 4));
                int    pt_z  = (int)m_File.Read32((uint)(m_PointsSectionOffset + (pt_id * 12) + 8));

                ushort nr_id = m_File.Read16(offset + 0x06);
                short  nr_x  = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (nr_id * 6)));
                short  nr_y  = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (nr_id * 6) + 2));
                short  nr_z  = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (nr_id * 6) + 4));

                ushort d1_id = m_File.Read16(offset + 0x08);
                short  d1_x  = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d1_id * 6)));
                short  d1_y  = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d1_id * 6) + 2));
                short  d1_z  = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d1_id * 6) + 4));

                ushort d2_id = m_File.Read16(offset + 0x0A);
                short  d2_x  = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d2_id * 6)));
                short  d2_y  = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d2_id * 6) + 2));
                short  d2_z  = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d2_id * 6) + 4));

                ushort d3_id = m_File.Read16(offset + 0x0C);
                short  d3_x  = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d3_id * 6)));
                short  d3_y  = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d3_id * 6) + 2));
                short  d3_z  = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d3_id * 6) + 4));

                ColFace plane = new ColFace((float)(length / 65536000f),
                                            new Vector3((float)pt_x / 64000f, (float)pt_y / 64000f, (float)pt_z / 64000f),
                                            new Vector3((float)nr_x / 1024f, (float)nr_y / 1024f, (float)nr_z / 1024f),
                                            new Vector3((float)d1_x / 1024f, (float)d1_y / 1024f, (float)d1_z / 1024f),
                                            new Vector3((float)d2_x / 1024f, (float)d2_y / 1024f, (float)d2_z / 1024f),
                                            new Vector3((float)d3_x / 1024f, (float)d3_y / 1024f, (float)d3_z / 1024f),
                                            m_File.Read16(offset + 0x0E));

                /* if (planeid == 31)
                 *   MessageBox.Show(string.Format("PLANE 32:\n{0}\n{1}\n{2}\n\n{3}\n{4}\n{5}\n\n{6}\n{7}\n{8}\n{9}\n{10}\n{11}",
                 *       d1_x, d1_y, d1_z,
                 *       d2_x, d2_y, d2_z,
                 *       plane.m_Position, plane.m_Normal, plane.m_Dir1, plane.m_Dir2, plane.m_Dir3, plane.m_Length));*/

                planeid++;

                /* if (Math.Abs(plane.m_Dir1.Length - 1f) > 0.0001f || Math.Abs(plane.m_Dir2.Length - 1f) > 0.0001f ||
                 *   Math.Abs(plane.m_Dir3.Length - 1f) > 0.0001f || Math.Abs(plane.m_Normal.Length - 1f) > 0.0001f ||
                 *   plane.m_Length < 0f)
                 *   MessageBox.Show(string.Format("WRONG PLANE | {0} | {1} | {2} | {3} | {4}",
                 *       plane.m_Dir1.Length, plane.m_Dir2.Length, plane.m_Dir3.Length, plane.m_Normal.Length, plane.m_Length));
                 *
                 * if (plane.m_Dir1.Length < 0.001f || plane.m_Dir2.Length < 0.001f ||
                 *   plane.m_Dir3.Length < 0.001f || plane.m_Normal.Length < 0.001f ||
                 *   Math.Abs(plane.m_Length) < 0.001f)
                 *   MessageBox.Show(string.Format("ZERO PLANE | {0} | {1} | {2} | {3} | {4}",
                 *       plane.m_Dir1.Length, plane.m_Dir2.Length, plane.m_Dir3.Length, plane.m_Normal.Length, plane.m_Length));
                 *
                 * Vector3 lol1 = Vector3.Cross(plane.m_Dir1, plane.m_Normal);
                 * float lol1len = plane.m_Length / (float)Math.Cos(Math.Acos(Math.Min(1f,Vector3.Dot(lol1, plane.m_Dir3))));
                 * Vector3 lol2 = Vector3.Cross(plane.m_Normal, plane.m_Dir2);
                 * float lol2len = plane.m_Length / (float)Math.Cos(Math.Acos(Math.Min(1f,Vector3.Dot(lol2, plane.m_Dir3))));
                 * if (Helper.VectorsEqual(plane.m_Position, Vector3.Multiply(lol1, lol1len)) ||
                 *   Helper.VectorsEqual(plane.m_Position, Vector3.Multiply(lol2, lol2len)))
                 *   MessageBox.Show(string.Format("WEIRD PLANE {5:X8} | {0} | {1} | {2} | {3} | {4}\n{6} | {7} / cos(acos({8})) = cos({9}) = {10}",
                 *       plane.m_Dir1, plane.m_Dir2, plane.m_Dir3, plane.m_Normal, plane.m_Length,
                 *       offset, lol2, plane.m_Length, Vector3.Dot(lol2, plane.m_Dir3), Math.Acos(Vector3.Dot(lol2, plane.m_Dir3)), Math.Cos(Math.Acos(Vector3.Dot(lol2, plane.m_Dir3)))));
                 */
                m_Planes.Add(plane);
            }

            OctreeNode.maxkids = 0;
            int     shift       = (int)m_File.Read32(0x2C);
            Vector3 octreestart = new Vector3((float)(int)m_File.Read32(0x14) / 64000f, (float)(int)m_File.Read32(0x18) / 64000f, (float)(int)m_File.Read32(0x1C) / 64000f);
            float   _cubesize   = (float)(1 << shift) / 1024f;
            Vector3 cubesize    = new Vector3(_cubesize, _cubesize, _cubesize);
            Vector3 octreesize  = new Vector3((~m_File.Read32(0x20) >> shift) + 1, (~m_File.Read32(0x24) >> shift) + 1, (~m_File.Read32(0x28) >> shift) + 1);

            OctreeNode.m_List = new List <OctreeNode>();
            uint loloffset = m_OctreeSectionOffset;

            for (int z = 0; z < octreesize.Z; z++)
            {
                for (int y = 0; y < octreesize.Y; y++)
                {
                    for (int x = 0; x < octreesize.X; x++)
                    {
                        new OctreeNode(m_File, m_OctreeSectionOffset, loloffset, octreestart + new Vector3(cubesize.X * x, cubesize.Y * y, cubesize.Z * z), cubesize); loloffset += 4;
                    }
                }
            }

            //MessageBox.Show(OctreeNode.m_List.Count.ToString());
        }
Exemplo n.º 3
0
        public KCL(NitroFile file)
        {
            m_File = file;

            m_Planes = new List<ColFace>();

            m_PointsSectionOffset = m_File.Read32(0x00);
            m_NormalsSectionOffset = m_File.Read32(0x04);
            m_PlanesSectionOffset = m_File.Read32(0x08);
            m_OctreeSectionOffset = m_File.Read32(0x0C);

            int planeid = 0;
            for (uint offset = m_PlanesSectionOffset + 0x10; offset < m_OctreeSectionOffset; offset += 0x10)
            {
                uint length = m_File.Read32(offset);

                ushort pt_id = m_File.Read16(offset + 0x04);
                int pt_x = (int)m_File.Read32((uint)(m_PointsSectionOffset + (pt_id*12)    ));
                int pt_y = (int)m_File.Read32((uint)(m_PointsSectionOffset + (pt_id*12) + 4));
                int pt_z = (int)m_File.Read32((uint)(m_PointsSectionOffset + (pt_id*12) + 8));

                ushort nr_id = m_File.Read16(offset + 0x06);
                short nr_x = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (nr_id*6)    ));
                short nr_y = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (nr_id*6) + 2));
                short nr_z = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (nr_id*6) + 4));

                ushort d1_id = m_File.Read16(offset + 0x08);
                short d1_x = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d1_id*6)    ));
                short d1_y = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d1_id*6) + 2));
                short d1_z = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d1_id*6) + 4));

                ushort d2_id = m_File.Read16(offset + 0x0A);
                short d2_x = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d2_id*6)    ));
                short d2_y = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d2_id*6) + 2));
                short d2_z = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d2_id*6) + 4));

                ushort d3_id = m_File.Read16(offset + 0x0C);
                short d3_x = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d3_id*6)    ));
                short d3_y = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d3_id*6) + 2));
                short d3_z = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d3_id*6) + 4));

                ColFace plane = new ColFace((float)(length / 65536000f),
                    new Vector3((float)pt_x / 64000f, (float)pt_y / 64000f, (float)pt_z / 64000f),
                    new Vector3((float)nr_x / 1024f, (float)nr_y / 1024f, (float)nr_z / 1024f),
                    new Vector3((float)d1_x / 1024f, (float)d1_y / 1024f, (float)d1_z / 1024f),
                    new Vector3((float)d2_x / 1024f, (float)d2_y / 1024f, (float)d2_z / 1024f),
                    new Vector3((float)d3_x / 1024f, (float)d3_y / 1024f, (float)d3_z / 1024f),
                    m_File.Read16(offset + 0x0E));

               /* if (planeid == 31)
                    MessageBox.Show(string.Format("PLANE 32:\n{0}\n{1}\n{2}\n\n{3}\n{4}\n{5}\n\n{6}\n{7}\n{8}\n{9}\n{10}\n{11}",
                        d1_x, d1_y, d1_z,
                        d2_x, d2_y, d2_z,
                        plane.m_Position, plane.m_Normal, plane.m_Dir1, plane.m_Dir2, plane.m_Dir3, plane.m_Length));*/

                planeid++;

               /* if (Math.Abs(plane.m_Dir1.Length - 1f) > 0.0001f || Math.Abs(plane.m_Dir2.Length - 1f) > 0.0001f ||
                    Math.Abs(plane.m_Dir3.Length - 1f) > 0.0001f || Math.Abs(plane.m_Normal.Length - 1f) > 0.0001f ||
                    plane.m_Length < 0f)
                    MessageBox.Show(string.Format("WRONG PLANE | {0} | {1} | {2} | {3} | {4}",
                        plane.m_Dir1.Length, plane.m_Dir2.Length, plane.m_Dir3.Length, plane.m_Normal.Length, plane.m_Length));

                if (plane.m_Dir1.Length < 0.001f || plane.m_Dir2.Length < 0.001f ||
                    plane.m_Dir3.Length < 0.001f || plane.m_Normal.Length < 0.001f ||
                    Math.Abs(plane.m_Length) < 0.001f)
                    MessageBox.Show(string.Format("ZERO PLANE | {0} | {1} | {2} | {3} | {4}",
                        plane.m_Dir1.Length, plane.m_Dir2.Length, plane.m_Dir3.Length, plane.m_Normal.Length, plane.m_Length));

                Vector3 lol1 = Vector3.Cross(plane.m_Dir1, plane.m_Normal);
                float lol1len = plane.m_Length / (float)Math.Cos(Math.Acos(Math.Min(1f,Vector3.Dot(lol1, plane.m_Dir3))));
                Vector3 lol2 = Vector3.Cross(plane.m_Normal, plane.m_Dir2);
                float lol2len = plane.m_Length / (float)Math.Cos(Math.Acos(Math.Min(1f,Vector3.Dot(lol2, plane.m_Dir3))));
                if (Helper.VectorsEqual(plane.m_Position, Vector3.Multiply(lol1, lol1len)) ||
                    Helper.VectorsEqual(plane.m_Position, Vector3.Multiply(lol2, lol2len)))
                    MessageBox.Show(string.Format("WEIRD PLANE {5:X8} | {0} | {1} | {2} | {3} | {4}\n{6} | {7} / cos(acos({8})) = cos({9}) = {10}",
                        plane.m_Dir1, plane.m_Dir2, plane.m_Dir3, plane.m_Normal, plane.m_Length,
                        offset, lol2, plane.m_Length, Vector3.Dot(lol2, plane.m_Dir3), Math.Acos(Vector3.Dot(lol2, plane.m_Dir3)), Math.Cos(Math.Acos(Vector3.Dot(lol2, plane.m_Dir3)))));
                */
                m_Planes.Add(plane);
            }

            OctreeNode.maxkids = 0;
            int shift = (int)m_File.Read32(0x2C);
            Vector3 octreestart = new Vector3((float)(int)m_File.Read32(0x14) / 64000f, (float)(int)m_File.Read32(0x18) / 64000f, (float)(int)m_File.Read32(0x1C) / 64000f);
            float _cubesize = (float)(1 << shift) / 1024f;
            Vector3 cubesize = new Vector3(_cubesize, _cubesize, _cubesize);
            Vector3 octreesize = new Vector3((~m_File.Read32(0x20) >> shift) + 1, (~m_File.Read32(0x24) >> shift) + 1, (~m_File.Read32(0x28) >> shift) + 1);
            OctreeNode.m_List = new List<OctreeNode>();
            uint loloffset = m_OctreeSectionOffset;
            for (int z = 0; z < octreesize.Z; z++)
                for (int y = 0; y < octreesize.Y; y++)
                    for (int x = 0; x < octreesize.X; x++)
                    { new OctreeNode(m_File, m_OctreeSectionOffset, loloffset, octreestart + new Vector3(cubesize.X * x, cubesize.Y * y, cubesize.Z * z), cubesize); loloffset += 4; }

            //MessageBox.Show(OctreeNode.m_List.Count.ToString());
        }