Пример #1
0
 public Vertex sub(Vertex other)
 {
     return new Vertex(this.x.theValue - other.x.theValue, this.y.theValue - other.y.theValue, this.z.theValue - other.z.theValue);
 }
Пример #2
0
        //For dealing with type Vertex
        public int add(Vertex v)
        {
            int min_ix = (int)((v.x.theValue - this.threshold) / this.cell_width);
            int min_iy = (int)((v.y.theValue - this.threshold) / this.cell_width);
            int min_iz = (int)((v.z.theValue - this.threshold) / this.cell_width);
            int max_ix = (int)((v.x.theValue + this.threshold) / this.cell_width);
            int max_iy = (int)((v.y.theValue + this.threshold) / this.cell_width);
            int max_iz = (int)((v.z.theValue + this.threshold) / this.cell_width);

            for (int ix = min_ix; ix < max_ix + 1; ix++)
            {
                for (int iy = min_iy; iy < max_iy + 1; iy++)
                {
                    for (int iz = min_iz; iz < max_iz + 1; iz++)
                    {
                        foreach (int index in this.buckets[(int)this.vertex_hash(ix, iy, iz)])
                        {
                            if (v.sub(this.vertices[index]).norm_sq() < this.threshold * this.threshold)
                                return index;
                        }
                    }
                }
            }

            this.vertices.Add(v);
            this.buckets[(int)this.vertex_hash((int)(v.x.theValue / this.cell_width), (int)(v.y.theValue / this.cell_width),
                (int)(v.z.theValue / this.cell_width))].Add(this.vertices.Count - 1);
            return (this.vertices.Count - 1);
        }
Пример #3
0
 public Vertex iadd(Vertex other)
 {
     this.x.theValue += other.x.theValue;
     this.y.theValue += other.y.theValue;
     this.z.theValue += other.z.theValue;
     return this;
 }
Пример #4
0
 public Vertex isub(Vertex other)
 {
     this.x.theValue -= other.x.theValue;
     this.y.theValue -= other.y.theValue;
     this.z.theValue -= other.z.theValue;
     return this;
 }
Пример #5
0
 public Triangle(Vertex u, Vertex v, Vertex w, int group)
 {
     this.u = u;
     this.v = v;
     this.w = w;
     this.n = KCLWriter.unit(KCLWriter.cross(v.sub(u), w.sub(u)));
     this.group = group;
 }
Пример #6
0
 public Vertex add(Vertex other)
 {
     return new Vertex(this.x.theValue + other.x.theValue, this.y.theValue + other.y.theValue, this.z.theValue + other.z.theValue);
 }
Пример #7
0
        //Base octree constructor
        public Octree(List<Triangle> triangles, int max_triangles, float min_width)
        {
            this.triangles = triangles;
            this.max_triangles = max_triangles;
            this.min_width = min_width;

            float min_x = 0, min_y = 0, min_z = 0, max_x = 0, max_y = 0, max_z = 0;

            foreach (Triangle t in triangles)
            {
                float min_x0 = KCLWriter.min(KCLWriter.min(t.u.x.theValue, t.v.x.theValue, t.w.x.theValue));
                if (min_x0 < min_x) min_x = min_x0;
                float min_y0 = KCLWriter.min(KCLWriter.min(t.u.y.theValue, t.v.y.theValue, t.w.y.theValue));
                if (min_y0 < min_y) min_y = min_y0;
                float min_z0 = KCLWriter.min(KCLWriter.min(t.u.z.theValue, t.v.z.theValue, t.w.z.theValue));
                if (min_z0 < min_z) min_z = min_z0;
                float max_x0 = KCLWriter.max(KCLWriter.max(t.u.x.theValue, t.v.x.theValue, t.w.x.theValue));
                if (max_x0 > max_x) max_x = max_x0;
                float max_y0 = KCLWriter.max(KCLWriter.max(t.u.y.theValue, t.v.y.theValue, t.w.y.theValue));
                if (max_y0 > max_y) max_y = max_y0;
                float max_z0 = KCLWriter.max(KCLWriter.max(t.u.z.theValue, t.v.z.theValue, t.w.z.theValue));
                if (max_z0 > max_z) max_z = max_z0;
            }

            // If model only uses two axes, eg. flat square, the base width will get set to min_width (1) which can
            // create an octree with 100's of thousands of tiny empty or almost empty nodes is very computationally expensive
            if (max_x == 0)
                max_x = KCLWriter.max(max_y, max_z);
            if (max_y == 0)
                max_y = KCLWriter.max(max_x, max_z);
            if (max_z == 0)
                max_z = KCLWriter.max(max_x, max_y);

            this.width_x = (float)Math.Pow(2, (int)(Math.Ceiling(Math.Log(KCLWriter.max(max_x - min_x, min_width), 2))));
            this.width_y = (float)Math.Pow(2, (int)(Math.Ceiling(Math.Log(KCLWriter.max(max_y - min_y, min_width), 2))));
            this.width_z = (float)Math.Pow(2, (int)(Math.Ceiling(Math.Log(KCLWriter.max(max_z - min_z, min_width), 2))));
            this.base_width = KCLWriter.min(width_x, width_y, width_z);
            this.bas = new Vertex(min_x, min_y, min_z);

            this.nx = (int)Math.Floor(this.width_x / this.base_width);
            this.ny = (int)Math.Floor(this.width_y / this.base_width);
            this.nz = (int)Math.Floor(this.width_z / this.base_width);

            List<int> ind = new List<int>();
            for (int i = 0; i < triangles.Count; i++)
                ind.Add(i);

            for (int k = 0; k < this.nz; k++)
            {
                for (int j = 0; j < this.ny; j++)
                {
                    for (int i = 0; i < this.nx; i++)
                    {
                        this.children.Add(new Octree(this.bas.add((new Vertex(i, j, k)).mul(this.base_width)), this.base_width,
                            ind, this.triangles, this.max_triangles, this.min_width));
                    }
                }
            }
        }
Пример #8
0
        //Constructor for creating nodes in the octree
        public Octree(Vertex bas, float width, List<int> indices, List<Triangle> triangles, int max_triangles, float min_width)
        {
            Vertex centre = bas.add(new Vertex(width, width, width).truediv(2f));
            this.triangles = triangles;
            this.max_triangles = max_triangles;
            this.min_width = min_width;

            this.width_x /= 2f;
            this.width_y /= 2f;
            this.width_z /= 2f;
            this.base_width = KCLWriter.min(width_x, width_y, width_z);
            this.bas = new Vertex(width / 2f, width / 2f, width / 2f);

            foreach (int i in indices)
            {
                if (KCLWriter.tribox_overlap(this.triangles[i], centre, width / 2f))
                {
                    this.indices.Add(i);
                }
            }
            this.is_leaf = true;

            //Console.WriteLine("node hw: " + width / 2f + " num of indices: " + this.indices.Count);

            if (this.indices.Count > this.max_triangles && width >= (2 * this.min_width))
            {
                for (int k = 0; k < 2; k++)
                {
                    for (int j = 0; j < 2; j++)
                    {
                        for (int i = 0; i < 2; i++)
                        {
                            this.children.Add(new Octree(bas.add(new Vertex((float)i, (float)j, (float)k).truediv(2f).mul(width)), width / 2,
                                    this.indices, this.triangles, this.max_triangles, this.min_width));
                        }
                    }
                }
                this.indices.Clear();
                this.is_leaf = false;
            }
        }
Пример #9
0
        private static List<Triangle> readLoadedModel(ModelBase model, float faceSizeThreshold, Dictionary<string, int> matColTypes)
        {
            List<Triangle> triangles = new List<Triangle>();

            foreach (ModelBase.BoneDef bone in model.m_BoneTree)
            {
                foreach (ModelBase.GeometryDef geometry in bone.m_Geometries.Values)
                {
                    foreach (ModelBase.PolyListDef polyList in geometry.m_PolyLists.Values)
                    {
                        string material = polyList.m_MaterialName;

                        foreach (ModelBase.FaceListDef faceList in polyList.m_FaceLists)
                        {
                            foreach (ModelBase.FaceDef face in faceList.m_Faces)
                            {
                                if (face.m_NumVertices == 3)
                                {
                                    Vertex u = new Vertex(
                                        face.m_Vertices[0].m_Position.X, face.m_Vertices[0].m_Position.Y, face.m_Vertices[0].m_Position.Z);
                                    Vertex v = new Vertex(
                                        face.m_Vertices[1].m_Position.X, face.m_Vertices[1].m_Position.Y, face.m_Vertices[1].m_Position.Z);
                                    Vertex w = new Vertex(
                                        face.m_Vertices[2].m_Position.X, face.m_Vertices[2].m_Position.Y, face.m_Vertices[2].m_Position.Z);

                                    //Below line gets rid of faces that are too small, original 0.001
                                    if (cross(v.sub(u), w.sub(u)).norm_sq() < faceSizeThreshold) { continue; } //#TODO: find a better solution
                                    triangles.Add(new Triangle(u, v, w, matColTypes[material]));
                                }
                                else if (face.m_NumVertices == 4)
                                {
                                    Vertex u1 = new Vertex(
                                        face.m_Vertices[0].m_Position.X, face.m_Vertices[0].m_Position.Y, face.m_Vertices[0].m_Position.Z);
                                    Vertex v1 = new Vertex(
                                        face.m_Vertices[1].m_Position.X, face.m_Vertices[1].m_Position.Y, face.m_Vertices[1].m_Position.Z);
                                    Vertex w1 = new Vertex(
                                        face.m_Vertices[3].m_Position.X, face.m_Vertices[3].m_Position.Y, face.m_Vertices[3].m_Position.Z);

                                    //Below line gets rid of faces that are too small, original 0.001
                                    if (cross(v1.sub(u1), w1.sub(u1)).norm_sq() < faceSizeThreshold) { continue; } //#TODO: find a better solution
                                    triangles.Add(new Triangle(u1, v1, w1, matColTypes[material]));

                                    Vertex u2 = new Vertex(
                                        face.m_Vertices[1].m_Position.X, face.m_Vertices[1].m_Position.Y, face.m_Vertices[1].m_Position.Z);
                                    Vertex v2 = new Vertex(
                                        face.m_Vertices[2].m_Position.X, face.m_Vertices[2].m_Position.Y, face.m_Vertices[2].m_Position.Z);
                                    Vertex w2 = new Vertex(
                                        face.m_Vertices[3].m_Position.X, face.m_Vertices[3].m_Position.Y, face.m_Vertices[3].m_Position.Z);

                                    //Below line gets rid of faces that are too small, original 0.001
                                    if (cross(v2.sub(u2), w2.sub(u2)).norm_sq() < faceSizeThreshold) { continue; } //#TODO: find a better solution
                                    triangles.Add(new Triangle(u2, v2, w2, matColTypes[material]));
                                }
                            }
                        }
                    }
                }
            }

            return triangles;
        }
Пример #10
0
        public static bool tribox_overlap(Triangle triangle, Vertex centre, float half_width)
        {
            /*Intersection test for triangle and axis-aligned cube.

              Test if the triangle  intersects the axis-aligned cube given by the center
              and half width. This algorithm is an adapted version of the algorithm
              presented here:
              http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/tribox3.txt
            */

            Vertex u = triangle.u.sub(centre);
            Vertex v = triangle.v.sub(centre);
            Vertex w = triangle.w.sub(centre);
            Vector n = triangle.n;

            // Test for separation along the axes normal to the faces of the cube

            if (max(u.x.theValue, v.x.theValue, w.x.theValue) < -half_width || min(u.x.theValue, v.x.theValue, w.x.theValue) > half_width) return false;
            if (max(u.y.theValue, v.y.theValue, w.y.theValue) < -half_width || min(u.y.theValue, v.y.theValue, w.y.theValue) > half_width) return false;
            if (max(u.z.theValue, v.z.theValue, w.z.theValue) < -half_width || min(u.z.theValue, v.z.theValue, w.z.theValue) > half_width) return false;

            // Test for separation along the axis normal to the face of the triangle

            float d = dot(n, u);
            float r = half_width * (Math.Abs(n.x.theValue) + Math.Abs(n.y.theValue) + Math.Abs(n.z.theValue));
            if (d < -r || d > r) return false;

            // Test for separation along the axes parallel to the cross products of the
            // edges of the triangle and the edges of the cube

            if (edge_test(u, v, w, half_width)) return false;
            if (edge_test(v, w, u, half_width)) return false;
            if (edge_test(w, u, v, half_width)) return false;

            // Triangle and cube intersects
            return true;
        }
Пример #11
0
 public static bool edge_test(Vertex v0, Vertex v1, Vertex v2, float hw)
 {
     Vertex e = v1.sub(v0);
     if (edge_axis_test(e.z.theValue, -e.y.theValue, v0.y.theValue, v0.z.theValue, v2.y.theValue, v2.z.theValue, hw))
         return true;
     if (edge_axis_test(-e.z.theValue, e.x.theValue, v0.x.theValue, v0.z.theValue, v2.x.theValue, v2.z.theValue, hw))
         return true;
     if (edge_axis_test(e.y.theValue, -e.x.theValue, v0.x.theValue, v0.y.theValue, v2.x.theValue, v2.y.theValue, hw))
         return true;
     return false;
 }
Пример #12
0
 public static float dot(Vertex a, Vector b)
 {
     return a.x.theValue * b.x.theValue + a.y.theValue * b.y.theValue + a.z.theValue * b.z.theValue;
 }
Пример #13
0
 //Vertex, Vector > Vector
 public static Vector cross(Vertex a, Vector b)
 {
     return new Vector(a.y.theValue * b.z.theValue - a.z.theValue * b.y.theValue, a.z.theValue * b.x.theValue - a.x.theValue * b.z.theValue,
         a.x.theValue * b.y.theValue - a.y.theValue * b.x.theValue);
 }