public override void LoadPage(PageInfo page) { //Calculate x/z indexes for the grid array page.XIndex -= (int)System.Math.Floor(mGridBounds.Left / mPageSize); page.ZIndex -= (int)System.Math.Floor(mGridBounds.Top / mPageSize); //Check if the requested page is in bounds if (page.XIndex < 0 || page.ZIndex < 0 || page.XIndex >= mPageGridX || page.ZIndex >= mPageGridZ) { return; } //For each tree type... foreach (KeyValuePair <Entity, List <List <TreeDef> > > it in mPageGridList) { //Get the appropriate tree list for the specified page List <List <TreeDef> > pageGrid = it.Value; List <TreeDef> treeList = GetGridPage(pageGrid, page.XIndex, page.ZIndex); Entity entity = it.Key; //Load the listed trees into the page foreach (TreeDef o in treeList) { //Get position Vector3 pos = Vector3.Zero; pos.x = page.Bounds.Left + ((float)o.XPos / 65535) * mPageSize; pos.z = page.Bounds.Top + ((float)o.ZPos / 65535) * mPageSize; //Calculate terrain height at pos.x / pos.z to get pos.y if (mHeightFunction != null) { pos.y = mHeightFunction.GetHeightAt(pos.x, pos.z, mHeightFunctionUserData); } else { pos.y = 0.0f; } //Get rotation Degree angle = new Degree((Real)o.Rotation * (360.0f / 255)); Quaternion rot = Quaternion.FromAngleAxis((float)angle.InRadians, Vector3.UnitY); //Get scale Vector3 scale = Vector3.Zero; scale.y = (float)(o.Scale * (mMaximumScale / 255) + mMinimumScale); scale.x = scale.y; scale.z = scale.y; //Get color ColorEx col = ColorEx.White; if (mColorMap != null) { col = mColorMap.GetColorAtUnpacked(pos.x, pos.z); } AddEntity(entity, pos, rot, scale, col); } } }
/// <summary> /// /// </summary> /// <param name="page"></param> /// <param name="layer"></param> /// <param name="grassPostions"></param> /// <param name="grassCount"></param> /// <returns></returns> private Mesh GenerateGrassQuad(PageInfo page, GrassLayer layer, IntPtr grassPostions, int grassCount) { //Calculate the number of quads to be added int quadCount = grassCount; //Create manual mesh to store grass quads Mesh mesh = (Mesh)MeshManager.Instance.CreateManual(GetUniqueID(), ResourceGroupManager.DefaultResourceGroupName, null); SubMesh subMesh = mesh.CreateSubMesh(); subMesh.useSharedVertices = false; //Setup vertex format information subMesh.vertexData = new VertexData(); subMesh.vertexData.vertexStart = 0; subMesh.vertexData.vertexCount = 4 * quadCount; VertexDeclaration dcl = subMesh.vertexData.vertexDeclaration; int offset = 0; dcl.AddElement(0, offset, VertexElementType.Float3, VertexElementSemantic.Position); offset += VertexElement.GetTypeSize(VertexElementType.Float3); dcl.AddElement(0, offset, VertexElementType.Color, VertexElementSemantic.Diffuse); offset += VertexElement.GetTypeSize(VertexElementType.Color); dcl.AddElement(0, offset, VertexElementType.Float2, VertexElementSemantic.TexCoords); offset += VertexElement.GetTypeSize(VertexElementType.Float2); //Populate a new vertex buffer with grass HardwareVertexBuffer vbuf = HardwareBufferManager.Instance.CreateVertexBuffer( /*offset*/ dcl, subMesh.vertexData.vertexCount, BufferUsage.DynamicWriteOnly, false); unsafe { float *pReal = (float *)vbuf.Lock(BufferLocking.Discard); //Calculate size variance float rndWidth = layer.mMaxWidth - layer.mMinWidth; float rndHeight = layer.mMaxHeight - layer.mMinHeight; float minY = float.PositiveInfinity, maxY = float.NegativeInfinity; float *posPtr = (float *)grassPostions; //Position array "iterator" for (int i = 0; i < grassCount; i++) { //Get the x and z positions from the position array float x = *posPtr++; float z = *posPtr++; //Get the color at the grass position uint color = 0; if (layer.ColorMap != null) { color = layer.ColorMap.GetColorAt(x, z); } else { color = 0xFFFFFFFF; } //Calculate size float rnd = MogreLibMath.Utility.UnitRandom();//The same rnd value is used for width and height to maintain aspect ratio float halfScaleX = (layer.mMinWidth + rndWidth * rnd) * 0.5f; float scaleY = (layer.mMinWidth + rndHeight * rnd); //Calculate rotation float angle = MogreLibMath.Utility.RangeRandom(0, MogreLibMath.Utility.TWO_PI); float xTrans = MogreLibMath.Utility.Cos(angle) * halfScaleX; float zTrans = MogreLibMath.Utility.Sin(angle) * halfScaleX; //Calculate heights and edge positions float x1 = x - xTrans, z1 = z - zTrans; float x2 = x + xTrans, z2 = z + zTrans; float y1, y2; if (mHeightFunction != null) { y1 = mHeightFunction.GetHeightAt(x1, z1, mHeightFunctionUserData); y2 = mHeightFunction.GetHeightAt(x2, z2, mHeightFunctionUserData); } else { y1 = 0; y2 = 0; } //Add vertices *pReal++ = (x1 - page.CenterPoint.x); *pReal++ = (y1 + scaleY); *pReal++ = (z1 - page.CenterPoint.z); //pos *((uint *)pReal++) = color; //color *pReal++ = 0; *pReal++ = 0; //uv *pReal++ = (x2 - page.CenterPoint.x); *pReal++ = (y2 + scaleY); *pReal++ = (z2 - page.CenterPoint.z); //pos *((uint *)pReal++) = color; //color *pReal++ = 1; *pReal++ = 0; //uv *pReal++ = (x1 - page.CenterPoint.x); *pReal++ = (y1); *pReal++ = (z1 - page.CenterPoint.z); //pos *((uint *)pReal++) = color; //color *pReal++ = 0; *pReal++ = 1; //uv *pReal++ = (x2 - page.CenterPoint.x); *pReal++ = (y2); *pReal++ = (z2 - page.CenterPoint.z); //pos *((uint *)pReal++) = color; //color *pReal++ = 1; *pReal++ = 1; //uv //Update bounds if (y1 < minY) { minY = y1; } if (y2 < minY) { minY = y2; } if (y1 + scaleY > maxY) { maxY = y1 + scaleY; } if (y2 + scaleY > maxY) { maxY = y2 + scaleY; } } vbuf.Unlock(); subMesh.vertexData.vertexBufferBinding.SetBinding(0, vbuf); //Populate index buffer subMesh.indexData.indexStart = 0; subMesh.indexData.indexCount = 6 * quadCount; subMesh.indexData.indexBuffer = HardwareBufferManager.Instance.CreateIndexBuffer( IndexType.Size16, subMesh.indexData.indexCount, BufferUsage.DynamicWriteOnly); ushort *pI = (ushort *)subMesh.indexData.indexBuffer.Lock(BufferLocking.Discard); for (ushort i = 0; i < quadCount; i++) { ushort ofset = (ushort)(i * 4); * pI++ = (ushort)(0 + ofset); * pI++ = (ushort)(2 + ofset); * pI++ = (ushort)(1 + ofset); *pI++ = (ushort)(1 + ofset); *pI++ = (ushort)(2 + ofset); *pI++ = (ushort)(3 + ofset); } subMesh.indexData.indexBuffer.Unlock(); //Finish up mesh AxisAlignedBox bounds = new AxisAlignedBox( new Vector3(page.Bounds.Left - page.CenterPoint.x, minY, page.Bounds.Top - page.CenterPoint.z), new Vector3(page.Bounds.Right - page.CenterPoint.x, maxY, page.Bounds.Bottom - page.CenterPoint.z)); mesh.BoundingBox = bounds; Vector3 tmp = bounds.Maximum - bounds.Minimum; mesh.BoundingSphereRadius = tmp.Length * 0.5f; mesh.Load(); //Apply grass material to mesh subMesh.MaterialName = layer.Material.Name; //Return the mesh return(mesh); } }