Esempio n. 1
0
        private void LateUpdate()
        {
            if (!m_isRunning)
            {
                return;
            }

            if (!IsReady)
            {
                RequestUpdate();
            }

            bool nullHit = false;

            for (int i = 0; i < m_sdfObjects.Count; i++)
            {
                SDFObject sdfObject = m_sdfObjects[i];
                bool      isNull    = !sdfObject;

                nullHit |= isNull;

                if (!isNull)
                {
                    m_isLocalDataDirty      |= sdfObject.IsDirty;
                    m_isLocalDataOrderDirty |= sdfObject.IsOrderDirty;
                }
            }

            if (nullHit)
            {
                ClearNulls(m_sdfObjects);
            }

            bool changed = false;

            if (m_isLocalDataOrderDirty)
            {
                ReorderObjects();
                changed = true;
            }

            if (changed || m_forceUpdateNextFrame || m_isGlobalMeshDataDirty || m_isLocalDataDirty || transform.hasChanged)
            {
                changed = true;
                RebuildData();
            }

            m_forceUpdateNextFrame = false;
            transform.hasChanged   = false;

            if (changed && !IsEmpty)
            {
                for (int i = 0; i < m_sdfComponents.Count; i++)
                {
                    m_sdfComponents[i].Run();
                }
            }
        }
Esempio n. 2
0
        public void Register(SDFObject sdfObject)
        {
            if (m_sdfObjects.Contains(sdfObject))
            {
                return;
            }

            if (sdfObject is SDFMesh sdfMesh)
            {
                // check if this is a totally new mesh that no group has seen
                if (!m_globalSDFMeshes.Contains(sdfMesh))
                {
                    m_globalSDFMeshes.Add(sdfMesh);
                    m_isGlobalMeshDataDirty = true;
                }

                // keep track of how many groups contain a local reference to this sdfmesh
                if (!m_meshCounts.ContainsKey(sdfMesh.ID))
                {
                    m_meshCounts.Add(sdfMesh.ID, 0);
                }

                m_meshCounts[sdfMesh.ID]++;
            }

            bool wasEmpty = IsEmpty;

            m_sdfObjects.Add(sdfObject);
            m_isLocalDataDirty      = true;
            m_isLocalDataOrderDirty = true;

            // this is almost certainly overkill, but i like the kind of guaranteed stability
            ClearNulls(m_sdfObjects);

            if (wasEmpty && !IsEmpty)
            {
                for (int i = 0; i < m_sdfComponents.Count; i++)
                {
                    m_sdfComponents[i].OnNotEmpty();
                }
            }

            RequestUpdate();
        }
Esempio n. 3
0
        public void Deregister(SDFObject sdfObject)
        {
            bool wasEmpty = IsEmpty;

            if (!m_sdfObjects.Remove(sdfObject))
            {
                return;
            }

            if (sdfObject is SDFMesh sdfMesh)
            {
                // if this was the only group referencing this sdfmesh, we can remove it from the global buffer too
                if (m_meshCounts.ContainsKey(sdfMesh.ID))
                {
                    m_meshCounts[sdfMesh.ID]--;

                    if (m_meshCounts[sdfMesh.ID] <= 0 && m_globalSDFMeshes.Remove(sdfMesh))
                    {
                        m_isGlobalMeshDataDirty = true;
                    }
                }
            }

            m_isLocalDataDirty      = true;
            m_isLocalDataOrderDirty = true;

            // this is almost certainly overkill
            ClearNulls(m_sdfObjects);

            if (!wasEmpty && IsEmpty)
            {
                for (int i = 0; i < m_sdfComponents.Count; i++)
                {
                    m_sdfComponents[i].OnEmpty();
                }
            }

            RequestUpdate();
        }
Esempio n. 4
0
        /// <summary>
        /// Repopulate the data relating to SDF primitives (spheres, toruses, cuboids etc) and SDF meshes (which point to where in the list of sample and uv data they begin, and how large they are)
        /// </summary>
        /// <param name="onlySendBufferOnChange">Whether to invoke the components and inform them the buffer has changed. This is only really necessary when the size changes.</param>
        private void RebuildData(bool onlySendBufferOnChange = true)
        {
            m_isLocalDataDirty = false;

            // should we rebuild the buffers which contain mesh sample + uv data?
            bool globalBuffersChanged = false;

            if (m_meshSamplesBuffer == null || !m_meshSamplesBuffer.IsValid() || m_meshPackedUVsBuffer == null || !m_meshPackedUVsBuffer.IsValid() || m_isGlobalMeshDataDirty)
            {
                globalBuffersChanged = RebuildGlobalMeshData(m_sdfObjects, onlySendBufferOnChange);
            }

            // memorize the size of the array before clearing it, for later comparison
            int previousCount = m_data.Count;

            m_data.Clear();

            // add all the sdf objects
            for (int i = 0; i < m_sdfObjects.Count; i++)
            {
                SDFObject sdfObject = m_sdfObjects[i];

                if (!sdfObject)
                {
                    continue;
                }

                sdfObject.SetClean();

                int meshStartIndex = -1;
                int uvStartIndex   = -1;

                if (sdfObject is SDFMesh mesh)
                {
                    // get the index in the global samples buffer where this particular mesh's samples begin
                    if (!m_meshSdfSampleStartIndices.TryGetValue(mesh.ID, out meshStartIndex))
                    {
                        globalBuffersChanged = RebuildGlobalMeshData(m_sdfObjects, onlySendBufferOnChange); // we don't recognize this mesh so we may need to rebuild the entire global list of mesh samples and UVs
                    }
                    // likewise, if this mesh has UVs, get the index where they begin too
                    if (mesh.Asset.HasUVs)
                    {
                        m_meshSdfUVStartIndices.TryGetValue(mesh.ID, out uvStartIndex);
                    }
                }

                m_data.Add(sdfObject.GetSDFGPUData(meshStartIndex, uvStartIndex));
            }

            bool sendBuffer = !onlySendBufferOnChange;

            // check whether we need to create a new buffer. buffers are fixed sizes so the most common occasion for this is simply a change of size
            if (m_dataBuffer == null || !m_dataBuffer.IsValid() || previousCount != m_data.Count)
            {
                sendBuffer = true;

                m_dataBuffer?.Dispose();
                m_dataBuffer = new ComputeBuffer(Mathf.Max(1, m_data.Count), SDFGPUData.Stride, ComputeBufferType.Structured);
            }

            // if the buffer is new, the size has changed, or if it's forced, we resend the buffer to the sdf group component classes
            if (sendBuffer)
            {
                for (int i = 0; i < m_sdfComponents.Count; i++)
                {
                    m_sdfComponents[i].UpdateDataBuffer(m_dataBuffer, m_data.Count);
                }
            }

            if (m_data.Count > 0)
            {
                m_dataBuffer.SetData(m_data);
            }

            // if we also changed the global mesh data buffer in this method, we need to send that as well
            if (!onlySendBufferOnChange || globalBuffersChanged)
            {
                Shader.SetGlobalBuffer(GlobalProperties.MeshSamples_StructuredBuffer, m_meshSamplesBuffer);
                Shader.SetGlobalBuffer(GlobalProperties.MeshPackedUVs_StructuredBuffer, m_meshPackedUVsBuffer);
            }
        }
Esempio n. 5
0
 public bool IsRegistered(SDFObject sdfObject) => !m_sdfObjects.IsNullOrEmpty() && m_sdfObjects.Contains(sdfObject);