Example #1
0
        private static PolygonOctree FindBlock(KCLModel model, PolygonOctree[] children, int x, int y, int z, int blockIdx, uint shiftR)
        {
            model.HitOctrees.Add(children[blockIdx]);

            if (children[blockIdx].Children != null)
            {
                shiftR--;
                var childBlockIdx = ((x >> (int)shiftR) & 1) |
                                    4 * ((z >> (int)shiftR) & 1) |
                                    2 * ((y >> (int)shiftR) & 1);

                return(FindBlock(model, children[blockIdx].Children, x, y, z, childBlockIdx, shiftR));
            }
            else
            {
                return(children[blockIdx]);
            }
        }
Example #2
0
        internal static ushort[] searchBlock(KCLModel model, int x, int y, int z)
        {
            int blockIdx = 0;
            var shiftR   = model.CoordinateShift.X;

            if (model.CoordinateShift.Y == ushort.MaxValue && model.CoordinateShift.Z == ushort.MaxValue)
            {
                blockIdx = 0;
            }
            else
            {
                blockIdx = ((z >> (int)shiftR) << (int)model.CoordinateShift.Z) |
                           ((y >> (int)shiftR) << (int)model.CoordinateShift.Y) |
                           ((x >> (int)shiftR));
            }

            model.HitOctrees.Clear();
            model.HitOctrees.Add(model.PolygonOctreeRoots[blockIdx]);

            var octree = FindBlock(model, model.PolygonOctreeRoots, x, y, z, blockIdx, shiftR);

            return(octree.TriangleIndices.ToArray());
        }
        private void Read(BinaryDataReader reader)
        {
            ModelOctreeRoot          = new ModelOctreeNode();
            ModelOctreeRoot.Children = new ModelOctreeNode[ModelOctreeNode.ChildCount];
            Models = new List <KCLModel>();

            reader.ByteOrder = ByteOrder.BigEndian;
            uint value = reader.ReadUInt32();

            Version = (FileVersion)value;

            ByteOrder        = CheckByteOrder(reader);
            reader.ByteOrder = this.ByteOrder;

            if ((FileVersion)value != FileVersion.Version2) //Assume the KCL is V1 instead
            {
                if (value == 56)                            //Smaller header (GCN)
                {
                    Version = FileVersion.VersionGC;
                }
                else
                {
                    using (reader.TemporarySeek(56, SeekOrigin.Begin)) {
                        if (reader.ReadInt32() == 102400)
                        {
                            Version = FileVersion.VersionDS;
                        }
                        else
                        {
                            Version = FileVersion.VersionWII;
                        }
                    }
                }

                reader.Seek(-4); //Seek back and read V1 properly

                //V1 KCL is just a KCL model.
                KCLModel model = new KCLModel();
                model.Read(reader, Version);
                Models.Add(model);

                //Create default model octrees that index the first model
                for (int i = 0; i < ModelOctreeNode.ChildCount; i++)
                {
                    ModelOctreeRoot.Children[i] = new ModelOctreeNode()
                    {
                        ModelIndex = 0
                    };
                }

                PrismCount    = model.Prisms.Length;
                MinCoordinate = model.MinCoordinate;

                //Todo, auto generate the rest of V2 header data for V1 for cross conversion.
            }
            else
            {
                int octreeOffset           = reader.ReadInt32();
                int modelOffsetArrayOffset = reader.ReadInt32();
                int modelCount             = reader.ReadInt32();
                MinCoordinate   = reader.ReadVector3F();
                MaxCoordinate   = reader.ReadVector3F();
                CoordinateShift = reader.ReadVector3U();
                PrismCount      = reader.ReadInt32();

                reader.Position = octreeOffset; // Mostly unrequired, data is successive.
                for (int i = 0; i < ModelOctreeNode.ChildCount; i++)
                {
                    ModelOctreeRoot.Children[i] = new ModelOctreeNode(reader, (uint)octreeOffset);
                }

                // Read the model offsets.
                reader.Position = modelOffsetArrayOffset; // Mostly unrequired, data is successive.
                int[] modelOffsets = reader.ReadInt32s(modelCount);
                Models = new List <KCLModel>(modelCount);
                foreach (int modelOffset in modelOffsets)
                {
                    reader.Position = modelOffset; // Required as loading a model does not position reader at its end.
                    var model = new KCLModel();
                    model.Read(reader, Version);
                    Models.Add(model);
                }
            }
        }
Example #4
0
        internal static KCLHit CheckPoint(KCLModel model, Vector3 point, float thicknessScale, float pointDistance)
        {
            float maxDistance = model.PrismThickness * thicknessScale;

            int x = (int)(point.X - model.MinCoordinate.X) | 0;
            int y = (int)(point.Y - model.MinCoordinate.Y) | 0;
            int z = (int)(point.Z - model.MinCoordinate.Z) | 0;

            if ((x & model.CoordinateMask.X) != 0 || (y & model.CoordinateMask.Y) != 0 || (z & model.CoordinateMask.Z) != 0)
            {
                return(null);
            }

            float  smallestDist = float.MaxValue;
            KCLHit closestHit   = null;

            var prismIndices = searchBlock(model, x, y, z);

            for (int i = 0; i < prismIndices.Length; i++)
            {
                var prism = model.Prisms[prismIndices[i]];
                if (prism.Length <= 0.0f)
                {
                    continue;
                }

                var position = model.Positions[prism.PositionIndex];
                position = point - position; //Local coordinates
                var edgeNormal1 = model.Normals[prism.Normal1Index];
                if (Vector3.Dot(position, edgeNormal1) > 0)
                {
                    continue;
                }

                var edgeNormal2 = model.Normals[prism.Normal2Index];
                if (Vector3.Dot(position, edgeNormal2) > 0)
                {
                    continue;
                }

                var edgeNormal3 = model.Normals[prism.Normal3Index];
                if (Vector3.Dot(position, edgeNormal3) > prism.Length)
                {
                    continue;
                }

                var   faceNormal = model.Normals[prism.DirectionIndex];
                float dist       = -Vector3.Dot(faceNormal, point);
                // if (dist < 0.0f || dist > maxDistance)
                //     continue;

                if (dist < smallestDist)
                {
                    model.HitPrisms.Add(prism);
                    smallestDist = dist;

                    //Return with a proper hit with all checks passed.
                    closestHit = new KCLHit()
                    {
                        Prism    = prism,
                        Distance = dist,
                    };
                }
            }

            return(closestHit);
        }