public override void Render() { VideoDriver driver = _mgr.VideoDriver; CameraSceneNode camera = _mgr.ActiveCamera; if (camera == null || driver == null) return; if (!redrawnextloop) { driver.SetTransform(TransformationState.World, AbsoluteTransformation); driver.SetMaterial(_material); driver.DrawIndexedTriangleList(Vertices, lastdrawcount * 4, Indices, lastdrawcount * 4); } else { ReallocateBuffers(); Vector3D campos = camera.AbsolutePosition; Box3D cbox = camera.ViewFrustum.BoundingBox; Vector3D pos = Position; int drawcount = 0; int max = (Particles.Length < MaxDensity) ? Particles.Length : MaxDensity; double d = pos.DistanceFrom(campos) / GRASS_PATCH_SIZE; if (d > 1.0) max = (int)(max / d); //Matrix4 m = new Matrix4(); for (int i = 0; i < max; i++) { int idx = drawcount * 4; GrassParticle particle = Particles[i]; Vector3D gpos = particle.pos + pos; double dist = campos.DistanceFromSQ(gpos); if (dist > NewMath.Sqr(DrawDistance)) continue; if (!cbox.IsPointInside(gpos)) continue; if (dist > NewMath.Sqr(DrawDistance * 0.5)) { if (particle.sprite.Height == 0) { float i1 = ((float)i) / ((float)max); float i2 = ((float)(dist / DrawDistance)) / 2f; if (i1 < i2) continue; } } int igridsize = GRASS_PATCH_SIZE / (int)WindRes; int ihalfres = (int)WindRes / 2; int xgrid = (int)(particle.pos.X / (igridsize) + ihalfres); int zgrid = (int)(particle.pos.Z / (igridsize) + ihalfres); float xnext = particle.pos.X / ((float)GRASS_PATCH_SIZE / (float)WindRes) + (WindRes / 2f) - xgrid; float znext = particle.pos.Z / ((float)GRASS_PATCH_SIZE / (float)WindRes) + (WindRes / 2f) - zgrid; Vector2D wind1 = WindGrid[xgrid * WindRes + zgrid]; Vector2D wind2 = WindGrid[(xgrid + 1) * WindRes + zgrid]; Vector2D wind3 = WindGrid[xgrid * (WindRes + 1) + zgrid]; Vector2D wind4 = WindGrid[(xgrid + 1) * (WindRes + 1) + zgrid]; Vector2D wind2d = wind1 * (1.0f - xnext) * (1.0f - znext) + wind2 * xnext * (1.0f - znext) + wind3 * (1.0f - xnext) * znext + wind4 * xnext * znext; wind2d *= particle.flex; Vector3D wind = new Vector3D(wind2d.X, 0f, wind2d.Y); Color gcol = new Color(particle.color.A, (int)(particle.color.R * 0.8f), (int)(particle.color.G * 0.8f), (int)(particle.color.B * 0.8f)); Vertices[0 + idx].Position = particle.points[0]; Vertices[0 + idx].Color = gcol; Vertices[1 + idx].Position = particle.points[1] + wind; Vertices[1 + idx].Color = particle.color; Vertices[2 + idx].Position = particle.points[2] + wind; Vertices[2 + idx].Color = particle.color; Vertices[3 + idx].Position = particle.points[3]; Vertices[3 + idx].Color = gcol; int arrpos = (_imagecount.Width * particle.sprite.Height) + particle.sprite.Width; Vertices[0 + idx].TCoords = new Vector2D(v1[arrpos], v2[arrpos]); Vertices[1 + idx].TCoords = new Vector2D(v1[arrpos], v3[arrpos]); Vertices[2 + idx].TCoords = new Vector2D(v4[arrpos], v3[arrpos]); Vertices[3 + idx].TCoords = new Vector2D(v4[arrpos], v2[arrpos]); drawcount++; } driver.SetTransform(TransformationState.World, AbsoluteTransformation); driver.SetMaterial(_material); driver.DrawIndexedTriangleList(Vertices, drawcount * 4, Indices, drawcount * 4); lastdrawcount = drawcount; } if (DebugDataVisible == DebugSceneType.BoundingBox) { driver.SetTransform(TransformationState.World, AbsoluteTransformation); Material m = new Material(); m.Lighting = false; driver.SetMaterial(m); driver.Draw3DBox(BoundingBox, Color.From(0, 255, 255, 255)); Box3D b2 = new Box3D(); b2.AddInternalPoint(BoundingBox.MaxEdge * 0.01f); driver.Draw3DBox(b2, Color.From(0, 255, 255, 255)); } }
bool Create(bool save) { Random rand = new Random((int)((100 * gridpos.X) + gridpos.Z)); int count = rand.Next(3000, 3200); _bbox = new Box3D(); Particles = new GrassParticle[count]; /*Matrix4 m = new Matrix4(); m.RotationDegrees = Terrain.Rotation; m.Translation = Terrain.AbsolutePosition; m.MakeInverse();*/ Color[,] TGMRetrieve = TerrainGrassMap.Retrieve(); Color[,] TCMRetrieve = TerrainColourMap.Retrieve(); Color[,] THMRetrieve = TerrainHeightMap.Retrieve(); System.Collections.ArrayList tosave = new System.Collections.ArrayList(); for (int i = 0; i < count; i++) { Particles[i].points = new Vector3D[4]; float x = rand.Next(0, GRASS_PATCH_SIZE * 10) / 10f; float z = rand.Next(0, GRASS_PATCH_SIZE * 10) / 10f; x -= GRASS_PATCH_SIZE / 2f; z -= GRASS_PATCH_SIZE / 2f; Particles[i].pos.X = x; Particles[i].pos.Z = z; Particles[i].flex = rand.Next(0, 100) / 100f; Particles[i].sprite.Width = rand.Next(0, _imagecount.Width); if (i < 30) Particles[i].sprite.Height = rand.Next(0, _imagecount.Height); else Particles[i].sprite.Height = 0; Vector3D p = Position + Particles[i].pos; Vector3D xz = new Vector3D(p.X / Terrain.Scale.X, 0f, p.Z / Terrain.Scale.Z); int x1 = (int)Math.Floor(xz.X); int z1 = (int)Math.Floor(xz.Z); if (x1 < 1 || z1 < 1 || x1 > TerrainHeightMap.OriginalSize.Width - 1 || z1 > TerrainHeightMap.OriginalSize.Height - 1) continue; Color cDensity = TGMRetrieve[x1, z1]; if (rand.Next(0, 255) > cDensity.A || cDensity.A < 1) continue; float ay = THMRetrieve[x1, z1].B * Terrain.Scale.Y; float by = THMRetrieve[x1 + 1, z1].B * Terrain.Scale.Y; float cy = THMRetrieve[x1, z1 + 1].B * Terrain.Scale.Y; float dy = THMRetrieve[x1 + 1, z1 + 1].B * Terrain.Scale.Y; float u1 = xz.X - x1; float v1 = xz.Z - z1; float height = ay * (1.0f - u1) * (1.0f - v1) + by * u1 * (1.0f - v1) + cy * (1.0f - u1) * v1 + dy * u1 * v1; Dimension2Df size = new Dimension2Df(rand.Next(40, 70), 100); size.Height *= cDensity.B / 200f; Particles[i].pos.Y = height + (size.Height * 0.5f); Particles[i].color = TCMRetrieve[x1, z1]; Particles[i].startColor = TCMRetrieve[x1, z1]; _bbox.AddInternalPoint(Particles[i].pos); Vector3D dimensions = new Vector3D(0.5f * size.Width, -0.5f * size.Height, 0); /*float rotation = rand.Next(0, 3600) / 10f; Matrix4 m2 = new Matrix4(); m2.RotationDegrees = new Vector3D(0, rotation, 0); m2.RotateVect(dimensions);*/ //Vector3D h = new Vector3D(dimensions.X,0.0f,dimensions.Z); //Vector3D v = new Vector3D(0.0f,dimensions.Y,0.0f); Particles[i].points[0] = Particles[i].pos + new Vector3D(dimensions.X, dimensions.Y, dimensions.Z); Particles[i].points[1] = Particles[i].pos + new Vector3D(dimensions.X, -dimensions.Y, dimensions.Z); Particles[i].points[2] = Particles[i].pos - new Vector3D(dimensions.X, dimensions.Y, dimensions.Z); Particles[i].points[3] = Particles[i].pos - new Vector3D(dimensions.X, -dimensions.Y, dimensions.Z); tosave.Add(Particles[i]); } Particles = (GrassParticle[])tosave.ToArray(typeof(GrassParticle)); tosave.Clear(); if (save) return Save(); return true; }