示例#1
0
        protected override void LoadInternal(int fileVersion, Stream stream, ref bool isOldFormat)
        {
            Debug.Assert(fileVersion == CURRENT_FILE_VERSION);

            ChunkHeader header = new ChunkHeader();
            Dictionary <byte, MyVoxelMaterialDefinition> materialTable = null;
            HashSet <UInt64> materialLeaves = new HashSet <UInt64>();
            HashSet <UInt64> contentLeaves  = new HashSet <UInt64>();

            while (header.ChunkType != ChunkTypeEnum.EndOfFile)
            {
                MyMicroOctreeLeaf contentLeaf;
                MyMicroOctreeLeaf materialLeaf;
                UInt64            key;

                header.ReadFrom(stream);
                Debug.Assert(Enum.IsDefined(typeof(ChunkTypeEnum), header.ChunkType));

                switch (header.ChunkType)
                {
                case ChunkTypeEnum.StorageMetaData:
                    ReadStorageMetaData(stream, header, ref isOldFormat);
                    break;

                case ChunkTypeEnum.MaterialIndexTable:
                    materialTable = ReadMaterialTable(stream, header, ref isOldFormat);
                    break;

                case ChunkTypeEnum.MacroContentNodes:
                    ReadOctreeNodes(stream, header, ref isOldFormat, m_contentNodes);
                    break;

                case ChunkTypeEnum.MacroMaterialNodes:
                    ReadOctreeNodes(stream, header, ref isOldFormat, m_materialNodes);
                    break;

                case ChunkTypeEnum.ContentLeafProvider:
                    ReadProviderLeaf(stream, header, ref isOldFormat, contentLeaves);
                    break;

                case ChunkTypeEnum.ContentLeafOctree:
                    ReadOctreeLeaf(stream, header, ref isOldFormat, MyStorageDataTypeEnum.Content, out key, out contentLeaf);
                    m_contentLeaves.Add(key, contentLeaf);
                    break;

                case ChunkTypeEnum.MaterialLeafProvider:
                    ReadProviderLeaf(stream, header, ref isOldFormat, materialLeaves);
                    break;

                case ChunkTypeEnum.MaterialLeafOctree:
                    ReadOctreeLeaf(stream, header, ref isOldFormat, MyStorageDataTypeEnum.Material, out key, out materialLeaf);
                    m_materialLeaves.Add(key, materialLeaf);
                    break;

                case ChunkTypeEnum.DataProvider:
                    ReadDataProvider(stream, header, ref isOldFormat, out m_dataProvider);
                    break;

                case ChunkTypeEnum.EndOfFile:
                    break;

                default:
                    throw new InvalidBranchException();
                }
            }

            { // At this point data provider should be loaded too, so have him create leaves
                MyCellCoord cell = new MyCellCoord();
                foreach (var key in contentLeaves)
                {
                    cell.SetUnpack(key);
                    cell.Lod += LeafLodCount;
                    m_contentLeaves.Add(key, new MyProviderLeaf(m_dataProvider, MyStorageDataTypeEnum.Content, ref cell));
                }

                foreach (var key in materialLeaves)
                {
                    cell.SetUnpack(key);
                    cell.Lod += LeafLodCount;
                    m_materialLeaves.Add(key, new MyProviderLeaf(m_dataProvider, MyStorageDataTypeEnum.Material, ref cell));
                }
            }

            { // material reindexing when definitions change
                Debug.Assert(materialTable != null);
                bool needsReindexing = false;
                foreach (var entry in materialTable)
                {
                    if (entry.Key != entry.Value.Index)
                    {
                        needsReindexing = true;
                    }
                    m_oldToNewIndexMap.Add(entry.Key, entry.Value.Index);
                }

                if (needsReindexing)
                {
                    if (m_dataProvider != null)
                    {
                        m_dataProvider.ReindexMaterials(m_oldToNewIndexMap);
                    }

                    foreach (var entry in m_materialLeaves)
                    {
                        entry.Value.ReplaceValues(m_oldToNewIndexMap);
                    }

                    MySparseOctree.ReplaceValues(m_materialNodes, m_oldToNewIndexMap);
                }
                m_oldToNewIndexMap.Clear();
            }
        }
        IMyClipmapCell IMyClipmapCellHandler.CreateCell(MyClipmapScaleEnum scaleGroup, MyCellCoord cellCoord, ref MatrixD worldMatrix)
        {
            switch (scaleGroup)
            {
            case MyClipmapScaleEnum.Normal:
                return(new MyRenderVoxelCell(scaleGroup, cellCoord, ref worldMatrix));

            case MyClipmapScaleEnum.Massive:
                return(new MyRenderVoxelCellBackground(cellCoord, ref worldMatrix, m_position, m_atmosphereRadius, m_planetRadius, m_hasAtmosphere, m_atmosphereWaveLengths.Value));

            default:
                throw new InvalidBranchException();
            }
        }
        internal CellData GetCell(ref MyCellCoord cell)
        {
            MyPrecalcComponent.AssertUpdateThread();

            bool     isEmpty;
            CellData data;

            if (TryGetCell(cell, out isEmpty, out data))
            {
                return(data);
            }

            MyIsoMesh mesh;

            if (!TryGetMesh(cell, out isEmpty, out mesh))
            {
                ProfilerShort.Begin("Cell precalc");
                if (true)
                {
                    var min = cell.CoordInLod << MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS_BITS;
                    var max = min + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS;
                    // overlap to neighbor; introduces extra data but it makes logic for raycasts simpler (no need to check neighbor cells)
                    min -= 1;
                    max += 2;
                    mesh = MyPrecalcComponent.IsoMesher.Precalc(m_storage, 0, min, max, false);
                }
                else
                {
                    mesh = MyPrecalcComponent.IsoMesher.Precalc(new MyIsoMesherArgs()
                    {
                        Storage      = m_storage,
                        GeometryCell = cell,
                    });
                }
                ProfilerShort.End();
            }

            if (mesh != null)
            {
                data = new CellData();
                data.Init(
                    mesh.PositionOffset, mesh.PositionScale,
                    mesh.Positions.GetInternalArray(), mesh.VerticesCount,
                    mesh.Triangles.GetInternalArray(), mesh.TrianglesCount);
            }

            if (cell.Lod == 0)
            {
                using (m_lock.AcquireExclusiveUsing())
                {
                    if (data != null)
                    {
                        var key = cell.PackId64();
                        m_cellsByCoordinate[key] = data;
                    }
                    else
                    {
                        SetEmpty(ref cell, true);
                    }
                }
            }

            return(data);
        }
        public void ProcessChangedCellComponents()
        {
            ProfilerShort.Begin("ProcessChangedCellComponents");

            m_currentHelper = this;

            Vector3I   min, max, pos;
            List <int> triangles = null;

            foreach (var cell in m_changedCells)
            {
                MyCellCoord cellCoord  = new MyCellCoord(0, cell);
                ulong       packedCell = cellCoord.PackId64();

                m_components.OpenCell(packedCell);

                min = CellToLowestCube(cell);
                max = min + m_cellSize - Vector3I.One;

                // Save a hashset of all the triangles in the current cell
                pos = min;
                for (var it = new Vector3I.RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out pos))
                {
                    if (!m_triangleRegistry.TryGetValue(pos, out triangles))
                    {
                        continue;
                    }

                    foreach (var triIndex in triangles)
                    {
                        m_tmpCellTriangles.Add(triIndex);
                    }
                }

                long timeBegin = m_mesh.GetCurrentTimestamp() + 1;
                long timeEnd   = timeBegin;
                m_currentComponentRel = 0;

                foreach (var triIndex in m_tmpCellTriangles)
                {
                    // Skip already visited triangles
                    var triangle = m_mesh.GetTriangle(triIndex);
                    if (m_currentComponentRel != 0 && m_mesh.VisitedBetween(triangle, timeBegin, timeEnd))
                    {
                        continue;
                    }

                    m_components.OpenComponent();

                    // Make sure we have place in m_currentCellConnections
                    if (m_currentComponentRel >= m_currentCellConnections.Count)
                    {
                        m_currentCellConnections.Add(new List <int>());
                    }

                    // Find connected component from an unvisited triangle and mark its connections
                    m_components.AddComponentTriangle(triangle, triangle.Center);
                    triangle.ComponentIndex = m_components.OpenComponentIndex;
                    m_mesh.PrepareTraversal(triangle, null, m_processTrianglePredicate);

                    var primitiveEnum = m_mesh.GetEnumerator();
                    while (primitiveEnum.MoveNext())
                    {
                        ;
                    }
                    primitiveEnum.Dispose();

                    m_components.CloseComponent();

                    timeEnd = m_mesh.GetCurrentTimestamp();
                    if (m_currentComponentRel == 0)
                    {
                        timeBegin = timeEnd;
                    }
                    m_currentComponentRel++;
                }

                m_tmpCellTriangles.Clear();

                MyNavmeshComponents.ClosedCellInfo cellInfo = new MyNavmeshComponents.ClosedCellInfo();
                m_components.CloseAndCacheCell(ref cellInfo);

                // Add new component primitives
                if (cellInfo.NewCell)
                {
                    for (int i = 0; i < cellInfo.ComponentNum; ++i)
                    {
                        m_mesh.HighLevelGroup.AddPrimitive(cellInfo.StartingIndex + i, m_components.GetComponentCenter(i));
                    }
                }

                // Connect new components with the others in the neighboring cells
                for (int i = 0; i < cellInfo.ComponentNum; ++i)
                {
                    foreach (var otherComponent in m_currentCellConnections[i])
                    {
                        m_mesh.HighLevelGroup.ConnectPrimitives(cellInfo.StartingIndex + i, otherComponent);
                    }
                    m_currentCellConnections[i].Clear();
                }

                // Set all the components as expanded
                for (int i = 0; i < cellInfo.ComponentNum; ++i)
                {
                    int componentIndex = cellInfo.StartingIndex + i;
                    var component      = m_mesh.HighLevelGroup.GetPrimitive(componentIndex);
                    if (component != null)
                    {
                        component.IsExpanded = true;
                    }
                }
            }

            m_changedCells.Clear();

            m_currentHelper = null;

            ProfilerShort.End();
        }
        private void AddVoxelMesh(MyVoxelBase voxelBase, IMyStorage storage, Dictionary <Vector3I, MyIsoMesh> cache, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List <BoundingBoxD> bbList)
        {
            bool useCache = cache != null;

            if (useCache)
            {
                CheckCacheValidity();
            }

            obb.HalfExtent += new Vector3D(border, 0, border);
            BoundingBoxD bb           = obb.GetAABB();
            int          aabbSideSide = (int)Math.Round(bb.HalfExtents.Max() * 2);

            bb = new BoundingBoxD(bb.Min, bb.Min + aabbSideSide);
            bb.Translate(obb.Center - bb.Center);

            // For debug
            bbList.Add(new BoundingBoxD(bb.Min, bb.Max));

            bb = (BoundingBoxD)bb.TransformFast(voxelBase.PositionComp.WorldMatrixInvScaled);
            bb.Translate(voxelBase.SizeInMetresHalf);

            Vector3I min = Vector3I.Round(bb.Min);
            Vector3I max = min + aabbSideSide;
            Vector3I geomMin, geomMax;

            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref min, out geomMin);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref max, out geomMax);

            var cullBox = obb;

            cullBox.Transform(voxelBase.PositionComp.WorldMatrixInvScaled);
            cullBox.Center += voxelBase.SizeInMetresHalf;
            ProfilerShort.Begin("WOOOORK");

            Vector3I_RangeIterator it    = new Vector3I_RangeIterator(ref geomMin, ref geomMax);
            MyCellCoord            coord = new MyCellCoord();
            BoundingBox            localAabb;

            coord.Lod = NAVMESH_LOD;
            int       hits = 0;
            MyIsoMesh gMesh;
            Vector3   offset = originPosition - voxelBase.PositionLeftBottomCorner;

            // Calculate rotation
            Vector3    gravityVector = -Vector3.Normalize(GameSystems.MyGravityProviderSystem.CalculateTotalGravityInPoint(originPosition));
            Vector3    forwardVector = Vector3.CalculatePerpendicularVector(gravityVector);
            Quaternion quaternion    = Quaternion.CreateFromForwardUp(forwardVector, gravityVector);
            Matrix     rotation      = Matrix.CreateFromQuaternion(Quaternion.Inverse(quaternion));

            Matrix ownRotation = voxelBase.PositionComp.WorldMatrix.GetOrientation();

            while (it.IsValid())
            {
                ProfilerShort.Begin("ITERATOR");

                if (useCache && cache.TryGetValue(it.Current, out gMesh))
                {
                    if (gMesh != null)
                    {
                        AddMeshTriangles(gMesh, offset, rotation, ownRotation);
                    }
                    it.MoveNext();
                    ProfilerShort.End();
                    continue;
                }

                coord.CoordInLod = it.Current;
                MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref coord.CoordInLod, out localAabb);

                if (!cullBox.Intersects(ref localAabb))
                {
                    hits++;
                    it.MoveNext();
                    ProfilerShort.End();
                    continue;
                }
                ProfilerShort.End();

                var debugBB = new BoundingBoxD(localAabb.Min, localAabb.Max).Translate(-voxelBase.SizeInMetresHalf);
                bbList.Add(debugBB);

                ProfilerShort.Begin("Mesh Calc");
                var voxelStart = coord.CoordInLod * MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS - 1;
                var voxelEnd   = voxelStart + MyVoxelConstants.GEOMETRY_CELL_SIZE_IN_VOXELS //- 1
                                 + 1                                                        // overlap to neighbor so geometry is stitched together within same LOD
                                 + 1;                                                       // for eg. 9 vertices in row we need 9 + 1 samples (voxels)

                var generatedMesh = MyPrecalcComponent.IsoMesher.Precalc(storage, NAVMESH_LOD, voxelStart, voxelEnd, false, false, true);
                ProfilerShort.End();

                if (useCache)
                {
                    cache[it.Current] = generatedMesh;
                }

                if (generatedMesh != null)
                {
                    ProfilerShort.Begin("Mesh NOT NULL");
                    AddMeshTriangles(generatedMesh, offset, rotation, ownRotation);
                    ProfilerShort.End();
                }
                it.MoveNext();
            }
            ProfilerShort.End();
        }
示例#6
0
        public void ProcessChangedCellComponents()
        {
            ProfilerShort.Begin("ProcessChangedCellComponents");

            m_currentHelper = this;

            Vector3I   min, max, pos;
            List <int> triangles = null;

            foreach (var cell in m_changedCells)
            {
                min = CellToLowestCube(cell);
                max = min + m_cellSize - Vector3I.One;

                // Save a hashset of all the triangles in the current cell
                pos = min;
                for (var it = new Vector3I.RangeIterator(ref min, ref max); it.IsValid(); it.GetNext(out pos))
                {
                    if (!m_triangleRegistry.TryGetValue(pos, out triangles))
                    {
                        continue;
                    }

                    foreach (var triIndex in triangles)
                    {
                        m_tmpCellTriangles.Add(triIndex);
                    }
                }

                if (m_tmpCellTriangles.Count == 0)
                {
                    continue;
                }

                MyCellCoord cellCoord  = new MyCellCoord(0, cell);
                ulong       packedCell = cellCoord.PackId64();
                m_components.OpenCell(packedCell);

                long timeBegin = m_mesh.GetCurrentTimestamp() + 1;
                long timeEnd   = timeBegin;
                m_currentComponentRel = 0;

                m_tmpComponentTriangles.Clear();
                foreach (var triIndex in m_tmpCellTriangles)
                {
                    // Skip already visited triangles
                    var triangle = m_mesh.GetTriangle(triIndex);
                    if (m_currentComponentRel != 0 && m_mesh.VisitedBetween(triangle, timeBegin, timeEnd))
                    {
                        continue;
                    }

                    m_components.OpenComponent();

                    // Make sure we have place in m_currentCellConnections
                    if (m_currentComponentRel >= m_currentCellConnections.Count)
                    {
                        m_currentCellConnections.Add(new List <int>());
                    }

                    // Find connected component from an unvisited triangle and mark its connections
                    m_components.AddComponentTriangle(triangle, triangle.Center);
                    triangle.ComponentIndex = m_currentComponentRel;
                    m_tmpComponentTriangles.Add(triangle);
                    m_mesh.PrepareTraversal(triangle, null, m_processTrianglePredicate);
                    m_mesh.PerformTraversal();
                    m_tmpComponentTriangles.Add(null);

                    m_components.CloseComponent();

                    timeEnd = m_mesh.GetCurrentTimestamp();
                    if (m_currentComponentRel == 0)
                    {
                        timeBegin = timeEnd;
                    }
                    m_currentComponentRel++;
                }

                m_tmpCellTriangles.Clear();

                MyNavmeshComponents.ClosedCellInfo cellInfo = new MyNavmeshComponents.ClosedCellInfo();
                m_components.CloseAndCacheCell(ref cellInfo);

                // Renumber triangles from the old indices to the newly assigned index from m_components
                int componentIndex = cellInfo.StartingIndex;
                foreach (var triangle in m_tmpComponentTriangles)
                {
                    if (triangle == null)
                    {
                        componentIndex++;
                        continue;
                    }
                    triangle.ComponentIndex = componentIndex;
                }
                m_tmpComponentTriangles.Clear();

                // Remove old component primitives
                if (!cellInfo.NewCell && cellInfo.ComponentNum != cellInfo.OldComponentNum)
                {
                    for (int i = 0; i < cellInfo.OldComponentNum; ++i)
                    {
                        m_mesh.HighLevelGroup.RemovePrimitive(cellInfo.OldStartingIndex + i);
                    }
                }

                // Add new component primitives
                if (cellInfo.NewCell || cellInfo.ComponentNum != cellInfo.OldComponentNum)
                {
                    for (int i = 0; i < cellInfo.ComponentNum; ++i)
                    {
                        m_mesh.HighLevelGroup.AddPrimitive(cellInfo.StartingIndex + i, m_components.GetComponentCenter(i));
                    }
                }

                // Update existing component primitives
                if (!cellInfo.NewCell && cellInfo.ComponentNum == cellInfo.OldComponentNum)
                {
                    for (int i = 0; i < cellInfo.ComponentNum; ++i)
                    {
                        var primitive = m_mesh.HighLevelGroup.GetPrimitive(cellInfo.StartingIndex + i);
                        primitive.UpdatePosition(m_components.GetComponentCenter(i));
                    }
                }

                // Connect new components with the others in the neighboring cells
                for (int i = 0; i < cellInfo.ComponentNum; ++i)
                {
                    int compIndex = cellInfo.StartingIndex + i;

                    var primitive = m_mesh.HighLevelGroup.GetPrimitive(compIndex);
                    primitive.GetNeighbours(m_tmpNeighbors);

                    // Connect to disconnected components
                    foreach (var connection in m_currentCellConnections[i])
                    {
                        if (!m_tmpNeighbors.Remove(connection))
                        {
                            m_mesh.HighLevelGroup.ConnectPrimitives(compIndex, connection);
                        }
                    }

                    // Disconnect neighbors that should be no longer connected
                    foreach (var neighbor in m_tmpNeighbors)
                    {
                        // Only disconnect from the other cell if it is expanded and there was no connection found
                        var neighborPrimitive = m_mesh.HighLevelGroup.TryGetPrimitive(neighbor);
                        if (neighborPrimitive != null && neighborPrimitive.IsExpanded)
                        {
                            m_mesh.HighLevelGroup.DisconnectPrimitives(compIndex, neighbor);
                        }
                    }

                    m_tmpNeighbors.Clear();
                    m_currentCellConnections[i].Clear();
                }

                // Set all the components as expanded
                for (int i = 0; i < cellInfo.ComponentNum; ++i)
                {
                    componentIndex = cellInfo.StartingIndex + i;
                    var component = m_mesh.HighLevelGroup.GetPrimitive(componentIndex);
                    if (component != null)
                    {
                        component.IsExpanded = true;
                    }
                }
            }

            m_changedCells.Clear();

            m_currentHelper = null;

            ProfilerShort.End();
        }
示例#7
0
 public MyProviderLeaf(IMyStorageDataProvider provider, MyStorageDataTypeEnum dataType, ref MyCellCoord cell)
 {
     m_provider = provider;
     m_dataType = dataType;
     m_cell     = cell;
 }
示例#8
0
        public void ProcessChangedCellComponents()
        {
            m_currentHelper = this;
            List <int> list = null;

            foreach (Vector3I vectori4 in this.m_changedCells)
            {
                Vector3I start = this.CellToLowestCube(vectori4);
                Vector3I end   = ((Vector3I)(start + this.m_cellSize)) - Vector3I.One;
                Vector3I key   = start;
                Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref start, ref end);
                while (true)
                {
                    if (!iterator.IsValid())
                    {
                        if (m_tmpCellTriangles.Count != 0)
                        {
                            ulong cellCoord = new MyCellCoord(0, vectori4).PackId64();
                            this.m_components.OpenCell(cellCoord);
                            long num2             = this.m_mesh.GetCurrentTimestamp() + 1L;
                            long currentTimestamp = num2;
                            this.m_currentComponentRel = 0;
                            this.m_tmpComponentTriangles.Clear();
                            foreach (int num6 in m_tmpCellTriangles)
                            {
                                MyNavigationTriangle vertex = this.m_mesh.GetTriangle(num6);
                                if ((this.m_currentComponentRel == 0) || !this.m_mesh.VisitedBetween(vertex, num2, currentTimestamp))
                                {
                                    this.m_components.OpenComponent();
                                    if (this.m_currentComponentRel >= this.m_currentCellConnections.Count)
                                    {
                                        this.m_currentCellConnections.Add(new List <int>());
                                    }
                                    this.m_components.AddComponentTriangle(vertex, vertex.Center);
                                    vertex.ComponentIndex = this.m_currentComponentRel;
                                    this.m_tmpComponentTriangles.Add(vertex);
                                    this.m_mesh.PrepareTraversal(vertex, null, this.m_processTrianglePredicate, null);
                                    this.m_mesh.PerformTraversal();
                                    this.m_tmpComponentTriangles.Add(null);
                                    this.m_components.CloseComponent();
                                    currentTimestamp = this.m_mesh.GetCurrentTimestamp();
                                    if (this.m_currentComponentRel == 0)
                                    {
                                        num2 = currentTimestamp;
                                    }
                                    this.m_currentComponentRel++;
                                }
                            }
                            m_tmpCellTriangles.Clear();
                            MyNavmeshComponents.ClosedCellInfo output = new MyNavmeshComponents.ClosedCellInfo();
                            this.m_components.CloseAndCacheCell(ref output);
                            int startingIndex = output.StartingIndex;
                            foreach (MyNavigationTriangle triangle2 in this.m_tmpComponentTriangles)
                            {
                                if (triangle2 == null)
                                {
                                    startingIndex++;
                                    continue;
                                }
                                triangle2.ComponentIndex = startingIndex;
                            }
                            this.m_tmpComponentTriangles.Clear();
                            if (!output.NewCell && (output.ComponentNum != output.OldComponentNum))
                            {
                                for (int i = 0; i < output.OldComponentNum; i++)
                                {
                                    this.m_mesh.HighLevelGroup.RemovePrimitive(output.OldStartingIndex + i);
                                }
                            }
                            if (output.NewCell || (output.ComponentNum != output.OldComponentNum))
                            {
                                for (int i = 0; i < output.ComponentNum; i++)
                                {
                                    this.m_mesh.HighLevelGroup.AddPrimitive(output.StartingIndex + i, this.m_components.GetComponentCenter(i));
                                }
                            }
                            if (!output.NewCell && (output.ComponentNum == output.OldComponentNum))
                            {
                                for (int i = 0; i < output.ComponentNum; i++)
                                {
                                    this.m_mesh.HighLevelGroup.GetPrimitive(output.StartingIndex + i).UpdatePosition(this.m_components.GetComponentCenter(i));
                                }
                            }
                            int num10 = 0;
                            while (true)
                            {
                                if (num10 >= output.ComponentNum)
                                {
                                    for (int i = 0; i < output.ComponentNum; i++)
                                    {
                                        startingIndex = output.StartingIndex + i;
                                        MyHighLevelPrimitive primitive = this.m_mesh.HighLevelGroup.GetPrimitive(startingIndex);
                                        if (primitive != null)
                                        {
                                            primitive.IsExpanded = true;
                                        }
                                    }
                                    break;
                                }
                                int index = output.StartingIndex + num10;
                                this.m_mesh.HighLevelGroup.GetPrimitive(index).GetNeighbours(this.m_tmpNeighbors);
                                foreach (int num12 in this.m_currentCellConnections[num10])
                                {
                                    if (!this.m_tmpNeighbors.Remove(num12))
                                    {
                                        this.m_mesh.HighLevelGroup.ConnectPrimitives(index, num12);
                                    }
                                }
                                foreach (int num13 in this.m_tmpNeighbors)
                                {
                                    MyHighLevelPrimitive primitive = this.m_mesh.HighLevelGroup.TryGetPrimitive(num13);
                                    if ((primitive != null) && primitive.IsExpanded)
                                    {
                                        this.m_mesh.HighLevelGroup.DisconnectPrimitives(index, num13);
                                    }
                                }
                                this.m_tmpNeighbors.Clear();
                                this.m_currentCellConnections[num10].Clear();
                                num10++;
                            }
                        }
                        break;
                    }
                    if (this.m_triangleRegistry.TryGetValue(key, out list))
                    {
                        foreach (int num5 in list)
                        {
                            m_tmpCellTriangles.Add(num5);
                        }
                    }
                    iterator.GetNext(out key);
                }
            }
            this.m_changedCells.Clear();
            m_currentHelper = null;
        }
示例#9
0
            private void UnclipCell(RequestCollector collector, MyCellCoord cell, bool isVisible)
            {
                var cellId        = cell.PackId64();
                var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId);
                MyClipmap_CellData data;

                if (isVisible)
                {
                    bool highPriority = true;

                    if (m_clippedCells.TryGetValue(cellId, out data))
                    {
                        m_clippedCells.Remove(cellId);
                    }
                    else
                    {
                        highPriority = false;

                        CellBlendData blendData;
                        if (!m_blendedCells.TryGetValue(cellId, out blendData))
                        {
                            data = CellsCache.Read(clipmapCellId);

                            if (data == null) //cache miss
                            {
                                data = new MyClipmap_CellData();
                                ClippingCacheMisses++;
                            }
                            else
                            {
                                //cache hit
                                ClippingCacheHits++;

                                //System.Diagnostics.Debug.Assert((!data.InScene && data.Cell != null) || data.Cell == null, "Not allowed cell state");
                                data.InScene = false;
                                if (data.Cell != null)
                                {
                                    m_nonEmptyCells[cellId] = data;
                                }
                            }
                        }
                        else
                        {
                            data = blendData.CellData;
                            if (blendData.State == BlendState.Removing)
                            {
                                blendData.UndoAfterFinish = true;
                            }
                            if (data.Cell != null)
                            {
                                m_nonEmptyCells[cellId] = data;
                            }
                        }
                    }

                    if (data.State == CellState.Invalid)
                    {
                        if (MyClipmap.UseQueries)
                        {
                            BoundingBoxD bbd;
                            MyVoxelCoordSystems.RenderCellCoordToLocalAABB(ref cell, out bbd);
                            BoundingBox bb = new BoundingBox(bbd);
                            if (m_clipmap.m_prunningFunc == null || m_clipmap.m_prunningFunc(ref bb, false) == ContainmentType.Intersects)
                            {
                                collector.AddRequest(cellId, data, highPriority);
                            }
                            else
                            {
                                data.State     = CellState.Loaded;
                                data.WasLoaded = true;
                            }
                        }
                        else
                        {
                            collector.AddRequest(cellId, data, highPriority);
                        }
                    }

                    m_storedCellData.Add(cellId, data);
                    data.ReadyInClipmap = true;
                    data.ClippedOut     = false;
                }
                else
                {
                    if (!m_storedCellData.ContainsKey(cellId) && (!PendingCacheCellData.ContainsKey(clipmapCellId) || PendingCacheCellData[clipmapCellId].State == CellState.Invalid) && CellsCache.Read(clipmapCellId) == null)
                    {
                        if (!PendingCacheCellData.TryGetValue(clipmapCellId, out data))
                        {
                            data = new MyClipmap_CellData();
                            PendingCacheCellData.Add(clipmapCellId, data);
                        }

                        if (MyClipmap.UseQueries)
                        {
                            BoundingBoxD bbd;
                            MyVoxelCoordSystems.RenderCellCoordToLocalAABB(ref cell, out bbd);
                            BoundingBox bb = new BoundingBox(bbd);
                            if (m_clipmap.m_prunningFunc == null || m_clipmap.m_prunningFunc(ref bb, false) == ContainmentType.Intersects)
                            {
                                data.State = CellState.Invalid;

                                collector.AddRequest(cellId, data, false);
                            }
                            else
                            {
                                data.State     = CellState.Loaded;
                                data.WasLoaded = true;
                            }
                        }
                        else
                        {
                            data.State = CellState.Invalid;
                            collector.AddRequest(cellId, data, false);
                        }
                    }
                }
            }
示例#10
0
        private static void WriteRange(
            ref WriteRangeArgs args,
            byte defaultData,
            int lodIdx,
            Vector3I lodCoord,
            ref Vector3I min,
            ref Vector3I max)
        {
            MyOctreeNode node = new MyOctreeNode();

            {
                MyCellCoord leaf    = new MyCellCoord(lodIdx - LeafLodCount, ref lodCoord);
                var         leafKey = leaf.PackId64();
                if (args.Leaves.ContainsKey(leafKey))
                {
                    args.Leaves.Remove(leafKey);
                    var         childBase = lodCoord << 1;
                    Vector3I    childOffset;
                    MyCellCoord child = new MyCellCoord();
                    child.Lod = leaf.Lod - 1;
                    var leafSize = LeafSizeInVoxels << child.Lod;
                    for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                    {
                        ComputeChildCoord(i, out childOffset);
                        child.CoordInLod = childBase + childOffset;
                        var childCopy = child;
                        childCopy.Lod += LeafLodCount;
                        IMyOctreeLeafNode octreeLeaf = new MyProviderLeaf(args.Provider, args.DataType, ref childCopy);
                        args.Leaves.Add(child.PackId64(), octreeLeaf);
                        node.SetChild(i, true);
                        node.SetData(i, octreeLeaf.GetFilteredValue());
                    }
                }
                else
                {
                    leaf.Lod -= 1; // changes to node coord instead of leaf coord
                    var nodeKey = leaf.PackId64();

                    if (!args.Nodes.TryGetValue(nodeKey, out node))
                    {
                        for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                        {
                            node.SetData(i, defaultData);
                        }
                    }
                }
            }

            if (lodIdx == (LeafLodCount + 1))
            {
                MyCellCoord child            = new MyCellCoord();
                Vector3I    childBase        = lodCoord << 1;
                Vector3I    minInLod         = min >> LeafLodCount;
                Vector3I    maxInLod         = max >> LeafLodCount;
                Vector3I    leafSizeMinusOne = new Vector3I(LeafSizeInVoxels - 1);
                Vector3I    childOffset;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    ComputeChildCoord(i, out childOffset);
                    child.CoordInLod = childBase + childOffset;
                    if (!child.CoordInLod.IsInsideInclusive(ref minInLod, ref maxInLod))
                    {
                        continue;
                    }
                    var childMin = child.CoordInLod << LeafLodCount;
                    var childMax = childMin + LeafSizeInVoxels - 1;
                    Vector3I.Max(ref childMin, ref min, out childMin);
                    Vector3I.Min(ref childMax, ref max, out childMax);
                    var readOffset = childMin - min;
                    IMyOctreeLeafNode leaf;
                    var leafKey      = child.PackId64();
                    var startInChild = childMin - (child.CoordInLod << LeafLodCount);
                    var endInChild   = childMax - (child.CoordInLod << LeafLodCount);

                    args.Leaves.TryGetValue(leafKey, out leaf);

                    byte uniformValue;
                    bool uniformLeaf;
                    {
                        // ensure leaf exists and is writable
                        // the only writable leaf type is MicroOctree at this point

                        byte childDefaultData = node.GetData(i);

                        if (leaf == null)
                        {
                            var octree = new MyMicroOctreeLeaf(args.DataType, LeafLodCount, child.CoordInLod << (child.Lod + LeafLodCount));
                            octree.BuildFrom(childDefaultData);
                            leaf = octree;
                        }

                        if (leaf.ReadOnly)
                        {
                            var rangeEnd = new Vector3I(LeafSizeInVoxels - 1);
                            m_temporaryCache.Resize(Vector3I.Zero, rangeEnd);
                            leaf.ReadRange(m_temporaryCache, ref Vector3I.Zero, 0, ref Vector3I.Zero, ref rangeEnd);
                            var inCell = startInChild;
                            for (var it2 = new Vector3I.RangeIterator(ref startInChild, ref endInChild);
                                 it2.IsValid(); it2.GetNext(out inCell))
                            {
                                var read = readOffset + (inCell - startInChild);
                                m_temporaryCache.Set(args.DataType, ref inCell, args.Source.Get(args.DataType, ref read));
                            }

                            var octree = new MyMicroOctreeLeaf(args.DataType, LeafLodCount, child.CoordInLod << (child.Lod + LeafLodCount));
                            octree.BuildFrom(m_temporaryCache);
                            leaf = octree;
                        }
                        else
                        {
                            leaf.WriteRange(args.Source, ref readOffset, ref startInChild, ref endInChild);
                        }

                        uniformLeaf = ((MyMicroOctreeLeaf)leaf).TryGetUniformValue(out uniformValue);
                    }

                    if (!uniformLeaf)
                    {
                        args.Leaves[leafKey] = leaf;
                        node.SetChild(i, true);
                    }
                    else
                    {
                        args.Leaves.Remove(leafKey);
                        node.SetChild(i, false);
                    }

                    node.SetData(i, leaf.GetFilteredValue());
                }
                args.Nodes[new MyCellCoord(lodIdx - 1 - LeafLodCount, ref lodCoord).PackId64()] = node;
            }
            else
            {
                MyCellCoord child = new MyCellCoord();
                child.Lod = lodIdx - 2 - LeafLodCount;
                var      childBase = lodCoord << 1;
                Vector3I childOffset;
                var      minInChild = (min >> (lodIdx - 1)) - childBase;
                var      maxInChild = (max >> (lodIdx - 1)) - childBase;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    ComputeChildCoord(i, out childOffset);
                    if (!childOffset.IsInsideInclusive(ref minInChild, ref maxInChild))
                    {
                        continue;
                    }

                    child.CoordInLod = childBase + childOffset;
                    WriteRange(ref args, node.GetData(i), lodIdx - 1, child.CoordInLod, ref min, ref max);
                    var childKey  = child.PackId64();
                    var childNode = args.Nodes[childKey];
                    if (!childNode.HasChildren && childNode.AllDataSame())
                    {
                        node.SetChild(i, false);
                        node.SetData(i, childNode.GetData(0));
                        args.Nodes.Remove(childKey);
                    }
                    else
                    {
                        node.SetChild(i, true);
                        node.SetData(i, childNode.ComputeFilteredValue(args.DataFilter));
                    }
                }

                args.Nodes[new MyCellCoord(lodIdx - 1 - LeafLodCount, ref lodCoord).PackId64()] = node;
            }
        }
示例#11
0
        public void ProcessCellComponents()
        {
            ProfilerShort.Begin("ProcessCellComponents");
            m_triangleLists.Add(m_packedCoord, m_triangleList.GetCopy());

            long timeBegin = m_mesh.GetCurrentTimestamp() + 1;
            long timeEnd   = timeBegin;

            m_currentComponentRel = 0;
            m_currentComponent    = m_navmeshComponents.OpenCell(m_packedCoord);

            foreach (var triIndex in m_triangleList)
            {
                // Skip already visited triangles
                var triangle = m_mesh.GetTriangle(triIndex);
                if (m_mesh.VisitedBetween(triangle, timeBegin, timeEnd))
                {
                    continue;
                }

                m_navmeshComponents.OpenComponent();

                // Make sure we have place in m_currentCellConnections
                if (m_currentComponentRel >= m_currentCellConnections.Count)
                {
                    m_currentCellConnections.Add(new List <ConnectionInfo>());
                }

                // Find connected component from an unvisited triangle
                ProfilerShort.Begin("Graph traversal");
                m_currentHelper = this;

                m_navmeshComponents.AddComponentTriangle(triangle, triangle.Center);
                triangle.ComponentIndex = m_navmeshComponents.OpenComponentIndex;
                m_mesh.PrepareTraversal(triangle, null, m_processTrianglePredicate);

                var primitiveEnum = m_mesh.GetEnumerator();
                while (primitiveEnum.MoveNext())
                {
                    ;
                }
                primitiveEnum.Dispose();
                ProfilerShort.End();

                m_navmeshComponents.CloseComponent();

                timeEnd = m_mesh.GetCurrentTimestamp();
                m_currentComponentRel++;
            }

            MyNavmeshComponents.ClosedCellInfo cellInfo = new MyNavmeshComponents.ClosedCellInfo();
            m_navmeshComponents.CloseAndCacheCell(ref cellInfo);

            // Add new component primitives
            if (cellInfo.NewCell)
            {
                for (int i = 0; i < cellInfo.ComponentNum; ++i)
                {
                    m_mesh.HighLevelGroup.AddPrimitive(cellInfo.StartingIndex + i, m_navmeshComponents.GetComponentCenter(i));
                }
            }

            // Connect new components with the others in the neighboring cells
            for (int i = 0; i < cellInfo.ComponentNum; ++i)
            {
                foreach (var connectionInfo in m_currentCellConnections[i])
                {
                    if (!cellInfo.ExploredDirections.HasFlag(Base6Directions.GetDirectionFlag(connectionInfo.Direction)))
                    {
                        m_mesh.HighLevelGroup.ConnectPrimitives(cellInfo.StartingIndex + i, connectionInfo.ComponentIndex);
                    }
                }
                m_currentCellConnections[i].Clear();
            }

            // Mark explored directions in the navmesh component helper
            foreach (var direction in Base6Directions.EnumDirections)
            {
                var dirFlag = Base6Directions.GetDirectionFlag(direction);
                if (cellInfo.ExploredDirections.HasFlag(dirFlag))
                {
                    continue;
                }

                Vector3I dirVec = Base6Directions.GetIntVector(direction);

                MyCellCoord otherCoord = new MyCellCoord();
                otherCoord.Lod        = MyVoxelNavigationMesh.NAVMESH_LOD;
                otherCoord.CoordInLod = m_currentCell + dirVec;
                if (otherCoord.CoordInLod.X == -1 || otherCoord.CoordInLod.Y == -1 || otherCoord.CoordInLod.Z == -1)
                {
                    continue;
                }

                ulong otherPackedCoord = otherCoord.PackId64();

                if (m_triangleLists.ContainsKey(otherPackedCoord))
                {
                    m_navmeshComponents.MarkExplored(otherPackedCoord, Base6Directions.GetFlippedDirection(direction));
                    cellInfo.ExploredDirections |= Base6Directions.GetDirectionFlag(direction);
                }
            }
            m_navmeshComponents.SetExplored(m_packedCoord, cellInfo.ExploredDirections);

            // Set all the components as expanded
            for (int i = 0; i < cellInfo.ComponentNum; ++i)
            {
                int componentIndex = cellInfo.StartingIndex + i;
                var component      = m_mesh.HighLevelGroup.GetPrimitive(componentIndex);
                if (component != null)
                {
                    component.IsExpanded = true;
                }
            }

            ProfilerShort.End();
        }
示例#12
0
        private static unsafe void ReadRange(
            MyStorageDataCache target,
            ref Vector3I targetWriteOffset,
            MyStorageDataTypeEnum type,
            int treeHeight,
            Dictionary <UInt64, MyOctreeNode> nodes,
            Dictionary <UInt64, IMyOctreeLeafNode> leaves,
            int lodIndex,
            ref Vector3I minInLod,
            ref Vector3I maxInLod)
        {
            int          stackIdx  = 0;
            int          stackSize = MySparseOctree.EstimateStackSize(treeHeight);
            MyCellCoord *stack     = stackalloc MyCellCoord[stackSize];
            MyCellCoord  data      = new MyCellCoord(treeHeight + LeafLodCount, ref Vector3I.Zero);

            stack[stackIdx++] = data;
            MyCellCoord cell = new MyCellCoord();

            while (stackIdx > 0)
            {
                Debug.Assert(stackIdx <= stackSize);
                data = stack[--stackIdx];

                cell.Lod        = data.Lod - LeafLodCount;
                cell.CoordInLod = data.CoordInLod;

                int lodDiff;
                IMyOctreeLeafNode leaf;
                if (leaves.TryGetValue(cell.PackId64(), out leaf))
                {
                    lodDiff = data.Lod - lodIndex;
                    var rangeMinInDataLod = minInLod >> lodDiff;
                    var rangeMaxInDataLod = maxInLod >> lodDiff;
                    if (data.CoordInLod.IsInsideInclusive(ref rangeMinInDataLod, ref rangeMaxInDataLod))
                    {
                        var nodePosInLod = data.CoordInLod << lodDiff;
                        var writeOffset  = nodePosInLod - minInLod;
                        Vector3I.Max(ref writeOffset, ref Vector3I.Zero, out writeOffset);
                        writeOffset += targetWriteOffset;
                        var lodSizeMinusOne = new Vector3I((1 << lodDiff) - 1);
                        var minInLeaf       = Vector3I.Clamp(minInLod - nodePosInLod, Vector3I.Zero, lodSizeMinusOne);
                        var maxInLeaf       = Vector3I.Clamp(maxInLod - nodePosInLod, Vector3I.Zero, lodSizeMinusOne);
                        leaf.ReadRange(target, ref writeOffset, lodIndex, ref minInLeaf, ref maxInLeaf);
                    }
                    continue;
                }

                cell.Lod -= 1;
                lodDiff   = data.Lod - 1 - lodIndex;
                var node = nodes[cell.PackId64()];

                var min = minInLod >> lodDiff;
                var max = maxInLod >> lodDiff;
                var nodePositionInChild = data.CoordInLod << 1;
                min -= nodePositionInChild;
                max -= nodePositionInChild;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    Vector3I childPosRelative;
                    ComputeChildCoord(i, out childPosRelative);
                    if (!childPosRelative.IsInsideInclusive(ref min, ref max))
                    {
                        continue;
                    }
                    if (lodIndex < data.Lod && node.HasChild(i))
                    {
                        Debug.Assert(stackIdx < stackSize);
                        stack[stackIdx++] = new MyCellCoord(data.Lod - 1, nodePositionInChild + childPosRelative);
                    }
                    else
                    {
                        var childMin = nodePositionInChild + childPosRelative;
                        childMin <<= lodDiff;
                        var writeOffset = childMin - minInLod;
                        Vector3I.Max(ref writeOffset, ref Vector3I.Zero, out writeOffset);
                        writeOffset += targetWriteOffset;
                        var nodeData = node.GetData(i);
                        if (lodDiff == 0)
                        {
                            target.Set(type, ref writeOffset, nodeData);
                        }
                        else
                        {
                            var childMax = childMin + ((1 << lodDiff) - 1);
                            Vector3I.Max(ref childMin, ref minInLod, out childMin);
                            Vector3I.Min(ref childMax, ref maxInLod, out childMax);
                            for (int z = childMin.Z; z <= childMax.Z; ++z)
                            {
                                for (int y = childMin.Y; y <= childMax.Y; ++y)
                                {
                                    for (int x = childMin.X; x <= childMax.X; ++x)
                                    {
                                        Vector3I write = writeOffset;
                                        write.X += x - childMin.X;
                                        write.Y += y - childMin.Y;
                                        write.Z += z - childMin.Z;
                                        target.Set(type, ref write, nodeData);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
示例#13
0
        private static bool ResetOutsideBorders(
            IMyStorageDataProvider provider,
            MyStorageDataTypeEnum dataType,
            int lodIdx,
            Dictionary <UInt64, MyOctreeNode> nodes,
            Dictionary <UInt64, IMyOctreeLeafNode> leaves,
            Vector3I lodCoord,
            Vector3I minVoxel,
            Vector3I maxVoxel,
            out bool canCollapse,
            Dictionary <UInt64, IMyOctreeLeafNode> outResetLeaves = null)
        {
            canCollapse = false;

            bool changed = false;

            var currentCell = new MyCellCoord(lodIdx, lodCoord);
            var key         = currentCell.PackId64();
            var leafCell    = currentCell;
            var leafKey     = leafCell.PackId64();

            IMyOctreeLeafNode leaf;

            if (leaves.TryGetValue(leafKey, out leaf))
            {
                canCollapse = leaf.ReadOnly;

                if (leafCell.Lod != 0)
                {
                    Debug.Assert(leaf.ReadOnly);
                    return(false);
                }
                else if (!leaf.ReadOnly)
                {
                    var minCell = minVoxel >> (LeafLodCount + leafCell.Lod);
                    var maxCell = maxVoxel >> (LeafLodCount + leafCell.Lod);

                    if (!leafCell.CoordInLod.IsInsideInclusive(ref minCell, ref maxCell))
                    {
                        canCollapse = true;

                        leaves.Remove(leafKey);
                        var leafCellCopy = leafCell;
                        leafCellCopy.Lod += LeafLodCount;
                        var leafNew = new MyProviderLeaf(provider, dataType, ref leafCellCopy);
                        leaves.Add(leafKey, leafNew);

                        changed = true;

                        if (outResetLeaves != null)
                        {
                            outResetLeaves.Add(leafKey, leafNew);
                        }
                    }
                }
            }
            else
            {
                currentCell.Lod -= 1;
                key              = currentCell.PackId64();
                var nodeCell = currentCell;

                var nodeKey = currentCell.PackId64();
                var node    = nodes[nodeKey];

                var      childBase = lodCoord << 1;
                Vector3I childOffset;
                var      minInChild = (minVoxel >> (LeafLodCount + currentCell.Lod)) - childBase;
                var      maxInChild = (maxVoxel >> (LeafLodCount + currentCell.Lod)) - childBase;
                var      leafSize   = LeafSizeInVoxels << currentCell.Lod;

                unsafe
                {
                    canCollapse = true;

                    for (int i = 0; i < MyOctreeNode.CHILD_COUNT; i++)
                    {
                        ComputeChildCoord(i, out childOffset);
                        if (childOffset.IsInsideExclusive(ref minInChild, ref maxInChild))
                        {
                            canCollapse = false;
                            continue;
                        }

                        currentCell.CoordInLod = childBase + childOffset;

                        if (node.HasChild(i))
                        {
                            bool localCanCollapse;
                            bool resetChanged = ResetOutsideBorders(provider, dataType, currentCell.Lod, nodes, leaves, currentCell.CoordInLod, minVoxel, maxVoxel, out localCanCollapse, outResetLeaves: outResetLeaves);
                            changed = changed || resetChanged;

                            canCollapse = localCanCollapse && canCollapse;
                        }
                        else
                        {
                            var currentCellCopy = currentCell;
                            currentCellCopy.Lod += LeafLodCount;
                            IMyOctreeLeafNode octreeLeaf = new MyProviderLeaf(provider, dataType, ref currentCellCopy);
                            leaves.Add(currentCell.PackId64(), octreeLeaf);
                            node.SetChild(i, true);
                            node.SetData(i, octreeLeaf.GetFilteredValue());

                            changed = true;
                        }
                    }
                    nodes[nodeKey] = node;

                    if (canCollapse)
                    {
                        // Remove leaves
                        for (int i = 0; i < MyOctreeNode.CHILD_COUNT; i++)
                        {
                            if (node.HasChild(i))
                            {
                                ComputeChildCoord(i, out childOffset);
                                currentCell.CoordInLod = childBase + childOffset;

                                var childKey = currentCell.PackId64();
                                leaves.Remove(childKey);
                                node.SetChild(i, false);
                            }
                        }

                        // Remove node
                        nodes.Remove(nodeKey);

                        // Add leaf
                        var leafCellCopy = leafCell;
                        leafCellCopy.Lod += LeafLodCount;
                        var leafNew = new MyProviderLeaf(provider, dataType, ref leafCellCopy);
                        leaves.Add(leafKey, leafNew);
                    }
                }
            }

            return(changed);
        }
示例#14
0
        private static ulong CountChangedVoxelsAmount(
            MyOctreeStorage baseStorage,
            int lodIdx,
            Dictionary <UInt64, MyOctreeNode> nodes,
            Dictionary <UInt64, IMyOctreeLeafNode> leaves,
            Vector3I lodCoord)
        {
            var currentCell = new MyCellCoord(lodIdx, lodCoord);
            var leafKey     = currentCell.PackId64();

            IMyOctreeLeafNode leaf;

            if (leaves.TryGetValue(leafKey, out leaf))
            {
                if (!leaf.ReadOnly && currentCell.Lod == 0)
                {
                    // Read data from leaf
                    var rangeEnd = new Vector3I(LeafSizeInVoxels - 1);
                    m_temporaryCache.Resize(Vector3I.Zero, rangeEnd);
                    leaf.ReadRange(m_temporaryCache, ref Vector3I.Zero, 0, ref Vector3I.Zero, ref rangeEnd);

                    // Read data from base storage
                    var minLeafVoxel = currentCell.CoordInLod * LeafSizeInVoxels;
                    var maxLeafVoxel = minLeafVoxel + (LeafSizeInVoxels - 1);
                    m_temporaryCache2.Resize(minLeafVoxel, maxLeafVoxel);
                    baseStorage.ReadRange(m_temporaryCache2, MyStorageDataTypeFlags.Content, currentCell.Lod, ref minLeafVoxel, ref maxLeafVoxel);

                    byte[] origData = m_temporaryCache2.Data;
                    byte[] currData = m_temporaryCache.Data;

                    Debug.Assert(currData.Length == origData.Length);

                    if (currData.Length != origData.Length)
                    {
                        return(0);
                    }

                    ulong countChangedVoxels = 0;
                    for (int i = (int)MyStorageDataTypeEnum.Content; i < m_temporaryCache.SizeLinear; i += m_temporaryCache.StepLinear)
                    {
                        countChangedVoxels += (ulong)Math.Abs(currData[i] - origData[i]);
                    }

                    return(countChangedVoxels);
                }
            }
            else
            {
                currentCell.Lod -= 1;

                var nodeKey = currentCell.PackId64();
                var node    = nodes[nodeKey];

                var      childBase = lodCoord << 1;
                Vector3I childOffset;

                if (node.HasChildren)
                {
                    ulong count = 0;

                    for (int i = 0; i < MyOctreeNode.CHILD_COUNT; i++)
                    {
                        if (node.HasChild(i))
                        {
                            ComputeChildCoord(i, out childOffset);
                            currentCell.CoordInLod = childBase + childOffset;

                            count += CountChangedVoxelsAmount(baseStorage, currentCell.Lod, nodes, leaves, currentCell.CoordInLod);
                        }
                    }

                    return(count);
                }
                else
                {
                    return((ulong)((MyOctreeNode.CHILD_COUNT << (currentCell.Lod * 3)) * LeafSizeInVoxels * LeafSizeInVoxels * LeafSizeInVoxels * MyVoxelConstants.VOXEL_CONTENT_FULL));
                }
            }

            return(0);
        }
示例#15
0
        private unsafe void WriteRange(
            MyCellCoord cell,
            TLeafData defaultData,
            MyStorageData source,
            MyStorageDataTypeEnum type,
            ref Vector3I readOffset,
            ref Vector3I min,
            ref Vector3I max)
        {
            var          nodeKey = cell.PackId32();
            MyOctreeNode node;

            if (!m_nodes.TryGetValue(nodeKey, out node))
            {
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    node.Data[i] = defaultData;
                }
            }

            if (cell.Lod == 0)
            {
                var      childBase = cell.CoordInLod << 1;
                Vector3I childOffset;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    ComputeChildCoord(i, out childOffset);
                    var child = childBase + childOffset;
                    if (!child.IsInsideInclusive(ref min, ref max))
                    {
                        continue;
                    }

                    child       -= min;
                    child       += readOffset;
                    node.Data[i] = source.Get(type, ref child);
                }
                m_nodes[nodeKey] = node;
            }
            else
            {
                var      childBase = cell.CoordInLod << 1;
                Vector3I childOffset;
                var      minInChild = (min >> cell.Lod) - childBase;
                var      maxInChild = (max >> cell.Lod) - childBase;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    ComputeChildCoord(i, out childOffset);
                    if (!childOffset.IsInsideInclusive(ref minInChild, ref maxInChild))
                    {
                        continue;
                    }

                    var childCell = new MyCellCoord(cell.Lod - 1, childBase + childOffset);
                    WriteRange(childCell, node.Data[i], source, type, ref readOffset, ref min, ref max);
                    var childKey  = childCell.PackId32();
                    var childNode = m_nodes[childKey];
                    if (!childNode.HasChildren && MyOctreeNode.AllDataSame(childNode.Data))
                    {
                        node.SetChild(i, false);
                        node.Data[i] = childNode.Data[0];
                        m_nodes.Remove(childKey);
                    }
                    else
                    {
                        node.SetChild(i, true);
                        node.Data[i] = m_nodeFilter(childNode.Data, cell.Lod);
                    }
                }

                m_nodes[nodeKey] = node;
            }
        }
示例#16
0
            internal void SetCellMesh(MyRenderMessageUpdateClipmapCell msg)
            {
                var cellId = msg.Metadata.Cell.PackId64();
                MyClipmap_CellData data;
                var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_clipmap.Id, cellId);

                //  MyCellCoord cellc = new MyCellCoord();
                //  cellc.SetUnpack(cellId);

                //MyLog.Default.WriteLine("SetCellMesh Lod: " + cellc.Lod + " Coord: " + cellc.CoordInLod);

                if (m_storedCellData.TryGetValue(cellId, out data))
                {
                    PendingCacheCellData.Remove(clipmapCellId);

                    if (data.State == CellState.Invalid)
                    {
//                        MyLog.Default.WriteLine("Invalid");
                        //Cell was invalidated while calculating from old data
                        return;
                    }

                    if (data.Cell == null && msg.Batches.Count != 0)
                    {
                        //MyLog.Default.WriteLine("added to nonempty");
                        data.Cell = m_clipmap.m_cellHandler.CreateCell(m_clipmap.m_scaleGroup, msg.Metadata.Cell, ref m_clipmap.m_worldMatrix);
                        System.Diagnostics.Debug.Assert(data.Cell != null, "Cell not created");
                        if (data.Cell != null)
                        {
                            if (data.Cell.IsValid())
                            {
                                data.CellHandler        = m_clipmap.m_cellHandler;
                                m_nonEmptyCells[cellId] = data;
                            }
                        }
                    }
                    else if (data.Cell != null && msg.Batches.Count == 0)
                    {
                        //MyLog.Default.WriteLine("removed");
                        RemoveFromScene(cellId, data);
                        m_nonEmptyCells.Remove(cellId);
                        m_clipmap.m_cellHandler.DeleteCell(data.Cell);
                        m_blendedCells.Remove(cellId);
                        data.Cell        = null;
                        data.CellHandler = null;
                        if (UseCache)
                        {
                            CellsCache.Remove(cellId);
                        }
                    }

                    if (data.Cell != null)
                    {
                        //MyLog.Default.WriteLine("mesh updated");
                        if (data.Cell.IsValid())
                        {
                            m_clipmap.m_cellHandler.UpdateMesh(data.Cell, msg);
                        }
                    }
                    data.State     = CellState.Loaded;
                    data.WasLoaded = true;
                }
                else
                if (PendingCacheCellData.TryGetValue(clipmapCellId, out data))
                {
                    if (msg.Batches.Count != 0)
                    {
                        data.Cell = m_clipmap.m_cellHandler.CreateCell(m_clipmap.m_scaleGroup, msg.Metadata.Cell, ref m_clipmap.m_worldMatrix);
                        m_clipmap.m_cellHandler.UpdateMesh(data.Cell, msg);
                        data.CellHandler = m_clipmap.m_cellHandler;
                    }

                    CellsCache.Write(clipmapCellId, data);
                    PendingCacheCellData.Remove(clipmapCellId);

                    data.State     = CellState.Loaded;
                    data.WasLoaded = true;
                }
            }
示例#17
0
        internal unsafe ContainmentType Intersect(ref BoundingBoxI box, bool lazy)
        {
            int          stackIdx  = 0;
            int          stackSize = MySparseOctree.EstimateStackSize(m_treeHeight);
            MyCellCoord *stack     = stackalloc MyCellCoord[stackSize];
            MyCellCoord  data      = new MyCellCoord(m_treeHeight - 1, ref Vector3I.Zero);

            stack[stackIdx++] = data;

            Vector3I minInLod = box.Min;
            Vector3I maxInLod = box.Max;

            MyOctreeNode node;
            Vector3I     childPosRelative, min, max, nodePositionInChild;
            int          lodDiff;

            // TODO(DI): Add support for checking for containment somehow, this needs neighbourhood information which kinda sucks.

            ContainmentType cont = ContainmentType.Disjoint;

            while (stackIdx > 0)
            {
                Debug.Assert(stackIdx <= stackSize);
                data = stack[--stackIdx];
                node = m_nodes[data.PackId32()];

                lodDiff             = data.Lod;
                min                 = minInLod >> lodDiff;
                max                 = maxInLod >> lodDiff;
                nodePositionInChild = data.CoordInLod << 1;
                min                -= nodePositionInChild;
                max                -= nodePositionInChild;
                for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                {
                    ComputeChildCoord(i, out childPosRelative);
                    if (!childPosRelative.IsInsideInclusive(ref min, ref max))
                    {
                        continue;
                    }
                    if (data.Lod > 0 && node.HasChild(i))
                    {
                        Debug.Assert(stackIdx < stackSize);
                        stack[stackIdx++] = new MyCellCoord(data.Lod - 1, nodePositionInChild + childPosRelative);
                    }
                    else
                    {
                        var nodeData = node.Data[i];
                        if (lodDiff == 0)
                        {
                            if (nodeData != 0)
                            {
                                return(ContainmentType.Intersects);
                            }
                        }
                        else
                        {
                            BoundingBoxI nodeBox;
                            nodeBox.Min   = nodePositionInChild + childPosRelative;
                            nodeBox.Min <<= lodDiff;
                            nodeBox.Max   = nodeBox.Min + (1 << lodDiff) - 1;
                            Vector3I.Max(ref nodeBox.Min, ref minInLod, out nodeBox.Min);
                            Vector3I.Min(ref nodeBox.Max, ref maxInLod, out nodeBox.Max);

                            bool res;
                            nodeBox.Intersects(ref nodeBox, out res);

                            if (res)
                            {
                                return(ContainmentType.Intersects);
                            }
                        }
                    }
                }
            }

            return(cont);
        }
示例#18
0
            public void DebugDraw()
            {
                //if (m_lodIndex > 5)
                //    return;


                //            if (m_lodIndex == 1)
                //            {
                //                float sizeInMetres = MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex);

                //                //var start = localFarCameraBox.Min;
                //                //var end = localFarCameraBox.Max;
                //                var start = m_localNearCameraBox.Min;
                //                var end = m_localNearCameraBox.Max;
                //                Vector3I coord = start;

                //                Color nearColor = Color.Yellow;
                //                Color farColor = Color.White;

                //                var startF = m_localFarCameraBox.Min;
                //                var endF = m_localFarCameraBox.Max;
                //                Vector3I coordF = startF;

                ////                for (var it = new Vector3I_RangeIterator(ref startF, ref endF);
                ////it.IsValid(); it.GetNext(out coordF))
                ////                {
                ////                    Vector3D min = Vector3D.Transform((Vector3D)(sizeInMetres * coordF), m_parent.m_worldMatrix);
                ////                    Vector3D max = Vector3D.Transform((Vector3D)(sizeInMetres * coordF + new Vector3(sizeInMetres)), m_parent.m_worldMatrix);

                ////                    BoundingBoxD aabb = new BoundingBoxD(min, max);
                ////                    MyRenderProxy.DebugDrawAABB(aabb, farColor, 1, 1, false);

                ////                    if (Vector3D.Distance(CameraFrustumGetter().Matrix.Translation, aabb.Center) < 200)
                ////                        MyRenderProxy.DebugDrawText3D(aabb.Center, coordF.ToString(), farColor, 0.5f, false);
                ////                }


                //                for (var it = new Vector3I_RangeIterator(ref start, ref end);
                //it.IsValid(); it.GetNext(out coord))
                //                {
                //                    Vector3D min = Vector3D.Transform((Vector3D)(sizeInMetres * coord), m_clipmap.m_worldMatrix);
                //                    Vector3D max = Vector3D.Transform((Vector3D)(sizeInMetres * coord + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix);

                //                    BoundingBoxD aabb = new BoundingBoxD(min, max);
                //                    MyRenderProxy.DebugDrawAABB(aabb, nearColor, 1, 1, false);
                //                }


                //                Vector3D center = Vector3D.Transform(m_localPosition, m_clipmap.m_worldMatrix);

                //                MyRenderProxy.DebugDrawSphere(center, m_nearDistance, nearColor, 1, false);
                //                MyRenderProxy.DebugDrawSphere(center, m_farDistance, farColor, 1, false);

                //            }

                var camera = m_clipmap.LastCameraPosition;

                //if (m_lodIndex < 6)
                {
                    float sizeInMetres = MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex);
                    Color color        = LOD_COLORS[m_lodIndex] + new Vector4(0.2f);


                    foreach (var cell in m_storedCellData)
                    {
                        if (!cell.Value.InScene)
                        {
                            continue;
                        }

                        MyCellCoord cellStr = new MyCellCoord();
                        cellStr.SetUnpack(cell.Key);
                        var coordF = cellStr.CoordInLod;

                        Vector3D min = Vector3D.Transform((Vector3D)(sizeInMetres * coordF), m_clipmap.m_worldMatrix);
                        Vector3D max = Vector3D.Transform((Vector3D)(sizeInMetres * coordF + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix);

                        BoundingBoxD aabb     = new BoundingBoxD(min, max);
                        double       distance = Vector3D.Distance(camera, aabb.Center);
                        //if (distance < sizeInMetres * 4)
                        MyRenderProxy.DebugDrawAABB(aabb, color, 1, 1, true);
                        if (distance < sizeInMetres * 2)
                        {
                            MyRenderProxy.DebugDrawText3D(aabb.Center, String.Format("{0}:{1}", m_lodIndex, coordF.ToString()), color, 0.7f, false);
                        }
                    }

                    if (m_storedCellData.Count > 0)
                    {
                        Vector3D center = Vector3D.Transform(m_localPosition, m_clipmap.m_worldMatrix);
                        //MyRenderProxy.DebugDrawSphere(center, m_farDistance, color, 1, false);
                    }
                }
            }
示例#19
0
        private unsafe void AddVoxelMesh(MyVoxelBase voxelBase, IMyStorage storage, Dictionary <Vector3I, MyIsoMesh> cache, float border, Vector3D originPosition, MyOrientedBoundingBoxD obb, List <BoundingBoxD> bbList)
        {
            Vector3I vectori3;
            Vector3I vectori4;
            bool     flag = cache != null;

            if (flag)
            {
                this.CheckCacheValidity();
            }
            Vector3D *vectordPtr1 = (Vector3D *)ref obb.HalfExtent;

            vectordPtr1[0] += new Vector3D((double)border, 0.0, (double)border);
            BoundingBoxD  aABB   = obb.GetAABB();
            int           num    = (int)Math.Round((double)(aABB.HalfExtents.Max() * 2.0));
            BoundingBoxD *xdPtr1 = (BoundingBoxD *)ref aABB;

            xdPtr1 = (BoundingBoxD *)new BoundingBoxD(aABB.Min, aABB.Min + num);
            ((BoundingBoxD *)ref aABB).Translate(obb.Center - aABB.Center);
            bbList.Add(new BoundingBoxD(aABB.Min, aABB.Max));
            aABB = aABB.TransformFast(voxelBase.PositionComp.WorldMatrixInvScaled);
            aABB.Translate(voxelBase.SizeInMetresHalf);
            Vector3I voxelCoord = Vector3I.Round(aABB.Min);
            Vector3I vectori2   = (Vector3I)(voxelCoord + num);

            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref voxelCoord, out vectori3);
            MyVoxelCoordSystems.VoxelCoordToGeometryCellCoord(ref vectori2, out vectori4);
            MyOrientedBoundingBoxD xd2 = obb;

            xd2.Transform(voxelBase.PositionComp.WorldMatrixInvScaled);
            Vector3D *vectordPtr2 = (Vector3D *)ref xd2.Center;

            vectordPtr2[0] += voxelBase.SizeInMetresHalf;
            Vector3I_RangeIterator iterator = new Vector3I_RangeIterator(ref vectori3, ref vectori4);
            MyCellCoord            coord    = new MyCellCoord {
                Lod = 0
            };
            int     num2        = 0;
            Vector3 offset      = (Vector3)(originPosition - voxelBase.PositionLeftBottomCorner);
            Vector3 up          = -Vector3.Normalize(MyGravityProviderSystem.CalculateTotalGravityInPoint(originPosition));
            Matrix  rotation    = Matrix.CreateFromQuaternion(Quaternion.Inverse(Quaternion.CreateFromForwardUp(Vector3.CalculatePerpendicularVector(up), up)));
            Matrix  orientation = (Matrix)voxelBase.PositionComp.WorldMatrix.GetOrientation();

            while (iterator.IsValid())
            {
                BoundingBox box;
                MyIsoMesh   mesh;
                if (flag && cache.TryGetValue(iterator.Current, out mesh))
                {
                    if (mesh != null)
                    {
                        this.AddMeshTriangles(mesh, offset, rotation, orientation);
                    }
                    iterator.MoveNext();
                    continue;
                }
                coord.CoordInLod = iterator.Current;
                MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref coord.CoordInLod, out box);
                if (!xd2.Intersects(ref box))
                {
                    num2++;
                    iterator.MoveNext();
                }
                else
                {
                    BoundingBoxD item = new BoundingBoxD(box.Min, box.Max).Translate(-voxelBase.SizeInMetresHalf);
                    bbList.Add(item);
                    Vector3I  lodVoxelMin = (coord.CoordInLod * 8) - 1;
                    MyIsoMesh mesh2       = MyPrecalcComponent.IsoMesher.Precalc(storage, 0, lodVoxelMin, (Vector3I)(((lodVoxelMin + 8) + 1) + 1), MyStorageDataTypeFlags.Content, 0);
                    if (flag)
                    {
                        cache[iterator.Current] = mesh2;
                    }
                    if (mesh2 != null)
                    {
                        this.AddMeshTriangles(mesh2, offset, rotation, orientation);
                    }
                    iterator.MoveNext();
                }
            }
        }
示例#20
0
            internal void DoClipping(float camDistanceFromCenter, Vector3D localPosition, float farPlaneDistance, RequestCollector collector, bool frustumCulling, float rangeScale)
            {
                int lodIndex = m_lodIndex;

                if (!ShouldBeThisLodVisible(camDistanceFromCenter))
                {
                    MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                    m_storedCellData.Clear();
                    return;
                }


                m_localPosition = localPosition;
                MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, lodIndex, out m_nearDistance, out m_farDistance);


                farPlaneDistance *= rangeScale;
                m_farDistance    *= rangeScale;
                m_nearDistance   *= rangeScale;

                m_fitsInFrustum = (farPlaneDistance * 1.25f) > m_nearDistance;

                if (!m_fitsInFrustum && m_lodIndex == lodIndex)
                {
                    return;
                }


                //var localFrustum = new BoundingFrustumD(CameraFrustumGetter().Matrix * m_parent.m_invWorldMatrix);
                var frustum = CameraFrustumGetter();

                Vector3I min, max;
                // Vector3I ignoreMin, ignoreMax;

                var minD = m_localPosition - (double)m_farDistance;
                var maxD = m_localPosition + (double)m_farDistance;

                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(lodIndex, ref minD, out min);
                MyVoxelCoordSystems.LocalPositionToRenderCellCoord(lodIndex, ref maxD, out max);

                BoundingBoxI lodBox     = new BoundingBoxI(Vector3I.Zero, Vector3I.Max(m_lodSizeMinusOne, Vector3I.Zero));
                bool         intersects = false;

                //bool intersectsNear = false;

                m_localFarCameraBox  = new BoundingBoxI(min, max);
                m_localNearCameraBox = new BoundingBoxI(min, max);
                if (lodBox.Intersects(m_localFarCameraBox))
                {
                    intersects = true;
                    var intersection = lodBox;
                    intersection.IntersectWith(ref m_localFarCameraBox);
                    min = intersection.Min;
                    max = intersection.Max;

                    //Optimize only LOD2 and higher by two lods, because neighbour cells shares border cells
                    //if (m_lodIndex > 1)
                    //{
                    //    float lowerFar, lowerNear;
                    //    MyClipmap.ComputeLodViewBounds(m_clipmap.m_scaleGroup, m_lodIndex - 2, out lowerFar, out lowerNear);

                    //    var minNear = m_localPosition - (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                    //    var maxNear = m_localPosition + (lowerNear - MyVoxelCoordSystems.RenderCellSizeInMeters(m_lodIndex) / 2);
                    //    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref minNear, out ignoreMin);
                    //    MyVoxelCoordSystems.LocalPositionToRenderCellCoord(m_lodIndex, ref maxNear, out ignoreMax);

                    //    m_localNearCameraBox = new BoundingBoxI(ignoreMin, ignoreMax);
                    //    if (lodBox.Intersects(m_localNearCameraBox))
                    //        intersectsNear = false;
                    //}
                }

                //if (m_lastMin == min && m_lastMax == max && !m_clipmap.m_updateClipping)
                //    return;

                //m_lastMin = min;
                //m_lastMax = max;

                //LodLevel parentLod, childLod;
                //GetNearbyLodLevels(out parentLod, out childLod);

                // Moves cells which are still needed from one collection to another.
                // All that is left behind is unloaded as no longer needed.

                // Move everything in range to collection of next stored cells.

                if (frustumCulling)
                {
                    MyUtils.Swap(ref m_storedCellData, ref m_clippedCells);
                    m_storedCellData.Clear();
                }

                if (intersects)
                {
                    float sizeInMetres = MyVoxelCoordSystems.RenderCellSizeInMeters(lodIndex);


                    MyCellCoord cell = new MyCellCoord(lodIndex, ref min);

                    for (var it = new Vector3I_RangeIterator(ref min, ref max);
                         it.IsValid(); it.GetNext(out cell.CoordInLod))
                    {
                        //if (intersectsNear &&
                        //    m_localNearCameraBox.Contains(cell.CoordInLod) == ContainmentType.Contains)
                        //    continue;

                        //if (frustumCulling)
                        //{
                        //    Vector3D minAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod - 2)), m_clipmap.m_worldMatrix);
                        //    Vector3D maxAABB = Vector3D.Transform((Vector3D)(sizeInMetres * (cell.CoordInLod + 2) + new Vector3(sizeInMetres)), m_clipmap.m_worldMatrix);

                        //    if (frustum.Contains(new BoundingBoxD(minAABB, maxAABB)) == ContainmentType.Disjoint)
                        //    {
                        //        m_outsideCells.Add(cell.CoordInLod);
                        //        continue;
                        //    }
                        //}

                        UnclipCell(collector, cell, true);
                    }

                    //cache cells around frustum
                    if (collector.SentRequestsEmpty)
                    {
                        foreach (var outsideCell in m_outsideCells)
                        {
                            cell.CoordInLod = outsideCell;
                            UnclipCell(collector, cell, frustumCulling);
                        }
                    }

                    m_outsideCells.Clear();
                }
            }
示例#21
0
        internal static void QueueJobCancel(MyWorkTracker <MyCellCoord, MyPrecalcJobPhysicsPrefetch> tracker, MyCellCoord id)
        {
            var threadCommandBuffer = ThreadCommandBuffer;

            lock (threadCommandBuffer)
            {
                ThreadCommandBuffer.Add(new JobCancelCommand
                {
                    Tracker = tracker,
                    Id      = id,
                });
            }
        }
示例#22
0
        internal unsafe void DebugDraw(IMyDebugDrawBatchAabb batch, Vector3 worldPos, MyVoxelDebugDrawMode mode)
        {
            Color?nullable;

            if (mode == MyVoxelDebugDrawMode.Content_MicroNodes)
            {
                foreach (KeyValuePair <uint, MyOctreeNode> pair in this.m_nodes)
                {
                    MyCellCoord coord = new MyCellCoord();
                    coord.SetUnpack(pair.Key);
                    MyOctreeNode node = pair.Value;
                    for (int i = 0; i < 8; i++)
                    {
                        if (!node.HasChild(i) || (coord.Lod == 0))
                        {
                            Vector3I     vectori;
                            BoundingBoxD xd;
                            this.ComputeChildCoord(i, out vectori);
                            Vector3I vectori2 = (Vector3I)((coord.CoordInLod << (coord.Lod + 1)) + (vectori << coord.Lod));
                            xd.Min = worldPos + (vectori2 * 1f);
                            BoundingBoxD *xdPtr1 = (BoundingBoxD *)ref xd;
                            xdPtr1->Max = xd.Min + (1f * (1 << (coord.Lod & 0x1f)));
                            if (node.GetData(i) != 0)
                            {
                                nullable = null;
                                batch.Add(ref xd, nullable);
                            }
                        }
                    }
                }
                return;
            }
            else if (mode != MyVoxelDebugDrawMode.Content_MicroNodesScaled)
            {
                return;
            }
            foreach (KeyValuePair <uint, MyOctreeNode> pair2 in this.m_nodes)
            {
                MyCellCoord coord2 = new MyCellCoord();
                coord2.SetUnpack(pair2.Key);
                MyOctreeNode node2 = pair2.Value;
                for (int i = 0; i < 8; i++)
                {
                    if (!node2.HasChild(i))
                    {
                        Vector3I vectori3;
                        this.ComputeChildCoord(i, out vectori3);
                        float num3 = ((float)node2.GetData(i)) / 255f;
                        if (num3 != 0f)
                        {
                            BoundingBoxD xd2;
                            num3 = (float)Math.Pow(num3 * 1.0, 0.3333);
                            Vector3I vectori4 = (Vector3I)((coord2.CoordInLod << (coord2.Lod + 1)) + (vectori3 << coord2.Lod));
                            float    num4     = 1f * (1 << (coord2.Lod & 0x1f));
                            Vector3  vector   = (worldPos + (vectori4 * 1f)) + (0.5f * num4);
                            xd2.Min  = vector - ((0.5f * num3) * num4);
                            xd2.Max  = vector + ((0.5f * num3) * num4);
                            nullable = null;
                            batch.Add(ref xd2, nullable);
                        }
                    }
                }
            }
        }
        public override void DoWork()
        {
            ProfilerShort.Begin("MyPrecalcJobRender.DoWork");
            try
            {
                if (m_isCancelled)
                    return;

                m_metadata.Cell = m_args.Cell;
                m_metadata.LocalAabb = BoundingBox.CreateInvalid();

                var cellSize = MyVoxelCoordSystems.RenderCellSizeInLodVoxels(m_args.Cell.Lod);
                var min = m_args.Cell.CoordInLod * cellSize - 1;
                var max = min + cellSize - 1
                    + 1 // overlap to neighbor so geometry is stitched together within same LOD
                    + 1 // extra overlap so there are more vertices for mapping to parent LOD
                    + 1; // for eg. 9 vertices in row we need 9 + 1 samples (voxels)
                //    + 1 // why not
                //  + 1 // martin kroslak approved

                var clipmapCellId = MyCellCoord.GetClipmapCellHash(m_args.ClipmapId, m_args.Cell.PackId64());
                MyIsoMesh highResMesh = IsoMeshCache.Read(clipmapCellId);

                if (highResMesh == null)
                {
                    highResMesh = MyPrecalcComponent.IsoMesher.Precalc(m_args.Storage, m_args.Cell.Lod, min, max, true, MyFakes.ENABLE_VOXEL_COMPUTED_OCCLUSION);
                    if (UseIsoCache && highResMesh != null)
                        IsoMeshCache.Write(clipmapCellId, highResMesh);
                }

                if (m_isCancelled || highResMesh == null)
                    return;

                MyIsoMesh lowResMesh = null;

                if (m_args.Cell.Lod < 15 && MyFakes.ENABLE_VOXEL_LOD_MORPHING)
                {
                    var nextLodCell = m_args.Cell;
                    nextLodCell.Lod++;
                    clipmapCellId = MyCellCoord.GetClipmapCellHash(m_args.ClipmapId, nextLodCell.PackId64());

                    lowResMesh = IsoMeshCache.Read(clipmapCellId);

                    if (lowResMesh == null)
                    {
                        // Less detailed mesh for vertex morph targets
                        min >>= 1;
                        max >>= 1;
                        min -= 1;
                        max += 2;

                        lowResMesh = MyPrecalcComponent.IsoMesher.Precalc(m_args.Storage, m_args.Cell.Lod + 1, min, max, true, MyFakes.ENABLE_VOXEL_COMPUTED_OCCLUSION);

                        if (UseIsoCache && lowResMesh != null)
                            IsoMeshCache.Write(clipmapCellId, lowResMesh);
                    }
                }

                if (m_isCancelled)
                    return;

                RenderCellBuilder.BuildCell(m_args, highResMesh, lowResMesh, m_batches, out m_metadata);
            }
            finally
            {
                ProfilerShort.End();
            }
        }
示例#24
0
        internal unsafe ContainmentType Intersect(ref BoundingBoxI box, int lod, bool exhaustiveContainmentCheck = true)
        {
            MyCellCoord *coordPtr = (MyCellCoord *)stackalloc byte[(((IntPtr)EstimateStackSize(this.m_treeHeight)) * sizeof(MyCellCoord))];
            MyCellCoord  coord    = new MyCellCoord(this.m_treeHeight - 1, ref Vector3I.Zero);
            int          index    = 0 + 1;

            coordPtr[index] = coord;
            Vector3I        min      = box.Min;
            Vector3I        max      = box.Max;
            ContainmentType disjoint = ContainmentType.Disjoint;

            while (index > 0)
            {
                coord = coordPtr[--index];
                MyOctreeNode node     = this.m_nodes[coord.PackId32()];
                int          num3     = coord.Lod;
                Vector3I     vectori6 = coord.CoordInLod << 1;
                Vector3I     vectori4 = (min >> num3) - vectori6;
                Vector3I     vectori5 = (max >> num3) - vectori6;
                for (int i = 0; i < 8; i++)
                {
                    Vector3I vectori3;
                    this.ComputeChildCoord(i, out vectori3);
                    if (vectori3.IsInsideInclusiveEnd(ref vectori4, ref vectori5))
                    {
                        if ((coord.Lod > 0) && node.HasChild(i))
                        {
                            index++;
                            coordPtr[index] = new MyCellCoord(coord.Lod - 1, (Vector3I)(vectori6 + vectori3));
                        }
                        else
                        {
                            byte num5 = &node.Data.FixedElementField[i];
                            if (num3 == 0)
                            {
                                if (num5 != 0)
                                {
                                    return(ContainmentType.Intersects);
                                }
                            }
                            else
                            {
                                BoundingBoxI xi;
                                bool         flag;
                                xi.Min = (Vector3I)(vectori6 + vectori3);
                                Vector3I *vectoriPtr1 = (Vector3I *)ref xi.Min;
                                vectoriPtr1[0] = vectoriPtr1[0] << num3;
                                BoundingBoxI *xiPtr1 = (BoundingBoxI *)ref xi;
                                xiPtr1->Max = (Vector3I)((xi.Min + (1 << (num3 & 0x1f))) - 1);
                                Vector3I.Max(ref xi.Min, ref min, out xi.Min);
                                Vector3I.Min(ref xi.Max, ref max, out xi.Max);
                                ((BoundingBoxI *)ref xi).Intersects(ref xi, out flag);
                                if (flag)
                                {
                                    return(ContainmentType.Intersects);
                                }
                            }
                        }
                    }
                }
            }
            return(disjoint);
        }
        private bool AddCell(Vector3I cellPos)
        {
            MyCellCoord coord = new MyCellCoord(NAVMESH_LOD, cellPos);

            var geometry = m_voxelMap.Storage.Geometry;

            MyVoxelGeometry.CellData data = geometry.GetCell(ref coord);
            if (data == null)
            {
                m_processedCells.Add(ref cellPos);
                m_higherLevelHelper.AddExplored(ref cellPos);
                return(false);
            }

            ulong packedCoord = coord.PackId64();

            List <DebugDrawEdge> debugEdgesList = new List <DebugDrawEdge>();

            m_debugCellEdges[packedCoord] = debugEdgesList;

            MyVoxelPathfinding.CellId cellId = new MyVoxelPathfinding.CellId()
            {
                VoxelMap = m_voxelMap, Pos = cellPos
            };

            MyTrace.Send(TraceWindow.Ai, "Adding cell " + cellPos);

            m_connectionHelper.ClearCell();
            m_vertexMapping.Init(data.VoxelVerticesCount);

            // Prepare list of possibly intersecting cube grids for voxel-grid navmesh intersection testing
            Vector3D     bbMin  = m_voxelMap.PositionLeftBottomCorner + (m_cellSize * (new Vector3D(-0.125) + cellPos));
            Vector3D     bbMax  = m_voxelMap.PositionLeftBottomCorner + (m_cellSize * (Vector3D.One + cellPos));
            BoundingBoxD cellBB = new BoundingBoxD(bbMin, bbMax);

            m_tmpGridList.Clear();
            m_navmeshCoordinator.PrepareVoxelTriangleTests(cellBB, m_tmpGridList);

            Vector3D voxelMapCenter     = m_voxelMap.PositionComp.GetPosition();
            Vector3  centerDisplacement = voxelMapCenter - m_voxelMap.PositionLeftBottomCorner;

            // This is needed for correct edge classification - to tell, whether the edges are inner or outer edges of the cell
            ProfilerShort.Begin("Triangle preprocessing");
            for (int i = 0; i < data.VoxelTrianglesCount; i++)
            {
                short a = data.VoxelTriangles[i].VertexIndex0;
                short b = data.VoxelTriangles[i].VertexIndex1;
                short c = data.VoxelTriangles[i].VertexIndex2;

                Vector3 aPos, bPos, cPos;
                Vector3 vert;
                data.GetUnpackedPosition(a, out vert);
                aPos = vert - centerDisplacement;
                data.GetUnpackedPosition(b, out vert);
                bPos = vert - centerDisplacement;
                data.GetUnpackedPosition(c, out vert);
                cPos = vert - centerDisplacement;

                bool invalidTriangle = false;
                if ((bPos - aPos).LengthSquared() <= MyVoxelConnectionHelper.OUTER_EDGE_EPSILON_SQ)
                {
                    m_vertexMapping.Union(a, b);
                    invalidTriangle = true;
                }
                if ((cPos - aPos).LengthSquared() <= MyVoxelConnectionHelper.OUTER_EDGE_EPSILON_SQ)
                {
                    m_vertexMapping.Union(a, c);
                    invalidTriangle = true;
                }
                if ((cPos - bPos).LengthSquared() <= MyVoxelConnectionHelper.OUTER_EDGE_EPSILON_SQ)
                {
                    m_vertexMapping.Union(b, c);
                    invalidTriangle = true;
                }

                if (invalidTriangle)
                {
                    continue;
                }

                m_connectionHelper.PreprocessInnerEdge(a, b);
                m_connectionHelper.PreprocessInnerEdge(b, c);
                m_connectionHelper.PreprocessInnerEdge(c, a);
            }
            ProfilerShort.End();

            ProfilerShort.Begin("Free face sorting");
            // Ensure that the faces have increasing index numbers
            Mesh.SortFreeFaces();
            ProfilerShort.End();

            m_higherLevelHelper.OpenNewCell(coord);

            ProfilerShort.Begin("Adding triangles");
            for (int i = 0; i < data.VoxelTrianglesCount; i++)
            {
                short a    = data.VoxelTriangles[i].VertexIndex0;
                short b    = data.VoxelTriangles[i].VertexIndex1;
                short c    = data.VoxelTriangles[i].VertexIndex2;
                short setA = (short)m_vertexMapping.Find(a);
                short setB = (short)m_vertexMapping.Find(b);
                short setC = (short)m_vertexMapping.Find(c);

                if (setA == setB || setB == setC || setA == setC)
                {
                    continue;
                }

                Vector3 aPos, bPos, cPos;
                Vector3 vert;
                data.GetUnpackedPosition(setA, out vert);
                aPos = vert - centerDisplacement;
                data.GetUnpackedPosition(setB, out vert);
                bPos = vert - centerDisplacement;
                data.GetUnpackedPosition(setC, out vert);
                cPos = vert - centerDisplacement;

                if (MyFakes.NAVMESH_PRESUMES_DOWNWARD_GRAVITY)
                {
                    Vector3 normal = (cPos - aPos).Cross(bPos - aPos);
                    normal.Normalize();
                    if (normal.Dot(ref Vector3.Up) <= Math.Cos(MathHelper.ToRadians(54.0f)))
                    {
                        continue;
                    }
                }

                Vector3D aTformed = aPos + voxelMapCenter;
                Vector3D bTformed = bPos + voxelMapCenter;
                Vector3D cTformed = cPos + voxelMapCenter;

                bool intersecting = false;
                m_tmpLinkCandidates.Clear();
                m_navmeshCoordinator.TestVoxelNavmeshTriangle(ref aTformed, ref bTformed, ref cTformed, m_tmpGridList, m_tmpLinkCandidates, out intersecting);
                if (intersecting)
                {
                    m_tmpLinkCandidates.Clear();
                    continue;
                }

                if (!m_connectionHelper.IsInnerEdge(a, b))
                {
                    debugEdgesList.Add(new DebugDrawEdge(aTformed, bTformed));
                }
                if (!m_connectionHelper.IsInnerEdge(b, c))
                {
                    debugEdgesList.Add(new DebugDrawEdge(bTformed, cTformed));
                }
                if (!m_connectionHelper.IsInnerEdge(c, a))
                {
                    debugEdgesList.Add(new DebugDrawEdge(cTformed, aTformed));
                }

                int edgeAB   = m_connectionHelper.TryGetAndRemoveEdgeIndex(b, a, ref bPos, ref aPos);
                int edgeBC   = m_connectionHelper.TryGetAndRemoveEdgeIndex(c, b, ref cPos, ref bPos);
                int edgeCA   = m_connectionHelper.TryGetAndRemoveEdgeIndex(a, c, ref aPos, ref cPos);
                int formerAB = edgeAB;
                int formerBC = edgeBC;
                int formerCA = edgeCA;

                ProfilerShort.Begin("AddTriangle");
                var tri = AddTriangle(ref aPos, ref bPos, ref cPos, ref edgeAB, ref edgeBC, ref edgeCA);
                ProfilerShort.End();

                CheckMeshConsistency();

                m_higherLevelHelper.AddTriangle(tri.Index);

                if (formerAB == -1)
                {
                    m_connectionHelper.AddEdgeIndex(a, b, ref aPos, ref bPos, edgeAB);
                }
                if (formerBC == -1)
                {
                    m_connectionHelper.AddEdgeIndex(b, c, ref bPos, ref cPos, edgeBC);
                }
                if (formerCA == -1)
                {
                    m_connectionHelper.AddEdgeIndex(c, a, ref cPos, ref aPos, edgeCA);
                }

                // TODO: Instead of this, just add the tri into a list of tris that want to connect with the link candidates
                //m_navmeshCoordinator.TryAddVoxelNavmeshLinks(tri, cellId, m_tmpLinkCandidates);
                foreach (var candidate in m_tmpLinkCandidates)
                {
                    List <MyNavigationPrimitive> primitives = null;
                    if (!m_tmpCubeLinkCandidates.TryGetValue(candidate, out primitives))
                    {
                        primitives = m_primitiveListPool.Allocate();
                        m_tmpCubeLinkCandidates.Add(candidate, primitives);
                    }

                    primitives.Add(tri);
                }
                m_tmpLinkCandidates.Clear();
            }
            ProfilerShort.End();

            m_tmpGridList.Clear();
            m_connectionHelper.ClearCell();
            m_vertexMapping.Clear();

            Debug.Assert(!m_processedCells.Contains(ref cellPos));
            m_processedCells.Add(ref cellPos);
            m_higherLevelHelper.AddExplored(ref cellPos);

            // Find connected components in the current cell's subgraph of the navigation mesh
            m_higherLevelHelper.ProcessCellComponents();
            m_higherLevelHelper.CloseCell();

            // Create navmesh links using the navmesh coordinator, taking into consideration the high level components
            m_navmeshCoordinator.TryAddVoxelNavmeshLinks2(cellId, m_tmpCubeLinkCandidates);
            m_navmeshCoordinator.UpdateVoxelNavmeshCellHighLevelLinks(cellId);

            foreach (var candidate in m_tmpCubeLinkCandidates)
            {
                candidate.Value.Clear();
                m_primitiveListPool.Deallocate(candidate.Value);
            }
            m_tmpCubeLinkCandidates.Clear();

            return(true);
        }
示例#26
0
 internal unsafe void ReadRange <TOperator>(ref TOperator target, MyStorageDataTypeEnum type, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod) where TOperator : struct, IVoxelOperator
 {
     try
     {
         MyCellCoord *coordPtr = (MyCellCoord *)stackalloc byte[(((IntPtr)EstimateStackSize(this.m_treeHeight)) * sizeof(MyCellCoord))];
         MyCellCoord  coord    = new MyCellCoord(this.m_treeHeight - 1, ref Vector3I.Zero);
         int          index    = 0 + 1;
         coordPtr[index] = coord;
         while (index > 0)
         {
             coord = coordPtr[--index];
             MyOctreeNode node     = this.m_nodes[coord.PackId32()];
             int          num3     = coord.Lod - lodIndex;
             Vector3I     vectori4 = coord.CoordInLod << 1;
             Vector3I     min      = (minInLod >> num3) - vectori4;
             Vector3I     max      = (maxInLod >> num3) - vectori4;
             for (int i = 0; i < 8; i++)
             {
                 Vector3I vectori;
                 this.ComputeChildCoord(i, out vectori);
                 if (vectori.IsInsideInclusiveEnd(ref min, ref max))
                 {
                     if ((lodIndex < coord.Lod) && node.HasChild(i))
                     {
                         index++;
                         coordPtr[index] = new MyCellCoord(coord.Lod - 1, (Vector3I)(vectori4 + vectori));
                     }
                     else
                     {
                         byte     inOutContent = &node.Data.FixedElementField[i];
                         Vector3I result       = (Vector3I)(vectori4 + vectori);
                         if (num3 == 0)
                         {
                             Vector3I position = (Vector3I)((writeOffset + result) - minInLod);
                             target.Op(ref position, type, ref inOutContent);
                         }
                         else
                         {
                             result = result << num3;
                             Vector3I  vectori7    = (Vector3I)((result + (1 << (num3 & 0x1f))) - 1);
                             Vector3I *vectoriPtr1 = (Vector3I *)ref result;
                             Vector3I.Max(ref (Vector3I) ref vectoriPtr1, ref minInLod, out result);
                             Vector3I *vectoriPtr2 = (Vector3I *)ref vectori7;
                             Vector3I.Min(ref (Vector3I) ref vectoriPtr2, ref maxInLod, out vectori7);
                             int z = result.Z;
                             while (z <= vectori7.Z)
                             {
                                 int y = result.Y;
                                 while (true)
                                 {
                                     if (y > vectori7.Y)
                                     {
                                         z++;
                                         break;
                                     }
                                     int x = result.X;
                                     while (true)
                                     {
                                         if (x > vectori7.X)
                                         {
                                             y++;
                                             break;
                                         }
                                         Vector3I position = writeOffset;
                                         int *    numPtr1  = (int *)ref position.X;
                                         numPtr1[0] += x - minInLod.X;
                                         int *numPtr2 = (int *)ref position.Y;
                                         numPtr2[0] += y - minInLod.Y;
                                         int *numPtr3 = (int *)ref position.Z;
                                         numPtr3[0] += z - minInLod.Z;
                                         target.Op(ref position, type, ref inOutContent);
                                         x++;
                                     }
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     finally
     {
     }
 }
示例#27
0
        internal void OnCellRequestCancelled(MyCellCoord cell)
        {
            var workId = cell.PackId64();

            m_renderWorkTracker.Cancel(workId);
        }
示例#28
0
        internal unsafe void ReadRange(MyStorageData target, MyStorageDataTypeEnum type, ref Vector3I writeOffset, int lodIndex, ref Vector3I minInLod, ref Vector3I maxInLod)
        {
            ProfilerShort.Begin("MySparseOctree2.ReadRangeToContent"); try
            {
                int          stackIdx  = 0;
                int          stackSize = MySparseOctree.EstimateStackSize(m_treeHeight);
                MyCellCoord *stack     = stackalloc MyCellCoord[stackSize];
                MyCellCoord  data      = new MyCellCoord(m_treeHeight - 1, ref Vector3I.Zero);
                stack[stackIdx++] = data;

                MyOctreeNode node;
                Vector3I     childPosRelative, min, max, nodePositionInChild;
                int          lodDiff;
                while (stackIdx > 0)
                {
                    Debug.Assert(stackIdx <= stackSize);
                    data = stack[--stackIdx];
                    node = m_nodes[data.PackId32()];

                    lodDiff             = data.Lod - lodIndex;
                    min                 = minInLod >> lodDiff;
                    max                 = maxInLod >> lodDiff;
                    nodePositionInChild = data.CoordInLod << 1;
                    min                -= nodePositionInChild;
                    max                -= nodePositionInChild;
                    for (int i = 0; i < MyOctreeNode.CHILD_COUNT; ++i)
                    {
                        ComputeChildCoord(i, out childPosRelative);
                        if (!childPosRelative.IsInsideInclusive(ref min, ref max))
                        {
                            continue;
                        }
                        if (lodIndex < data.Lod && node.HasChild(i))
                        {
                            Debug.Assert(stackIdx < stackSize);
                            stack[stackIdx++] = new MyCellCoord(data.Lod - 1, nodePositionInChild + childPosRelative);
                        }
                        else
                        {
                            var nodeData = node.Data[i];
                            var childMin = nodePositionInChild + childPosRelative;
                            if (lodDiff == 0)
                            {
                                var write = writeOffset + childMin - minInLod;
                                target.Set(type, ref write, nodeData);
                            }
                            else
                            {
                                childMin <<= lodDiff;
                                var childMax = childMin + (1 << lodDiff) - 1;
                                Vector3I.Max(ref childMin, ref minInLod, out childMin);
                                Vector3I.Min(ref childMax, ref maxInLod, out childMax);
                                for (int z = childMin.Z; z <= childMax.Z; ++z)
                                {
                                    for (int y = childMin.Y; y <= childMax.Y; ++y)
                                    {
                                        for (int x = childMin.X; x <= childMax.X; ++x)
                                        {
                                            var write = writeOffset;
                                            write.X += x - minInLod.X;
                                            write.Y += y - minInLod.Y;
                                            write.Z += z - minInLod.Z;
                                            target.Set(type, ref write, nodeData);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            finally { ProfilerShort.End(); }
        }
示例#29
0
        public bool Intersects(ref BoundingSphereD localSphere)
        {
            MyPrecalcComponent.AssertUpdateThread();

            //  Get min and max cell coordinate where boundingBox can fit
            BoundingBoxD sphereBoundingBox = BoundingBoxD.CreateInvalid();

            sphereBoundingBox.Include(ref localSphere);
            Vector3I cellCoordMin, cellCoordMax;

            {
                Vector3D minD = sphereBoundingBox.Min;
                Vector3D maxD = sphereBoundingBox.Max;
                MyVoxelCoordSystems.LocalPositionToGeometryCellCoord(ref minD, out cellCoordMin);
                MyVoxelCoordSystems.LocalPositionToGeometryCellCoord(ref maxD, out cellCoordMax);
            }

            //  Fix min and max cell coordinates so they don't overlap the voxelmap
            ClampCellCoord(ref cellCoordMin);
            ClampCellCoord(ref cellCoordMax);

            MyCellCoord cell = new MyCellCoord();

            for (cell.CoordInLod.X = cellCoordMin.X; cell.CoordInLod.X <= cellCoordMax.X; cell.CoordInLod.X++)
            {
                for (cell.CoordInLod.Y = cellCoordMin.Y; cell.CoordInLod.Y <= cellCoordMax.Y; cell.CoordInLod.Y++)
                {
                    for (cell.CoordInLod.Z = cellCoordMin.Z; cell.CoordInLod.Z <= cellCoordMax.Z; cell.CoordInLod.Z++)
                    {
                        //  If no overlap between bounding box of data cell and the sphere
                        BoundingBox cellBoundingBox;
                        MyVoxelCoordSystems.GeometryCellCoordToLocalAABB(ref cell.CoordInLod, out cellBoundingBox);
                        if (cellBoundingBox.Intersects(ref localSphere) == false)
                        {
                            continue;
                        }

                        //  Get cell from cache. If not there, precalc it and store in the cache.
                        //  If null is returned, we know that cell doesn't contain any triangleVertexes so we don't need to do intersections.
                        CellData cachedData = GetCell(ref cell);

                        if (cachedData == null)
                        {
                            continue;
                        }

                        for (int i = 0; i < cachedData.VoxelTrianglesCount; i++)
                        {
                            MyVoxelTriangle voxelTriangle = cachedData.VoxelTriangles[i];

                            MyTriangle_Vertexes triangle;
                            cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex0, out triangle.Vertex0);
                            cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex1, out triangle.Vertex1);
                            cachedData.GetUnpackedPosition(voxelTriangle.VertexIndex2, out triangle.Vertex2);

                            BoundingBox localTriangleAABB = BoundingBox.CreateInvalid();
                            localTriangleAABB.Include(ref triangle.Vertex0);
                            localTriangleAABB.Include(ref triangle.Vertex1);
                            localTriangleAABB.Include(ref triangle.Vertex2);

                            //  First test intersection of triangle's bounding box with line's bounding box. And only if they overlap or intersect, do further intersection tests.
                            if (localTriangleAABB.Intersects(ref localSphere))
                            {
                                PlaneD trianglePlane = new PlaneD(triangle.Vertex0, triangle.Vertex1, triangle.Vertex2);

                                if (MyUtils.GetSphereTriangleIntersection(ref localSphere, ref trianglePlane, ref triangle) != null)
                                {
                                    //  If intersection found - we are finished. We don't need to look for more.
                                    return(true);
                                }
                            }
                        }
                    }
                }
            }

            return(false);
        }
示例#30
0
        IMyClipmapCell IMyClipmapCellHandler.CreateCell(MyClipmapScaleEnum scaleGroup, MyCellCoord cellCoord, ref MatrixD worldMatrix)
        {
            switch (scaleGroup)
            {
            case MyClipmapScaleEnum.Normal:
                return(new MyRenderVoxelCell(scaleGroup, cellCoord, ref worldMatrix));

            default:
                throw new InvalidBranchException();
            }
        }