Grass Systems using TVMiniMesh

MiniMeshes were a community-inspired feature to allow for the same mesh to be instantiated in multiple places with different properties. It is optimized to be much faster than using many meshes. In this tutorial, we will cover a terrain with many minimeshes, which will be blades of grass. This tutorial assumes you have a basic TV setup running, such as the Templates from the beta page.

First, some basic variables need to be declared. These include a Terrain, a GrassMesh, and a GrassMini variable, along with the TGlobals class for later use.

Public TGlobals As New TVGlobals
Public Terrain As TVLandscape
Public GrassMesh As TVMesh
Public GrassMini As TVMiniMesh

Next, the terrain needs to be created. In this code, we load the terrain from a terrain data file, but any method of your choice will do. A grass texture is set and scaled as well. The texture and TVM of the terrain are included in the sample project.

Dim iGrassTex As Integer
iGrassTex = TextureFactory.LoadTexture(Application.StartupPath & "\grass.jpg", "grass")
 
Terrain = Scene.CreateLandscape("Terrain1")
Terrain.LoadTerrainData(Application.StartupPath & "\Terrain1.tvm")
Terrain.SetTexture(iGrassTex)
Terrain.SetTextureScale(4, 4)

After setting up the terrain, we need to initialize the grass mesh. Although we don’t render it, this mesh will be used to create the minimesh system later on. Here, we load the grass mesh included in the sample project, set it’s scale, and set several alpha settings to make it look right.

GrassMesh = Scene.CreateMeshBuilder("GrassMesh")
GrassMesh.LoadTVM(Application.StartupPath & "\Grass.tvm")
GrassMesh.SetBlendingMode(CONST_TV_BLENDINGMODE.TV_BLEND_ALPHA)
GrassMesh.SetAlphaTest(True, 64)
GrassMesh.SetScale(0.08, 0.08, 0.08)

Next, the minimesh system needs to be created. We specify in CreateMiniMesh that we want only 100 meshes in this system. If you ever try to access meshes over this limit, you will get a memory error. If you want to alter the max mesh count, use MiniMesh.SetMaxMeshCount(). Also, we specify we want to create from GrassMesh, we want coloring enabled, and we specify several alpha settings, which are not carried over fom the mesh at the moment.

GrassMini = Scene.CreateMiniMesh(100, "GrassMini")
GrassMini.CreateFromMesh(GrassMesh)
GrassMini.SetAlphaSort(True)
GrassMini.SetAlphaTest(True, 64)
GrassMini.SetBlendingMode(CONST_TV_BLENDINGMODE.TV_BLEND_ALPHA)
GrassMini.SetClamping(True)
GrassMini.SetColorMode(True)

We now need to go through each mesh in the system and specify properties. To start out, several variables need to be declared. First, we have the range variables, which will determine the range of possible values for the meshes.

Dim StartRotation As Single = 0
Dim EndRotation As Single = 360
 
Dim StartScale As Single = 0.8
Dim EndScale As Single = 1.2
 
Dim StartColor As Color = Color.PaleGreen
Dim EndColor As Color = Color.Green

Next come the final value variables, which will store the data for each individual mesh.

Dim x, y, z As Single
Dim Scale As Single
Dim R, B, G As Single
Dim RotationY As Single

Before we actually go through and set the properties to the meshes in the system, two functions need to be declared. The first is RndInterval, which finds a random value between specified values, and the second is BindMiniToTerrain, which aligns the mesh to the terrain along with setting position, scale, and rotation.

Public Function RndInterval(ByVal StartVal As Single, ByVal EndVal As Single) As Single
    Return (StartVal + Rnd() * (EndVal - StartVal))
End Function
 
Public Function BindMiniToLand(ByVal InMatrix As TV_3DMATRIX, ByVal Scale As TV_3DVECTOR, ByVal Position As TV_3DVECTOR, ByVal Terrain As TVLandscape) As TV_3DMATRIX
    With InMatrix
        Dim TopVector As TV_3DVECTOR = Terrain.GetNormal(Position.x, Position.z)
        Dim TentativeForwardVector As New TV_3DVECTOR(.m31, .m32, .m33)
        Dim RightVector As New TV_3DVECTOR()
        Dim ForwardVector As New TV_3DVECTOR()
        Math.TVVec3Cross(RightVector, TopVector, TentativeForwardVector)
        Math.TVVec3Cross(ForwardVector, RightVector, TopVector)
        Math.TVVec3Normalize(RightVector, RightVector)
        Math.TVVec3Normalize(ForwardVector, ForwardVector)
        .m11 = RightVector.x * Scale.x
        .m12 = RightVector.y * Scale.y
        .m13 = RightVector.z * Scale.z
        .m21 = TopVector.x * Scale.x
        .m22 = TopVector.y * Scale.y
        .m23 = TopVector.z * Scale.z
        .m31 = ForwardVector.x * Scale.x
        .m32 = ForwardVector.y * Scale.y
        .m33 = ForwardVector.z * Scale.z
        .m41 = Position.x
        .m42 = Position.y
        .m43 = Position.z
    End With
 
    Return InMatrix
End Function

Now that that’s out of the way, the program is ready to recieve instructions for the individual minimeshes. First, we set up a For/Next loop from 0 to 99 (which totals to 100 minimeshes). Next, we enable the minimesh at this index. After, we get the X/Y/Z(position), the scale, the R/G/B(color), and the RotationY, using RndInterval and the specified ranges, which you can change to your liking. Finally, we set the color to the minimesh and pass a matrix with rotation to BindMiniToLand, which finally goes to the GrassMini’s matrix.

For n As Integer = 0 To 99
    GrassMini.EnableMiniMesh(n, True)
    x = RndInterval(0, Terrain.GetLandRealWidth)
    z = RndInterval(0, Terrain.GetLandRealHeight)
    y = Terrain.GetHeight(x, z)
    Scale = RndInterval(StartScale, EndScale)
    R = RndInterval(StartColor.R, EndColor.R)
    G = RndInterval(StartColor.G, EndColor.G)
    B = RndInterval(StartColor.B, EndColor.B)
    RotationY = RndInterval(StartRotation, EndRotation)
 
    GrassMini.SetColor(TGlobals.RGBA256(R, G, B, 255), n)
 
    Dim blankM As TV_3DMATRIX
    Math.TVMatrixRotationYawPitchRoll(blankM, RotationY, 0, 0)
    GrassMini.SetMatrix(BindMiniToLand(blankM, New TV_3DVECTOR(Scale, Scale, Scale), New TV_3DVECTOR(x, y, z), Terrain), n)
Next

The last step is to render the minimesh system and the terrain in the render loop, between Tv.Clear and Tv.RenderToScreen.

Terrain.Render()
GrassMini.Render()

Now you should see your terrain covered with grass. If you want to make more grass, increase the value in CreateMiniMesh, as well as the max value in the for/next loop.

MiniMesh Sample Project: http://pizzayoyo.smithbower.com/other/MiniMeshSample.rar Don’t forget to include the lateset MTV3D65.dll in the bin\x86\release folder, and to enter your beta key.

 
tutorialsarticlesandexamples/grass_systems_using_tvminimesh.txt · Last modified: 2013/11/22 13:32