' ________________________________________________________________________ ' TrueVision3D (web: http://www.truevision3d.com) ' ???????????????????????????????????? ' Tutorial 7 : A landscape. ' ????? ' Description : In this 7th tutorial, we keep the movement code from ' ?????? the last tutorial but change the room for a land. ' Terrain/Landscape is another big feature of TV3D ' It allows to render really huge and realistic outdoors scene ' using detailed terrain and texture. ' ' ' Update on the basic steps : Since the beginning, we have been playing ' ????????????? with all the objects included in TV3D. Now, ' it's time to add extra functionnality by ' adding DirectX8 to our project. So, just ' like the first time you referenced TV3D to ' your project, reference "DirectX8 for ' Visual Basic Type Library".
' Force explicit declarations Option Explicit
' We declare TrueVision3D. Private TV3D As TVEngine
' We declare the landscape Private Land As TVLandscape
' Defines the texture factory. To apply a texture to the land, we have ' to use and other object that will hold all the textures needed ' in our project. Private TextureFactory As TVTextureFactory
' We the declare the scene Private Scene As TVScene
' We declare the input engine. Private InputEngine As TVInputEngine
' We declare the atmosphere Private Atmos As TVAtmosphere
' The loop. Private DoLoop As Boolean
' We are going to use camera (point of view) angles, as well as the ' camera position and look at vectors. Private sngPositionX As Single Private sngPositionY As Single Private sngPositionZ As Single Private snglookatX As Single Private snglookatY As Single Private snglookatZ As Single Private sngAngleX As Single Private sngAngleY As Single
' We could have done this in many ways, but we added some smoothing to ' the movement se we need to declare two additional variables. Private sngWalk As Single Private sngStrafe As Single
' We declare a variable which will hold the water height. Private sngWaterHeight As Single
Private Sub cmdQuit_Click()
' We have clicked on the "Quit" button, so we change the DoLoop. DoLoop = False
End Sub
Private Sub Form_Load()
' We have to create the TV3D object before anything else. Set TV3D = New TVEngine
' Set the search directory of the objects, textures, ... TV3D.SetSearchDirectory App.Path ' We initialize TV3D in the picture box of the form. TV3D.Init3DWindowedMode Picture1.hWnd
' We want to see the FPS. TV3D.DisplayFPS = True
' We create the input object. Set InputEngine = New TVInputEngine
' We create the scene (the world). Set Scene = New TVScene ' We create the atmosphere for the sky Set Atmos = New TVAtmosphere
' We need to create a new object which will ' hold all the textures needed for our land. Set TextureFactory = New TVTextureFactory
' We load the sky textures. TextureFactory.LoadTexture "..\..\..\Media\sky\sunset\up.jpg", "SkyTop" TextureFactory.LoadTexture "..\..\..\Media\sky\sunset\down.jpg", "SkyBottom" TextureFactory.LoadTexture "..\..\..\Media\sky\sunset\left.jpg", "SkyLeft" TextureFactory.LoadTexture "..\..\..\Media\sky\sunset\right.jpg", "SkyRight" TextureFactory.LoadTexture "..\..\..\Media\sky\sunset\front.jpg", "SkyFront" TextureFactory.LoadTexture "..\..\..\Media\sky\sunset\back.jpg", "SkyBack" ' We set the sky textures, into on each face of the skycube.
Atmos.SkyBox_SetTexture GetTex("SkyFront"), GetTex("SkyBack"), GetTex("SkyLeft"), GetTex("SkyRight"), GetTex("SkyTop"), GetTex("SkyBottom") Atmos.SkyBox_Enable True
' New : the land generation. This is so much fun because it's ' so You load a texture as a height map, the engine ' does the rest. But before this, we create the land object. '设置地形 Set Land = New TVLandscape ' Generate the height of the land from the grayscale of the image. ' Black is altitude 0 for the engine, and White is altitude 255. ' See the FAQ of JohnnyC on the site, for further information ' about all the subtilities of Terrain generation. '生成巨大地形根据灰度图形,黑色海拔为0,白色海拔为255 Land.GenerateHugeTerrain "..\..\..\Media\heightmap.jpg", TV_PRECISION_LOW, 8, 8, 0, 0, True ' Then, we load the land texture that will be applied to the land ' here we take a grass texture. '加载材质 TextureFactory.LoadTexture "..\..\..\Media\grass9.jpg", "LandTexture" ' We assign a texture to that land. '将材质赋给地面 Land.SetTexture GetTex("LandTexture") ' Change the tiling of the texture, this means that you can repeat the texture motif ' several times per landscape chunk (part of terrain) or several times. ' Here we will repeat the grass motif 2x2 on a chunk '设置材质刻度 Land.SetTextureScale 2, 2 ' Now we set simply the viewdistance '设置视图距离 Scene.SetViewFrustum 60, 5000 ' We set the camera vectors (position and look at) and angles. ' at the center of the landscape. sngPositionX = 512 sngPositionY = 20 sngPositionZ = 512 snglookatX = 512 snglookatY = 20 snglookatZ = 550 sngAngleX = 0 sngAngleY = 0 ' We set the initial values of movement sngWalk = 0 sngStrafe = 0 ' We pop the form over everything else. Form1.Show ' We start the main loop. DoLoop = True Main_Loop
End Sub
Private Sub Form_Unload(Cancel As Integer)
' The user asked to quit but clicked on the 'X' button at up right. DoLoop = False ' And ask to quit. Main_Quit
End Sub
Private Sub Main_Loop() ' The main loop Do ' Let us the capacity to use buttons of the form. DoEvents ' New : We moved the movement code in an other sub to make ' the code clearer. '检测输入 Check_Input ' New : We moved the checking of maximum camera "look at" and ' also the camera movement smoothing in an other sub too. '检没移动 Check_Movement
' Clear the the last frame. TV3D.Clear ' New have to render the sky. Atmos.Atmosphere_Render ' New : we have to render the landscape. Land.Render True ' We render all the 3D objects contained in the scene. Scene.RenderAllMeshes ' We display everything that we have rendered TV3D.RenderToScreen 'We loop all of this until the DoLoop isn't True. Loop Until DoLoop = False ' We ask to quit. Main_Quit
End Sub
Private Sub Check_Input() ' Check if we pressed the UP arrow key, if so, then we are ' walking forward. If InputEngine.IsKeyPressed(TV_KEY_UP) = True Then sngWalk = 1 ' If we are not walking forward, maybe we are walking backward ' by using the DOWN arrow? If so, set walk speed to negative. ElseIf InputEngine.IsKeyPressed(TV_KEY_DOWN) = True Then sngWalk = -1 End If
' Check if we pressed the LEFT arrow key, if so, then strafe ' on the left. If InputEngine.IsKeyPressed(TV_KEY_LEFT) = True Then sngStrafe = 1 ' If we are not strafing left, maybe we want to strafe to the ' right, using the RIGHT arrow? If so, set strafe to negative. ElseIf InputEngine.IsKeyPressed(TV_KEY_RIGHT) = True Then sngStrafe = -1 End If
' Now, for the mouse input... Dim tmpMouseX As Long, tmpMouseY As Long Dim tmpMouseB1 As Integer, tmpMouseB2 As Integer, tmpMouseB3 As Integer Dim tmpMouseScrollOld As Long, tmpMouseScrollNew As Long
' Actual value to old mouse scroller value. tmpMouseScrollOld = tmpMouseScrollNew
' Get the movement of the mouse. InputEngine.GetMouseState tmpMouseX, tmpMouseY, tmpMouseB1, tmpMouseB2, tmpMouseB3, tmpMouseScrollNew
' Update the camera angles. sngAngleX = sngAngleX - (tmpMouseY / 100) sngAngleY = sngAngleY - (tmpMouseX / 100)
End Sub
Private Sub Check_Movement() ' Simple check of the mouse. If sngAngleX > 1.3 Then sngAngleX = 1.3 If sngAngleX < -1.3 Then sngAngleX = -1.3
' Okay, now for the smothing of the movement... Update ' the forward and backward (walk) movement. Select Case sngWalk Case Is > 0 sngWalk = sngWalk - 0.005 * TV3D.TimeElapsed If sngWalk < 0 Then sngWalk = 0 Case Is < 0 sngWalk = sngWalk + 0.005 * TV3D.TimeElapsed If sngWalk > 0 Then sngWalk = 0 End Select ' Now, we update the left and right (strafe) movement. Select Case sngStrafe Case Is > 0 sngStrafe = sngStrafe - 0.005 * TV3D.TimeElapsed If sngStrafe < 0 Then sngStrafe = 0 Case Is < 0 sngStrafe = sngStrafe + 0.005 * TV3D.TimeElapsed If sngStrafe > 0 Then sngStrafe = 0 End Select ' Update the vectors using the angles and positions. sngPositionX = sngPositionX + (Cos(sngAngleY) * sngWalk / 5 * TV3D.TimeElapsed) + (Cos(sngAngleY + 3.141596 / 2) * sngStrafe / 5 * TV3D.TimeElapsed) sngPositionZ = sngPositionZ + (Sin(sngAngleY) * sngWalk / 5 * TV3D.TimeElapsed) + (Sin(sngAngleY + 3.141596 / 2) * sngStrafe / 5 * TV3D.TimeElapsed) ' New : because we are using a landscape with up and down, we ' can't let the camera at the same height. We want the camera to ' follow the height of the map, so we use the "get height". Also, ' because we want to have the effect that we are not a mouse, ' we will add some height to the height returned... sngPositionY = Land.GetHeight(sngPositionX, sngPositionZ) + 10 ' We update the look at position. snglookatX = sngPositionX + Cos(sngAngleY) snglookatY = sngPositionY + Tan(sngAngleX) snglookatZ = sngPositionZ + Sin(sngAngleY)
' With the new values of the camera vectors (position and ' look at), we update the scene's camera. '设置摄像视角 Scene.SetCamera sngPositionX, sngPositionY, sngPositionZ, snglookatX, snglookatY, snglookatZ
End Sub
Private Sub Main_Quit() ' We want to quit the project, so we start by desroyng ' the texture factory. Set TextureFactory = Nothing ' We destroy the land object. Set Land = Nothing ' Don't forget to destroy the inputengine object... Set InputEngine = Nothing ' Then, we destroy the scene object. Set Scene = Nothing ' We finish the frenetic destroy with the TV3D object. Set TV3D = Nothing ' We end the application. End
End Sub
|