private static void ReadFoliageCellDataSubdivided(BinaryReader a, out int key, out FoliageCellSubdividedData data)
        {
            // Read the key
            key = a.ReadInt32();

            // Create new data
            data = new FoliageCellSubdividedData();

            data.m_Bounds   = ReadBounds(a);
            data.m_Position = ReadFoliageCell(a);

            int entries = a.ReadInt32();

            for (int i = 0; i < entries; i++)
            {
                int dataKey = a.ReadInt32();

                // Add the data with the key
                data.m_TypeHashLocationsEditor.Add(dataKey, new Dictionary <string, List <FoliageInstance> >());

                // Read the content
                int entriesLabeled = a.ReadInt32();
                for (int j = 0; j < entriesLabeled; j++)
                {
                    string dataKeyLabel = a.ReadString();
                    List <FoliageInstance> instances = ReadListFoliageInstance(a, false);

                    data.m_TypeHashLocationsEditor[dataKey].Add(dataKeyLabel, instances);
                }
            }
        }
Пример #2
0
        private void RemoveEmptyTypeDataCellSubdivided(FoliageCellSubdividedData data)
        {
            if (data.m_TypeHashLocationsEditor.Count > 0)
            {
                HashSet <int> removeTypes = null;

                // Remove labeled data
                foreach (var pair in data.m_TypeHashLocationsEditor)
                {
                    Dictionary <string, List <FoliageInstance> > labeled = pair.Value;
                    HashSet <string> removeLabels = null;

                    // Iterate through the label data
                    foreach (var pairLabeled in labeled)
                    {
                        if (pairLabeled.Value.Count <= 0)
                        {
                            if (removeLabels == null)
                            {
                                removeLabels = new HashSet <string>();
                            }

                            removeLabels.Add(pairLabeled.Key);
                        }
                    }

                    // Labels to remove
                    if (removeLabels != null)
                    {
                        foreach (string label in removeLabels)
                        {
                            labeled.Remove(label);
                        }
                    }

                    // If we ended up with an empty list of data
                    if (labeled.Count <= 0)
                    {
                        if (removeTypes == null)
                        {
                            removeTypes = new HashSet <int>();
                        }

                        removeTypes.Add(pair.Key);
                    }
                }

                if (removeTypes != null)
                {
                    foreach (int type in removeTypes)
                    {
                        data.m_TypeHashLocationsEditor.Remove(type);
                    }
                }
            }
        }
Пример #3
0
        private bool IsSubCellEmpty(FoliageCellSubdividedData cell)
        {
            foreach (var data in cell.m_TypeHashLocationsEditor.Values)
            {
                foreach (var instances in data.Values)
                {
                    // If we have a count return that we are not empty
                    if (instances.Count > 0)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
        private static void WriteFoliageCellDataSubdivided(BinaryWriter a, int key, FoliageCellSubdividedData data)
        {
            // Write key
            a.Write(key);

            WriteBounds(a, data.m_Bounds);
            WriteFoliageCell(a, data.m_Position);

            // Write inner cell data
            a.Write(data.m_TypeHashLocationsEditor.Count);

            foreach (int dataKey in data.m_TypeHashLocationsEditor.Keys)
            {
                a.Write(dataKey);
                var labeled = data.m_TypeHashLocationsEditor[dataKey];

                a.Write(labeled.Count);
                foreach (string dataKeyLabel in labeled.Keys)
                {
                    a.Write(dataKeyLabel);
                    WriteListFoliageInstance(a, labeled[dataKeyLabel], false, true);
                }
            }
        }
Пример #5
0
        /**
         * Add a new foliage instance to the underlaying data.
         *
         * The painter should decide if our data is added to the subdivisions or if it is a tree type and must not be added to the subdivision.
         */
        public void AddInstance(int typeHash, FoliageInstance instance, bool subdivision, string label = FoliageGlobals.LABEL_PAINTED)
        {
            int hash = FoliageCell.MakeHash(instance.m_Position);

            if (m_FoliageData.ContainsKey(hash) == false)
            {
                FoliageCellData data = new FoliageCellData();
                data.m_Position = new FoliageCell();
                data.m_Position.Set(instance.m_Position);

                data.m_Bounds         = data.m_Position.GetBounds();
                data.m_BoundsExtended = data.m_Bounds;

                // Add the foliage cell
                m_FoliageData.Add(hash, data);
            }

            FoliageCellData cellData = m_FoliageData[hash];

            if (subdivision == false)
            {
                if (cellData.m_TypeHashLocationsEditor.ContainsKey(typeHash) == false)
                {
                    cellData.m_TypeHashLocationsEditor.Add(typeHash, new Dictionary <string, List <FoliageInstance> >());
                }

                var labeled = cellData.m_TypeHashLocationsEditor[typeHash];

                if (labeled.ContainsKey(label) == false)
                {
                    labeled.Add(label, new List <FoliageInstance>());
                }

                // Add the foliage data
                labeled[label].Add(instance);

                // Make the extended bounds larger. Encapsulate anything that might make the bounds larger. Only applied to trees
                m_FoliageData[hash].m_BoundsExtended.Encapsulate(instance.m_Bounds);
            }
            else
            {
                var foliageSubdividedData = cellData.m_FoliageDataSubdivided;

                Vector3 localPosition = GetLocalInCell(instance.m_Position, cellData);

                int hashSubdivided = FoliageCell.MakeHashSubdivided(localPosition);

                if (foliageSubdividedData.ContainsKey(hashSubdivided) == false)
                {
                    FoliageCellSubdividedData data = new FoliageCellSubdividedData();
                    data.m_Position = new FoliageCell();
                    data.m_Position.SetSubdivided(localPosition);

                    // Get bounds in world space
                    data.m_Bounds        = data.m_Position.GetBoundsSubdivided();
                    data.m_Bounds.center = GetWorldInCell(data.m_Bounds.center, cellData);

                    foliageSubdividedData.Add(hashSubdivided, data);
                }

                FoliageCellSubdividedData cellDataSubdivided = foliageSubdividedData[hashSubdivided];

                if (cellDataSubdivided.m_TypeHashLocationsEditor.ContainsKey(typeHash) == false)
                {
                    cellDataSubdivided.m_TypeHashLocationsEditor.Add(typeHash, new Dictionary <string, List <FoliageInstance> >());
                }

                var labeled = cellDataSubdivided.m_TypeHashLocationsEditor[typeHash];

                if (labeled.ContainsKey(label) == false)
                {
                    labeled.Add(label, new List <FoliageInstance>());
                }

                labeled[label].Add(instance);
            }
        }
        /**
         * Load from file the runtime version of the data
         */
        public static FoliageDataRuntime LoadFromFileRuntime(string filename)
        {
            FoliageData data = LoadFromFileEditTime(filename);

            // Build the runtime data from the edit time data
            FoliageDataRuntime runtime = new FoliageDataRuntime();

            foreach (var hashedCell in data.m_FoliageData)
            {
                FoliageCellData        editCell    = hashedCell.Value;
                FoliageCellDataRuntime runtimeCell = new FoliageCellDataRuntime();

                // Set the data. Note that we only need the extended bounds
                runtimeCell.m_Bounds   = editCell.m_BoundsExtended;
                runtimeCell.m_Position = editCell.m_Position;

                // Build the tree instance data
                int idx = -1;
                runtimeCell.m_TypeHashLocationsRuntime = new FoliageKeyValuePair <int, FoliageTuple <FoliageInstance[]> > [editCell.m_TypeHashLocationsEditor.Count];
                foreach (var instances in editCell.m_TypeHashLocationsEditor)
                {
                    idx++;

                    List <FoliageInstance> allTreeInstances = new List <FoliageInstance>();
                    var labeledInstances = instances.Value;

                    // Build all the data from the labeled data
                    foreach (List <FoliageInstance> inst in labeledInstances.Values)
                    {
                        allTreeInstances.AddRange(inst);
                    }

                    // We will build the world matrix for trees
                    for (int i = 0; i < allTreeInstances.Count; i++)
                    {
                        FoliageInstance inst = allTreeInstances[i];
                        inst.BuildWorldMatrix();
                        allTreeInstances[i] = inst;
                    }

                    // Don't forget to trim all excess instances!
                    allTreeInstances.TrimExcess();

                    #if UNITY_EDITOR
                    if (allTreeInstances.Count == 0)
                    {
                        Debug.Assert(false, "Count 0!");
                    }
                    #endif

                    runtimeCell.m_TypeHashLocationsRuntime[idx] = new FoliageKeyValuePair <int, FoliageTuple <FoliageInstance[]> >(instances.Key, new FoliageTuple <FoliageInstance[]>(allTreeInstances.ToArray()));
                }

                // Build the grass instance data from the subdivided cells
                List <FoliageKeyValuePair <int, FoliageCellSubdividedDataRuntime> > foliageCellDataSubdivided = new List <FoliageKeyValuePair <int, FoliageCellSubdividedDataRuntime> >(editCell.m_FoliageDataSubdivided.Count);

                foreach (var hashedSubdividedCell in editCell.m_FoliageDataSubdivided)
                {
                    FoliageCellSubdividedData        editSubdividedCell    = hashedSubdividedCell.Value;
                    FoliageCellSubdividedDataRuntime runtimeSubdividedCell = new FoliageCellSubdividedDataRuntime();

                    // Set the data
                    runtimeSubdividedCell.m_Bounds   = editSubdividedCell.m_Bounds;
                    runtimeSubdividedCell.m_Position = editSubdividedCell.m_Position;

                    idx = -1;
                    runtimeSubdividedCell.m_TypeHashLocationsRuntime = new FoliageKeyValuePair <int, FoliageTuple <Matrix4x4[][]> > [editSubdividedCell.m_TypeHashLocationsEditor.Count];
                    foreach (var instances in editSubdividedCell.m_TypeHashLocationsEditor)
                    {
                        idx++;

                        List <FoliageInstance> allGrassInstances = new List <FoliageInstance>();
                        var labeledInstances = instances.Value;

                        foreach (List <FoliageInstance> inst in labeledInstances.Values)
                        {
                            allGrassInstances.AddRange(inst);
                        }

                        #if UNITY_EDITOR
                        if (allGrassInstances.Count == 0)
                        {
                            Debug.Assert(false, "Count 0!");
                        }
                        #endif

                        // Build the multi-array data
                        int           ranges  = Mathf.CeilToInt(allGrassInstances.Count / (float)FoliageGlobals.RENDER_BATCH_SIZE);
                        Matrix4x4[][] batches = new Matrix4x4[ranges][];

                        for (int i = 0; i < ranges; i++)
                        {
                            List <FoliageInstance> range = allGrassInstances.GetRange(i * FoliageGlobals.RENDER_BATCH_SIZE,
                                                                                      i * FoliageGlobals.RENDER_BATCH_SIZE + FoliageGlobals.RENDER_BATCH_SIZE > allGrassInstances.Count
                                    ? allGrassInstances.Count - i * FoliageGlobals.RENDER_BATCH_SIZE
                                    : FoliageGlobals.RENDER_BATCH_SIZE);

                            batches[i] = range.ConvertAll <Matrix4x4>((x) => x.GetWorldTransform()).ToArray();
                        }

                        // Set the data
                        runtimeSubdividedCell.m_TypeHashLocationsRuntime[idx] = new FoliageKeyValuePair <int, FoliageTuple <Matrix4x4[][]> >(instances.Key, new FoliageTuple <Matrix4x4[][]>(batches));
                    }

                    // Add the subdivided runtime cell
                    foliageCellDataSubdivided.Add(new FoliageKeyValuePair <int, FoliageCellSubdividedDataRuntime>(hashedSubdividedCell.Key, runtimeSubdividedCell));
                }

                // Build the subdivided data
                runtimeCell.m_FoliageDataSubdivided = foliageCellDataSubdivided.ToArray();


                // Add the runtime cell
                runtime.m_FoliageData.Add(hashedCell.Key, runtimeCell);
            }

            // Good for GC
            data = null;

            return(runtime);
        }