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))); }
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); }
public void Init() { RedGrassInstance.Init(); data = new RGDataSource(); data.Init(evniAsset, dataIO); RGPoolSig.Init(); // Render Part Init mTree = new RGLODQuadTree(evniAsset); }
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); }
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; }
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"); } }