internal float SampleField(ref Vector3 position)
        {
            Vector3  localPosition = position - m_translation;
            Vector3I samplePos;
            Vector2  pos = Vector2.Zero;

            MyCsgPrecomputedHelpres.CalculateSamplePosition(ref localPosition, out samplePos, ref pos, m_header.Resolution);
            return(GetValueForPosition(ref samplePos, ref pos, true));
        }
        private float GetValueForPosition(ref Vector3I samplePos, ref Vector2 pos, bool interpolate)
        {
            float value = 0.0f;

            if (interpolate)
            {
                float fx  = pos.X - samplePos.Y;
                float fy  = pos.Y - samplePos.Z;
                float fx1 = 1.0f - fx;
                float fy1 = 1.0f - fy;

                Vector2I newSamplePos = new Vector2I(samplePos.Y, samplePos.Z);

                ushort height;

                int newFacePosition = 0;

                GetHeightFromBatch(samplePos.X, newSamplePos.X, newSamplePos.Y, out height);
                value += height * (fx1 * fy1);

                newSamplePos.X = samplePos.Y + 1;
                newSamplePos.Y = samplePos.Z;

                newFacePosition = MyCsgPrecomputedHelpres.GetFaceForTexcoord(ref newSamplePos, samplePos.X, m_header.Resolution);
                GetHeightFromBatch(newFacePosition, newSamplePos.X, newSamplePos.Y, out height);
                value += height * (fx * fy1);

                newSamplePos.X = samplePos.Y;
                newSamplePos.Y = samplePos.Z + 1;

                if (newSamplePos.Y < m_header.Resolution)
                {
                    GetHeightFromBatch(samplePos.X, newSamplePos.X, newSamplePos.Y, out height);
                    value += height * (fx1 * fy);

                    newSamplePos.X = samplePos.Y + 1;

                    newFacePosition = MyCsgPrecomputedHelpres.GetFaceForTexcoord(ref newSamplePos, samplePos.X, m_header.Resolution);
                    GetHeightFromBatch(newFacePosition, newSamplePos.X, newSamplePos.Y, out height);
                    value += height * (fx * fy);
                }
            }
            else
            {
                ushort height;
                GetHeightFromBatch(samplePos.X, samplePos.Y, samplePos.Z, out height);
                value = height;
            }

            if (MyFakes.ENABLE_PLANET_FROZEN_SEA)
            {
                return(Math.Max((value * m_maxHillHeight) / (float)m_header.MaxValue, MyCsgPrecomputedHelpres.FROZEN_OCEAN_LEVEL));
            }

            return((value * m_maxHillHeight) / (float)m_header.MaxValue);
        }
 private float SignedDistanceInternal(float lodVoxelSize, IMyModule macroModulator, IMyModule detailModulator, ref Vector3 localPosition, float distance)
 {
     if (distance > 0.0f)
     {
         float    signedDistance = distance - m_averageRadius;
         Vector3I samplePos;
         Vector2  pos = Vector2.Zero;
         MyCsgPrecomputedHelpres.CalculateSamplePosition(ref localPosition, out samplePos, ref pos, m_header.Resolution);
         float value = GetValueForPosition(ref samplePos, ref pos, true);
         return((signedDistance - value) / lodVoxelSize);
     }
     return(0.0f);
 }
        public MyCsgShapePrecomputed(Vector3 translation, float averageRadius, string folderPath, float maxHillHeight)
        {
            m_maxHillHeight = maxHillHeight;

            m_file   = new MemoryMappedFile[MyCsgPrecomputedHelpres.NUM_MAPS];
            m_reader = new MemoryMappedViewAccessor[MyCsgPrecomputedHelpres.NUM_MAPS][];

            for (int i = 0; i < MyCsgPrecomputedHelpres.NUM_MAPS; ++i)
            {
                string name = null;
                MyCsgPrecomputedHelpres.GetNameForFace(i, ref name);

                name = Path.Combine(folderPath, name + ".bin");
                FileInfo fi     = new FileInfo(name);
                long     length = fi.Length;

                m_file[i] = MemoryMappedFile.CreateFromFile(name, FileMode.Open, null, 0, MemoryMappedFileAccess.Read);

                // read header separately
                m_headerLenght = 2 * sizeof(int) + 2 * sizeof(ushort);
                var headerReader = m_file[i].CreateViewAccessor(0, m_headerLenght, MemoryMappedFileAccess.Read);
                headerReader.Read(0, out m_header.MaxValue);
                headerReader.Read(sizeof(ushort), out m_header.BatchSize);
                headerReader.Read(2 * sizeof(ushort), out m_header.TypeSize);
                headerReader.Read(2 * sizeof(ushort) + sizeof(int), out m_header.Resolution);
                headerReader.Dispose();

                var  batchSectorsCount = m_header.Resolution / m_header.BatchSize;
                long batchLength       = m_header.TypeSize * m_header.BatchSize * m_header.BatchSize;

                m_reader[i] = new MemoryMappedViewAccessor[batchSectorsCount * batchSectorsCount];

                for (int j = 0; j < batchSectorsCount; ++j)
                {
                    for (int k = 0; k < batchSectorsCount; ++k)
                    {
                        int  batchIndex = j * batchSectorsCount + k;
                        long offset     = m_headerLenght + j * batchSectorsCount * batchLength + k * batchLength;
                        long size       = batchLength;
                        m_reader[i][batchIndex] = m_file[i].CreateViewAccessor(offset, size, MemoryMappedFileAccess.Read);
                    }
                }
            }

            m_batchLength   = m_header.BatchSize * m_header.BatchSize * m_header.TypeSize;
            m_sectorCount   = m_header.Resolution / m_header.BatchSize;
            m_averageRadius = averageRadius;
            m_translation   = translation;
            m_innerRadius   = averageRadius;
            m_outerRadius   = averageRadius + m_maxHillHeight;
        }
        internal override ContainmentType Contains(ref BoundingBox queryAabb, ref BoundingSphere querySphere, float lodVoxelSize)
        {
            ContainmentType outerContainment, innerContainment;

            BoundingSphere sphere = new BoundingSphere(
                m_translation,
                m_outerRadius + lodVoxelSize);

            sphere.Contains(ref queryAabb, out outerContainment);
            if (outerContainment == ContainmentType.Disjoint)
            {
                return(ContainmentType.Disjoint);
            }

            sphere.Radius = m_innerRadius - lodVoxelSize;
            sphere.Contains(ref queryAabb, out innerContainment);
            if (innerContainment == ContainmentType.Contains)
            {
                return(ContainmentType.Contains);
            }

            float minDistance = float.MaxValue;
            float maxDistance = -float.MaxValue;

            Vector3 localPosition = queryAabb.Min - m_translation;
            float   distance      = localPosition.LengthSquared();

            if (distance < 0.01f)
            {
                return(ContainmentType.Intersects);
            }

            Vector3I samplePos;
            Vector2  pos = Vector2.Zero;

            MyCsgPrecomputedHelpres.CalculateSamplePosition(ref localPosition, out samplePos, ref pos, m_header.Resolution);

            float value = GetValueForPosition(ref samplePos, ref pos, true);

            minDistance = MathHelper.Min(minDistance, value);
            maxDistance = MathHelper.Max(maxDistance, value);

            localPosition = queryAabb.Max - m_translation;
            distance      = localPosition.LengthSquared();
            if (distance < 0.01f)
            {
                return(ContainmentType.Intersects);
            }

            MyCsgPrecomputedHelpres.CalculateSamplePosition(ref localPosition, out samplePos, ref pos, m_header.Resolution);

            value = GetValueForPosition(ref samplePos, ref pos, true);

            minDistance = MathHelper.Min(minDistance, value);
            maxDistance = MathHelper.Max(maxDistance, value);

            sphere.Radius = m_innerRadius + maxDistance + lodVoxelSize;

            sphere.Contains(ref queryAabb, out outerContainment);
            if (outerContainment == ContainmentType.Disjoint)
            {
                return(ContainmentType.Disjoint);
            }

            sphere.Radius = m_innerRadius + minDistance - lodVoxelSize;
            sphere.Contains(ref queryAabb, out innerContainment);
            if (innerContainment == ContainmentType.Contains)
            {
                return(ContainmentType.Contains);
            }

            return(ContainmentType.Intersects);
        }