public override void Draw()
            {
                base.Draw();

                if (MySession.Static == null)
                {
                    return;
                }

                if (m_showVoxelProbe)
                {
                    float halfSize = m_probeSize * .5f;
                    float lodSize  = 1 << m_probeLod;

                    if (m_moveProbe)
                    {
                        m_probePosition = MySector.MainCamera.Position + MySector.MainCamera.ForwardVector * m_probeSize * 3;
                    }

                    BoundingBox  bb;
                    BoundingBoxD bbp; // Box used for drawing and finding the probe and drawing

                    bb  = new BoundingBox(m_probePosition - halfSize, m_probePosition + halfSize);
                    bbp = (BoundingBoxD)bb;

                    m_voxels.Clear();
                    MyGamePruningStructure.GetAllVoxelMapsInBox(ref bbp, m_voxels);

                    MyVoxelBase map      = null;
                    double      distance = double.PositiveInfinity;

                    foreach (var vox in m_voxels)
                    {
                        var d = Vector3D.Distance(vox.WorldMatrix.Translation, m_probePosition);
                        if (d < distance)
                        {
                            distance = d;
                            map      = vox;
                        }
                    }

                    ContainmentType cont = ContainmentType.Disjoint;

                    if (map != null)
                    {
                        map = map.RootVoxel;

                        Vector3 localPos = Vector3.Transform(m_probePosition, map.PositionComp.WorldMatrixInvScaled);
                        localPos += map.SizeInMetresHalf;

                        // Create similar bounding box in storage space
                        bb = new BoundingBox(localPos - halfSize, localPos + halfSize);

                        m_probedVoxel = map;

                        Section("Probing {1}: {0}", map.StorageName, map.GetType().Name);
                        Text("Probe mode: {0}", m_mode);

                        if (m_mode == ProbeMode.Intersect)
                        {
                            Text("Local Pos: {0}", localPos);
                            Text("Probe Size: {0}", m_probeSize);
                            cont = map.Storage.Intersect(ref bb, false);
                            Text("Result: {0}", cont.ToString());
                            bbp = (BoundingBoxD)bb;
                        }
                        else
                        {
                            Vector3I min = Vector3I.Floor(bb.Min / lodSize + .5f);
                            Vector3I max = min + ((int)m_probeSize >> m_probeLod) - 1;

                            bbp = new BoundingBoxD(min << m_probeLod, (max + 1) << m_probeLod);
                            bbp.Translate(new Vector3D(-.5));

                            Text("Probe Size: {0}({1})", (max - min).X + 1, m_probeSize);
                            Text("Probe LOD: {0}", m_probeLod);

                            var requestData           = (MyStorageDataTypeEnum)(int)m_mode;
                            MyVoxelRequestFlags flags = MyVoxelRequestFlags.ContentChecked;

                            m_target.Resize(max - min + 1);
                            m_target.Clear(MyStorageDataTypeEnum.Content, 0);
                            m_target.Clear(MyStorageDataTypeEnum.Material, 0);
                            map.Storage.ReadRange(m_target, (MyStorageDataTypeFlags)(1 << (int)requestData), m_probeLod, ref min, ref max, ref flags);

                            if (requestData == MyStorageDataTypeEnum.Content)
                            {
                                if (flags.HasFlag(MyVoxelRequestFlags.EmptyContent))
                                {
                                    cont = ContainmentType.Disjoint;
                                }
                                else if (flags.HasFlag(MyVoxelRequestFlags.FullContent))
                                {
                                    cont = ContainmentType.Contains;
                                }
                                else
                                {
                                    int val = m_target.ValueWhenAllEqual(requestData);
                                    if (val == -1)
                                    {
                                        cont = ContainmentType.Intersects;
                                    }
                                    else if (val >= MyVoxelConstants.VOXEL_ISO_LEVEL)
                                    {
                                        cont = ContainmentType.Contains;
                                    }
                                    else
                                    {
                                        cont = ContainmentType.Disjoint;
                                    }
                                }

                                DrawContentsInfo(m_target);
                            }
                            else
                            {
                                cont = ContainmentType.Disjoint;
                                DrawMaterialsInfo(m_target);
                            }

                            Text(Color.Yellow, 1.5f, "Voxel Editing:");
                            Text("Value to set (Ctrl+Mousewheel): {0}", m_valueToSet);
                            if (m_probeLod != 0)
                            {
                                Text(Color.Red, "Writing to storage is only possible when probe is set to LOD 0");
                            }
                            else
                            {
                                Text("Use primary mouse button to set.");
                                Text("Position/Extents: {0}/{1}", bbp.Min, bbp.Extents);

                                if (MyInput.Static.IsLeftMousePressed())
                                {
                                    if (requestData == MyStorageDataTypeEnum.Content)
                                    {
                                        m_target.BlockFillContent(Vector3I.Zero, m_target.Size3D - Vector3I.One, m_valueToSet);
                                    }
                                    else
                                    {
                                        m_target.BlockFillMaterial(Vector3I.Zero, m_target.Size3D - Vector3I.One, m_valueToSet);
                                    }

                                    map.Storage.WriteRange(m_target, (MyStorageDataTypeFlags)(1 << (int)requestData), ref min, ref max);
                                }
                            }
                        }
                    }
                    else
                    {
                        Section("No Voxel Found");
                        Text("Probe mode: {0}", m_mode);
                        Text("Probe Size: {0}", m_probeSize);
                    }

                    Color c = ColorForContainment(cont);
                    if (map != null)
                    {
                        bbp = bbp.Translate(-map.SizeInMetresHalf);
                        MyOrientedBoundingBoxD oobb = new MyOrientedBoundingBoxD(bbp, map.WorldMatrix);
                        MyRenderProxy.DebugDrawOBB(oobb, c, 0.5f, true, false);
                    }
                    else
                    {
                        MyRenderProxy.DebugDrawAABB(bbp, c, 0.5f, 1.0f, true);
                    }
                }
            }
Example #2
0
        public MyIsoMesh Precalc(IMyStorage storage, int lod, Vector3I voxelStart, Vector3I voxelEnd, bool generateMaterials, bool useAmbient, bool doNotCheck = false)
        {
            // change range so normal can be computed at edges (expand by 1 in all directions)
            voxelStart -= 1;
            voxelEnd   += 1;

            if (storage == null)
            {
                return(null);
            }

            using (storage.Pin())
            {
                if (storage.Closed)
                {
                    return(null);
                }

                MyVoxelRequestFlags request = MyVoxelRequestFlags.ContentChecked; // | (doNotCheck ? MyVoxelRequestFlags.DoNotCheck : 0);
                //if (lod == 0 && generateMaterials) request |= MyVoxelRequestFlags.AdviseCache;

                bool readAmbient = false;

                if (generateMaterials && storage.DataProvider != null && storage.DataProvider.ProvidesAmbient)
                {
                    readAmbient = true;
                }

                m_cache.Resize(voxelStart, voxelEnd);
                if (readAmbient)
                {
                    m_cache.StoreOcclusion = true;
                }

                storage.ReadRange(m_cache, MyStorageDataTypeFlags.Content, lod, ref voxelStart, ref voxelEnd, ref request);

                if (request.HasFlag(MyVoxelRequestFlags.EmptyContent) || request.HasFlag(MyVoxelRequestFlags.FullContent) ||
                    (!request.HasFlag(MyVoxelRequestFlags.ContentChecked) && !m_cache.ContainsIsoSurface()))
                {
                    //if(generateMaterials && lod == 0) Debugger.Break();
                    //storage.DebugDrawChunk(voxelStart, voxelEnd);
                    return(null);
                }

                var    center           = (storage.Size / 2) * MyVoxelConstants.VOXEL_SIZE_IN_METRES;
                var    voxelSize        = MyVoxelConstants.VOXEL_SIZE_IN_METRES * (1 << lod);
                var    vertexCellOffset = voxelStart - AffectedRangeOffset;
                double numCellsHalf     = 0.5 * (m_cache.Size3D.X - 3);
                var    posOffset        = ((Vector3D)vertexCellOffset + numCellsHalf) * (double)voxelSize;

                if (generateMaterials)
                {
                    // 255 is the new black
                    m_cache.ClearMaterials(255);
                }

                if (readAmbient)
                {
                    m_cache.Clear(MyStorageDataTypeEnum.Occlusion, 0);
                }

                IsoMesher mesher = new IsoMesher();
                ProfilerShort.Begin("Dual Contouring");
                unsafe
                {
                    fixed(byte *content = m_cache[MyStorageDataTypeEnum.Content])
                    fixed(byte *material = m_cache[MyStorageDataTypeEnum.Material])
                    {
                        var size3d = m_cache.Size3D;

                        Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z);
                        mesher.Calculate(size3d.X, content, material, m_buffer, useAmbient, posOffset - center);
                    }
                }
                ProfilerShort.End();

                if (generateMaterials)
                {
                    request = 0;

                    request |= MyVoxelRequestFlags.SurfaceMaterial;
                    request |= MyVoxelRequestFlags.ConsiderContent;

                    var req = readAmbient ? MyStorageDataTypeFlags.Material | MyStorageDataTypeFlags.Occlusion : MyStorageDataTypeFlags.Material;

                    storage.ReadRange(m_cache, req, lod, ref voxelStart, ref voxelEnd, ref request);

                    FixCacheMaterial(voxelStart, voxelEnd);
                    unsafe
                    {
                        fixed(byte *content = m_cache[MyStorageDataTypeEnum.Content])
                        fixed(byte *material = m_cache[MyStorageDataTypeEnum.Material])
                        {
                            int materialOverride = request.HasFlag(MyVoxelRequestFlags.OneMaterial) ? m_cache.Material(0) : -1;
                            var size3d           = m_cache.Size3D;

                            Debug.Assert(size3d.X == size3d.Y && size3d.Y == size3d.Z);

                            if (readAmbient)
                                fixed(byte *ambient = m_cache[MyStorageDataTypeEnum.Occlusion])
                                mesher.CalculateMaterials(size3d.X, content, material, ambient, materialOverride);
                            else
                            {
                                mesher.CalculateMaterials(size3d.X, content, material, null, materialOverride);
                            }
                        }
                    }
                }
                else
                {
                    m_cache.ClearMaterials(0);
                }

                mesher.Finish(m_buffer);

                if (m_buffer.VerticesCount == 0 || m_buffer.Triangles.Count == 0)
                {
                    return(null);
                }

                ProfilerShort.Begin("Geometry post-processing");
                {
                    var positions   = m_buffer.Positions.GetInternalArray();
                    var vertexCells = m_buffer.Cells.GetInternalArray();
                    var materials   = m_buffer.Materials.GetInternalArray();
                    for (int i = 0; i < m_buffer.VerticesCount; i++)
                    {
                        Debug.Assert(positions[i].IsInsideInclusive(ref Vector3.MinusOne, ref Vector3.One));
                        vertexCells[i] += vertexCellOffset;
                        Debug.Assert(vertexCells[i].IsInsideInclusive(voxelStart + 1, voxelEnd - 1));
                        Debug.Assert(materials[i] != MyVoxelConstants.NULL_MATERIAL);
                    }

                    m_buffer.PositionOffset = posOffset;
                    m_buffer.PositionScale  = new Vector3((float)(numCellsHalf * voxelSize));
                    m_buffer.CellStart      = voxelStart + 1;
                    m_buffer.CellEnd        = voxelEnd - 1;
                }
                ProfilerShort.End();

                // Replace filled mesh with new one.
                // This way prevents allocation of meshes which then end up empty.
                var buffer = m_buffer;
                m_buffer = new MyIsoMesh();
                return(buffer);
            }
        }