Exemple #1
0
        public bool Write(RedGrassInstance rgi)
        {
            Vector3 pos = rgi.Position;

            int cx = (int)pos.x >> SHIFT;
            int cz = (int)pos.z >> SHIFT;

            RGChunk chunk = mChunks [cx, cz];

            if (chunk != null)
            {
                if (rgi.Density < 0.001f)
                {
                    chunk.Remove((int)pos.x, (int)pos.y, (int)pos.z);
                }
                else
                {
                    chunk.Write(rgi);
                }
            }
            else
            {
                if (rgi.Density > 0.001f)
                {
                    chunk = RGPoolSig.GetChunk();
                    chunk.Init(cx, cz, mEvni);
                    mChunks[cx, cz] = chunk;
                    chunk.Write(rgi);
                }
            }

            return(true);
        }
        private static int RandomCount(float expectation, RedGrassInstance rgi)
        {
            float min = (float)((int)(expectation));
            float p   = expectation - min;

            return((int)((p == 0f) ? min : ((rgi.RandAttr.x < p) ? min + 1 : min)));
        }
Exemple #3
0
        public List <RedGrassInstance> Read(int x, int z, int ymin, int ymax)
        {
            int key = PosToKey(Mathf.FloorToInt(x) & MASK, Mathf.FloorToInt(z) & MASK);

            List <RedGrassInstance> output = new List <RedGrassInstance>();

            if (mGrasses.ContainsKey(key))
            {
                RedGrassInstance rgi = mGrasses[key];
                if ((int)rgi.Position.y >= ymin && (int)rgi.Position.y <= ymax)
                {
                    output.Add(rgi);
                }

                if (mHGrass.ContainsKey(key))
                {
                    foreach (RedGrassInstance inst in mHGrass[key])
                    {
                        if ((int)inst.Position.y >= ymin && (int)inst.Position.y <= ymax)
                        {
                            output.Add(inst);
                        }
                    }
                }
            }


            return(output);
        }
Exemple #4
0
        public void Init()
        {
            RedGrassInstance.Init();

            data = new RGDataSource();
            data.Init(evniAsset, dataIO);

            RGPoolSig.Init();

            // Render Part Init
            mTree = new RGLODQuadTree(evniAsset);
        }
Exemple #5
0
        public bool Remove(int x, int y, int z)
        {
            int key = PosToKey(Mathf.FloorToInt(x) & MASK, Mathf.FloorToInt(z) & MASK);

            if (mGrasses.ContainsKey(key))
            {
                RedGrassInstance rgi = mGrasses[key];
                if ((int)rgi.Position.y == y)
                {
                    if (mHGrass.ContainsKey(key))
                    {
                        List <RedGrassInstance> rgis = mHGrass[key];
                        mGrasses[key] = rgis[0];
                        rgis.RemoveAt(0);
                        if (rgis.Count == 0)
                        {
                            RGPoolSig.RecycleRGList(rgis);
                            mHGrass.Remove(key);
                        }

                        Dirty = true;
                        return(true);
                    }
                    else
                    {
                        Dirty = true;
                        mGrasses.Remove(key);
                        return(true);
                    }
                }
                else if (mHGrass.ContainsKey(key))
                {
                    int index = mHGrass[key].FindIndex(item0 => (int)item0.Position.y == y);
                    if (index != -1)
                    {
                        mHGrass[key].RemoveAt(index);
                        if (mHGrass[key].Count == 0)
                        {
                            mHGrass.Remove(key);
                        }

                        Dirty = true;
                        return(true);
                    }
                }
            }

            return(false);
        }
Exemple #6
0
        public RedGrassInstance Read(int x, int y, int z)
        {
            int key = PosToKey(Mathf.FloorToInt(x) & MASK, Mathf.FloorToInt(z) & MASK);

            if (mGrasses.ContainsKey(key))
            {
                RedGrassInstance rgi = mGrasses[key];
                if ((int)rgi.Position.y == y)
                {
                    return(rgi);
                }
                else if (mHGrass.ContainsKey(key))
                {
                    return(mHGrass[key].Find(item0 => (int)item0.Position.y == y));
                }
            }

            return(new RedGrassInstance());
        }
        public static void ComputeParticleMesh(RedGrassInstance[] grass_array, int count)
        {
            s_Output.Reset();

            // Billboard grasses
            for (int i = 0; i < count; ++i)
            {
                RedGrassInstance vgi = grass_array[i];

                int a = i * 4;
                int b = a + 1;
                int c = a + 2;
                int d = a + 3;

                s_Output.Norms[d]             =
                    s_Output.Norms[c]         =
                        s_Output.Norms[b]     =
                            s_Output.Norms[a] = vgi.RandPos(0);

                Vector3 n = vgi.Normal;

                s_Output.UVs[d]             =
                    s_Output.UVs[c]         =
                        s_Output.UVs[b]     =
                            s_Output.UVs[a] = new Vector2(n.x, n.z);

                s_Output.UV2s[d]             =
                    s_Output.UV2s[c]         =
                        s_Output.UV2s[b]     =
                            s_Output.UV2s[a] = new Vector2((float)(vgi.Prototype) / (float)(RGPrototypeMgr.s_PrototypeCount), 0);

                s_Output.Color32s[d]             =
                    s_Output.Color32s[c]         =
                        s_Output.Color32s[b]     =
                            s_Output.Color32s[a] = Color.white;
            }
            s_Output.BillboardCount = count;
            s_Output.TriquadCount   = 0;
            s_Output.TotalVertCount = count * 4;
        }
Exemple #8
0
        public void Write(RedGrassInstance grass)
        {
            Vector3 pos = grass.Position;
            int     y   = (int)pos.y;
            int     key = PosToKey(Mathf.FloorToInt(pos.x) & MASK, Mathf.FloorToInt(pos.z) & MASK);

            if (mGrasses.ContainsKey(key))
            {
                RedGrassInstance rgi = mGrasses[key];
                if ((int)rgi.Position.y == y)
                {
                    mGrasses[key] = grass;
                }
                else if (mHGrass.ContainsKey(key))
                {
                    List <RedGrassInstance> rgis = mHGrass[key];
                    int index = rgis.FindIndex(item0 => (int)item0.Position.y == y);
                    if (index != -1)
                    {
                        rgis[index] = grass;
                    }
                    else
                    {
                        rgis.Add(grass);
                    }
                }
                else
                {
                    List <RedGrassInstance> rgis = RGPoolSig.GetRGList();
                    rgis.Add(grass);
                    mHGrass[key] = rgis;
                }
            }
            else
            {
                mGrasses.Add(key, grass);
            }

            Dirty = true;
        }
        void DeleteGrass(Vector3 point, Vector3 nml)
        {
            int step = Mathf.CeilToInt(radius / 30) * 2;

            bool    up  = (nml.y >= -0.1f && Camera.main.transform.forward.y < 0.7f);
            Vector3 dir = up ? Vector3.down : Vector3.up;
            float   h   = up ? point.y + radius : point.y - radius;

            int half_step = step / 2;

            Color[] pixels = mapProjector.MapTex.GetPixels();
            int     tex_h  = mapProjector.MapTex.height;
            int     tex_w  = mapProjector.MapTex.width;


            for (float x = -radius; x < radius; x += 1)
            {
                for (float z = -radius; z < radius; z += 1)
                {
                    Vector3 tar_pos = point + new Vector3(x, h, z);
                    Ray     ray     = new Ray(tar_pos, dir);

                    RaycastHit rch;
                    if (Physics.Raycast(ray, out rch, 1000, (1 << Pathea.Layer.VFVoxelTerrain)))
                    {
                        for (int dx = -half_step; dx <= half_step; dx++)
                        {
                            for (int dz = -half_step; dz <= half_step; dz++)
                            {
                                Vector2 tex_pos = new Vector2(((x + dx) / radius + 1) * 0.5f * tex_w, ((z + dz) / radius + 1) * 0.5f * tex_h);

                                float fd = CalcHeight(tex_pos, pixels, tex_w, tex_h) * density;

                                List <RedGrassInstance> old_grasses = scene.data.Read((int)tar_pos.x + dx, (int)tar_pos.z + dz,
                                                                                      (int)rch.point.y - half_step - 1, (int)rch.point.y + half_step + 1 + Mathf.Max(0, deleteHeight));

                                if (fd < 0.0001f)
                                {
                                    continue;
                                }

                                foreach (RedGrassInstance old_vgi in old_grasses)
                                {
                                    RedGrassInstance new_vgi = new RedGrassInstance();
                                    new_vgi.Position  = old_vgi.Position;
                                    new_vgi.Normal    = old_vgi.Normal;
                                    new_vgi.Density   = Mathf.Max(0, old_vgi.Density - fd);
                                    new_vgi.ColorF    = old_vgi.ColorF;
                                    new_vgi.Prototype = old_vgi.Prototype;

                                    // Modidy
                                    if (scene.data.Write(new_vgi))
                                    {
                                        Vector3 _pos = new_vgi.Position;
                                        mAddGrasses[new INTVECTOR3((int)_pos.x, (int)_pos.y, (int)_pos.z)] = new_vgi;
                                    }
                                }
                            }
                        }

                        //					Vector2 tex_pos = new Vector2( (x / radius + 1) * 0.5f * tex_w, (z / radius + 1) * 0.5f * tex_h );
                        //					float fd = CalcHeight(tex_pos, pixels, tex_w, tex_h) * density;
                        //
                        //					List<RedGrassInstance> old_grasses = scene.data.Read((int)tar_pos.x, (int)tar_pos.z,
                        //							                                                     (int)rch.point.y - half_step -1, (int)rch.point.y + half_step + 1);
                        //
                        //					if (fd < 0.0001f)
                        //						continue;
                        //
                        //					foreach (RedGrassInstance old_vgi in old_grasses)
                        //					{
                        //						RedGrassInstance new_vgi = new RedGrassInstance();
                        //						new_vgi.Position    = old_vgi.Position;
                        //						new_vgi.Normal	    = old_vgi.Normal;
                        //						new_vgi.Density     = Mathf.Max(0, old_vgi.Density - fd);
                        //						new_vgi.ColorF	    = old_vgi.ColorF;
                        //						new_vgi.Prototype	= old_vgi.Prototype;
                        //
                        //						// Modidy
                        //						if (scene.data.Write(new_vgi))
                        //						{
                        //							Vector3 _pos = new_vgi.Position;
                        //							mAddGrasses[new INTVECTOR3((int)_pos.x, (int)_pos.y, (int)_pos.z)] = new_vgi;
                        //						}
                        //
                        //					}
                    }
                }
            }
        }
        void DrawGrass(Vector3 point, Vector3 nml, int[] protos)
        {
            float size = radius * 2;
            int   step = Mathf.Clamp(Mathf.RoundToInt(size / 30) + 1, 1, 4);

            float begin_x = Mathf.Max(0, point.x - radius - step);
            float end_x   = point.x + radius + step * 2;
            float begin_z = Mathf.Max(0, point.z - radius - step);
            float end_z   = point.z + radius + step * 2;

            bool up = (point.y >= -0.1f && Camera.main.transform.forward.y < 0.7f);


            // Calc heights matrixs
            int count = Mathf.CeilToInt(size / step) + 1;

            float[,] heights = new float[count + 2, count + 2];

            Vector3 dir = up ? Vector3.down : Vector3.up;
            float   h   = up ? point.y + 100 : point.y - 100;

            {
                int i = 0;
                for (float x = begin_x; x < end_x; x += step, i++)
                {
                    int j = 0;
                    for (float z = begin_z; z < end_z; z += step, j++)
                    {
                        Vector3 p = new Vector3(x, h, z);

                        RaycastHit rch;
                        Ray        ray = new Ray(p, dir);
                        if (Physics.Raycast(ray, out rch, 1000, 1 << Pathea.Layer.VFVoxelTerrain))
                        {
                            heights[i, j] = rch.point.y;
                        }
                    }
                }
            }

            // Calc normal matrixs
            _normals = new Vector3[count, count];
            for (int i = 0; i < count; ++i)
            {
                for (int j = 0; j < count; ++j)
                {
                    _normals[i, j] = CalculateNormal(heights[i + 2, j + 1], heights[i, j + 1], heights[i + 1, j + 2], heights[i + 1, j], step * 2);
                }
            }

            // readly draw
            int bound = Mathf.CeilToInt(radius);

            Color[] pixels = mapProjector.MapTex.GetPixels();
            int     tex_h  = mapProjector.MapTex.height;
            int     tex_w  = mapProjector.MapTex.width;

            for (int x = -bound; x <= bound; ++x)
            {
                for (int z = -bound; z <= bound; ++z)
                {
                    Vector3 p = point + new Vector3(x, h, z);

                    Vector2 tex_pos     = new Vector2((float)(x + radius) / (radius * 2) * tex_w, (float)(z + radius) / (radius * 2) * tex_h);
                    float   pic_density = CalcHeight(tex_pos, pixels, tex_w, tex_h);
                    float   den         = Mathf.Clamp01(pic_density * density);

                    if (pic_density < 0.02f || den < 0.002f)
                    {
                        continue;
                    }

                    RaycastHit rch;
                    if (Physics.Raycast(p, dir, out rch, 1000, (1 << Pathea.Layer.VFVoxelTerrain)))
                    {
                        INTVECTOR3       ipos    = new INTVECTOR3((int)rch.point.x, (int)rch.point.y, (int)rch.point.z);
                        RedGrassInstance old_rgi = scene.data.Read(ipos.x, ipos.y, ipos.z);

                        if (old_rgi.Density < 0.001f)
                        {
                            RedGrassInstance rgi = new RedGrassInstance();
                            rgi.Density  = den;
                            rgi.Position = rch.point;

                            rgi.Prototype = protos[Random.Range(0, protos.Length) % protos.Length];
                            rgi.ColorF    = Color.white;

                            if (scene.data.Write(rgi))
                            {
                                mAddGrasses[ipos] = rgi;
                            }
                        }
                        else
                        {
                            RedGrassInstance rgi = new RedGrassInstance();
                            rgi.Density  = Mathf.Clamp01(den + old_rgi.Density);
                            rgi.Position = old_rgi.Position;

                            if (Random.value < density)
                            {
                                rgi.Prototype = protos[Random.Range(0, protos.Length) % protos.Length];
                            }
                            else
                            {
                                rgi.Prototype = old_rgi.Prototype;
                            }

                            rgi.ColorF = old_rgi.ColorF;
                            rgi.Normal = old_rgi.Normal;

                            if (scene.data.Write(rgi))
                            {
                                mAddGrasses[ipos] = rgi;
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Computes the mesh elements info the output
        /// </summary>
        /// <param name='grass_list'>
        /// Grass list.
        /// </param>
        /// <param name='density'>
        /// Global Density.
        /// </param>
        public static void ComputeMesh(List <RedGrassInstance> grass_list, List <RedGrassInstance> tri_grass_list, float density)
        {
            try
            {
                s_Output.Reset();
                int grass_cnt     = 0;
                int tri_grass_cnt = 0;
                if (grass_list != null)
                {
                    grass_cnt = grass_list.Count;
                }
                if (tri_grass_list != null)
                {
                    tri_grass_cnt = tri_grass_list.Count;
                }

                Vector3 up               = Vector3.up;
                int     quad             = 0;
                float   _2pi             = Mathf.PI * 2;
                float   _page_interval   = _2pi / 3;
                float   angle_randomness = 0.3f;

                // Billboard grasses
                for (int i = 0; i < grass_cnt; ++i)
                {
                    RedGrassInstance vgi = grass_list[i];
                    int randcnt          = RandomCount(s_FullDensity * vgi.Density * density, vgi);
                    for (int q = 0; q < randcnt; ++q)
                    {
                        int a = quad * 4;
                        int b = a + 1;
                        int c = a + 2;
                        int d = a + 3;

                        s_Output.Norms[d]             =
                            s_Output.Norms[c]         =
                                s_Output.Norms[b]     =
                                    s_Output.Norms[a] = vgi.RandPos(q);

                        Vector3 n  = vgi.Normal;
                        Vector3 n1 = (n * 1.25f - up * 0.25f).normalized;
                        Vector3 n2 = (n * 0.5f + up * 0.5f).normalized;

                        s_Output.UVs[a]     = new Vector2(n1.x, n1.z);
                        s_Output.UVs[c]     =
                            s_Output.UVs[b] = new Vector2(n2.x, n2.z);
                        s_Output.UVs[d]     = s_Output.UVs[a];

                        s_Output.UV2s[d]             =
                            s_Output.UV2s[c]         =
                                s_Output.UV2s[b]     =
                                    s_Output.UV2s[a] = new Vector2((float)(vgi.Prototype) / (float)(RGPrototypeMgr.s_PrototypeCount), 0);

                        s_Output.Color32s[d]             =
                            s_Output.Color32s[c]         =
                                s_Output.Color32s[b]     =
                                    s_Output.Color32s[a] = vgi.ColorDw;

                        quad++;
                    }
                }
                s_Output.BillboardCount = quad;

                // Tri-quad grasses
                for (int i = 0; i < tri_grass_cnt; ++i)
                {
                    RedGrassInstance vgi = tri_grass_list[i];
                    int randcnt          = RandomCount(s_FullDensity * vgi.Density * density * 0.333f, vgi);
                    for (int t = 0; t < randcnt; ++t)
                    {
                        float   phase   = (float)(vgi.RandAttr.x) * _2pi;
                        Vector3 randpos = vgi.RandPos(t);
                        for (int page = 0; page < 3; ++page)
                        {
                            int a = quad * 4;
                            int b = a + 1;
                            int c = a + 2;
                            int d = a + 3;

                            s_Output.Norms[d]             =
                                s_Output.Norms[c]         =
                                    s_Output.Norms[b]     =
                                        s_Output.Norms[a] = randpos;

                            Vector3 n  = vgi.Normal;
                            Vector3 n1 = (n * 1.1f - up * 0.1f).normalized;
                            Vector3 n2 = (n * 0.5f + up * 0.5f).normalized;

                            s_Output.UVs[a]     = new Vector2(n1.x, n1.z);
                            s_Output.UVs[c]     =
                                s_Output.UVs[b] = new Vector2(n2.x, n2.z);
                            s_Output.UVs[d]     = s_Output.UVs[a];

                            s_Output.UV2s[d]             =
                                s_Output.UV2s[c]         =
                                    s_Output.UV2s[b]     =
                                        s_Output.UV2s[a] = new Vector2((float)(vgi.Prototype - 64) / (float)(RGPrototypeMgr.s_PrototypeCount),
                                                                       page * _page_interval + phase + ((float)(vgi.RandAttrs(page + 1).x) - 0.5f) * angle_randomness);

                            s_Output.Color32s[d]             =
                                s_Output.Color32s[c]         =
                                    s_Output.Color32s[b]     =
                                        s_Output.Color32s[a] = vgi.ColorDw;

                            quad++;
                        }
                    }
                }
                s_Output.TriquadCount   = quad - s_Output.BillboardCount;
                s_Output.TotalVertCount = quad * 4;
            }
            catch
            {
                Debug.Log("-----------------------------Grass Thread error");
            }
        }