' 在地形中包括地面天空水云彩________________________________________________________________________ ' TrueVision3D (web: http://www.truevision3d.com) ' ???????????????????????????????????? ' Tutorial 8 : A complete landscape. ' ????? ' Description : In this 8th tutorial, we take the last tutorial but ' ?????? we add everything we can to make this world the most ' impressive we can with effects like : water, clouds, ' a sun with lens flare and some underwater fog.
' Force explicit declarations Option Explicit
' We declare TrueVision3D. Private TV3D As TVEngine
' We declare the landscape Private Land As TVLandscape
' New : 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
' New : to enable fog in our project, we have to use the TVAtmosphere object like ' the sky. The TVGraphicEffect class let us to make some interesting screen 'effects like fade in and fade out. Private Atmos As TVAtmosphere Private GraphicFX As TVGraphicEffect
' We the declare the scene Private Scene As TVScene
' We declare the input engine. Private InputEngine As TVInputEngine
' 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
' We put the debug file in the app directory TV3D.SetDebugFile App.Path + "\debug.txt" 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 class Set Atmos = New TVAtmosphere
' We create the texture factory Set TextureFactory = New TVTextureFactory
' We load the sky textures into the tex factory.. 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. 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 ' SetFactorY must be applied BEFORE generating the terrain ' If you want to change dynamically the scaling of terrain afterwars ' use Land.SetTerrainScale method. ' Generate the height of the land from the grayscale of the image. Land.GenerateHugeTerrain "..\..\..\Media\heightmap.jpg", TV_PRECISION_LOW, 8, 8, -700, -1024, True
' Then, we load the land texture. TextureFactory.LoadTexture "..\..\..\Media\dirtandgrass.jpg", "LandTexture" ' We assign a texture to that land. Land.SetTexture GetTex("LandTexture") Land.SetTextureScale 3, 3 ' New : the sun. We have to place the sun in the world. Just like the ' sky box, the sun is attached to the camera position vector. You will ' never notice it until you start playing really badly with the ' properties of the sun. Let's start by loading a texture for it. TextureFactory.LoadTexture "..\..\..\Media\sun.jpg", "Sun" ' Then, initialize it by placing it via a vector ' using the atmosphere sun feature '设置大气中太阳的材质 Atmos.Sun_SetTexture GetTex("Sun") '设置太阳大小 Atmos.Sun_SetBillboardSize 1 ' this is the relative position of the sun from the player camera. '设置太阳位置 Atmos.Sun_SetPosition -1000, 570, 0 Atmos.Sun_Enable True ' New : To add extra visual effects, we add a lens flare effect. For ' this, we have to load some cirles that will be used to simulate ' the flare effect. TextureFactory.LoadTexture "..\..\..\Media\flare1.jpg", "Flare1" TextureFactory.LoadTexture "..\..\..\Media\flare2.jpg", "Flare2" TextureFactory.LoadTexture "..\..\..\Media\flare3.jpg", "Flare3" TextureFactory.LoadTexture "..\..\..\Media\flare4.jpg", "Flare4" ' Initialize the lens flares. '初始化光晕 Atmos.LensFlare_SetLensNumber 4 Atmos.LensFlare_Enable True Atmos.LensFlare_SetLensParams 1, GetTex("Flare1"), 2 * 5, 40, RGBA(1, 1, 1, 0.5), RGBA(1, 1, 1, 0.5) Atmos.LensFlare_SetLensParams 2, GetTex("Flare2"), 2 * 1, 18, RGBA(1, 1, 1, 0.5), RGBA(1, 1, 1, 0.5) Atmos.LensFlare_SetLensParams 3, GetTex("Flare3"), 2 * 1.8, 15, RGBA(1, 1, 1, 0.5), RGBA(0.7, 1, 1, 0.5) Atmos.LensFlare_SetLensParams 4, GetTex("Flare4"), 2 * 1, 6, RGBA(1, 0.1, 0, 0.5), RGBA(0.5, 1, 1, 0.5)
' New : also for fun, we add animated water. We start by loading the ' water teture... '在材质库中加载水的材质 TextureFactory.LoadTexture "..\..\..\Media\water.bmp", "Water" ' Then, we set everything we can for this water. ' This for example, setup a transparent water (50%) '陆地中水的材质的水的效果 Land.SetWaterTexture GetTex("Water") Land.SetWaterEffect True, 0.5, True, D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA, False, 0 Land.SetWaterTextureScale 32 ' We set the water height via a variable. We need this variable ' to be able to add an extra underwater fog effect later, at the ' rendering. sngWaterHeight = 100 Land.SetWaterAltitude sngWaterHeight ' And we finish by enabling the water. Land.SetWaterEnable True ' New : for fun, we will also add some clouds, just over the water ' to give a creepy fog effect. Let's start by loading the clouds textures. '加载云的材质 TextureFactory.LoadTexture "..\..\..\Media\clouds.dds", "Clouds", , , TV_COLORKEY_BLACK
' Then, set the land's clouds. ' Land.SetCloudTexture GetTex("Clouds") '初始化云彩 Land.InitClouds GetTex("Clouds"), TV_CLOUD_MOVE, 500, 1, 1, 2, 2, 1024 '设置云的速度 Land.SetCloudVelocity 1, 0.01, 0.01
' We set the camera vectors (position and look at) and angles. sngPositionX = 0 sngPositionY = 20 sngPositionZ = 0 snglookatX = 0 snglookatY = 20 snglookatZ = 50 sngAngleX = 0 sngAngleY = 0 ' We set the initial values of movement sngWalk = 0 sngStrafe = 0 ' We pop the form over everything else. Form1.Show 'Set the viewing distance Scene.SetViewFrustum 90, 4000 ' 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 : if we are below the waterheight, this means the we are ' underwater. To give a cool underwater effect, we will add fog. ' If we are over the ground, then don't add the fog but render ' the lens flare. '如果y坐标小于水的高度时 If sngPositionY < sngWaterHeight Then ' Render a blue fog to simulate under water. '给大气中设置蓝色的雾效果 Atmos.Fog_Enable True Atmos.Fog_SetColor 0, 0.4, 0.5, 1 Atmos.Fog_SetParameters 0, 0, 0.01 Atmos.Fog_SetType TV_FOG_EXP, TV_FOGTYPE_RANGE Atmos.LensFlare_Enable False Else ' ' New : we have to render the lens flare. Atmos.LensFlare_Enable True Atmos.Fog_Enable False End If
' New have to render the sky, the sun and lens flares Atmos.Atmosphere_Render
' New : we have to render the landscape. Land.Render True, True 'Land.RenderWater ' 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 graphic effects object Set GraphicFX = 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
|