; ; ------------------------------------------------------------ ; ; PureBasic - Terrain : Terrain Height change ; ; (c) Fantaisie Software ; ; ------------------------------------------------------------ ; ; Use left button to select an area, then use PageUp or PageDown to change terrain's height ; Use [F5] to init BlendMaps IncludeFile #PB_Compiler_Home + "examples/3d/Screen3DRequester.pb" #CameraSpeed = 1 #TerrainMiniX = 0 #TerrainMiniY = 0 #TerrainMaxiX = 0 #TerrainMaxiY = 0 #NbSommet = 36 Define.f KeyX, KeyY, MouseX, MouseY, TimeSinceLastFrame Define Selected Declare InitBlendMaps() Declare Clamp(*var.float, min.f, max.f) Declare DisplayPolygon(Px.f, Py.f, Pz.f, Rayon.f) Declare DoTerrainModify(tx, ty, wx.f, wy.f, wz.f, mBrushSizeTerrainSpace.f, height.f) ; OpenGL needs to have CG enabled to work (Linux and OS X have OpenGL by default) ; CompilerIf #PB_Compiler_OS <> #PB_OS_Windows Or Subsystem("OpenGL") Flags = #PB_Engine3D_EnableCG CompilerEndIf If InitEngine3D(Flags) InitSprite() InitKeyboard() InitMouse() If Screen3DRequester() Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures/", #PB_3DArchive_FileSystem) Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Textures/nvidia", #PB_3DArchive_FileSystem) Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/GUI", #PB_3DArchive_FileSystem) Add3DArchive(#PB_Compiler_Home + "examples/3d/Data/Packs/desert.zip", #PB_3DArchive_Zip) Parse3DScripts() ;- Light ; light = CreateLight(#PB_Any ,RGB(185, 185, 185), 4000, 1200, 1000, #PB_Light_Directional) SetLightColor(light, #PB_Light_SpecularColor, RGB(255*0.4, 255*0.4,255*0.4)) LightDirection(light ,0.55, -0.3, -0.75) AmbientColor(RGB(5, 5,5)) ;- Camera ; CreateCamera(0, 0, 0, 100, 100) MoveCamera(0, 0, 500, -50, #PB_Absolute) CameraRange(0, 1, 0) ;---------------------------------- ; terrain definition SetupTerrains(LightID(Light), 3000, #PB_Terrain_NormalMapping) ; initialize terrain CreateTerrain(0, 513, 12000, 600, 3, "TerrainHeight", "dat") ; set all texture will be use when terrrain will be constructed AddTerrainTexture(0, 0, 100, "dirt_grayrocky_diffusespecular.jpg", "dirt_grayrocky_normalheight.jpg") AddTerrainTexture(0, 1, 30, "grass_green-01_diffusespecular.jpg", "grass_green-01_normalheight.jpg") AddTerrainTexture(0, 2, 200, "growth_weirdfungus-03_diffusespecular.jpg", "growth_weirdfungus-03_normalheight.jpg") ;- define terrains For ty = #TerrainMiniY To #TerrainMaxiY For tx = #TerrainMiniX To #TerrainMaxiX Imported = DefineTerrainTile(0, tx, ty, "terrain513.png", ty % 2, tx % 2) Next Next BuildTerrain(0) If Imported = #True InitBlendMaps() UpdateTerrain(0) ; If enabled, it will save the terrain as a (big) cache for a faster load next time the program is executed ; SaveTerrain(0, #False) EndIf ; SkyBox ; SkyBox("desert07.jpg") ShowGUI(128, 1) Repeat Screen3DEvents() If ExamineMouse() MouseX = -(MouseDeltaX()/10) MouseY = -(MouseDeltaY()/10) InputEvent3D(MouseX(), MouseY(), MouseButton(#PB_MouseButton_Left), "F", 0) TerrainMousePick(0, CameraID(0), MouseX(), MouseY()) If MouseButton(#PB_MouseButton_Left) ShowGUI(128, 1) DisplayPolygon(PickX(), PickY(), PickZ(), 50) Selected = #True Else ShowGUI(128, 0) MoveCamera (0, KeyX, 0, KeyY) DisplayPolygon(PickX(), PickY(), PickZ(), 0) Selected = #False If CameraY(0) < TerrainHeight(0, CameraX(0), CameraZ(0)) + 10 MoveCamera(0, CameraX(0), TerrainHeight(0, CameraX(0), CameraZ(0)) + 10, CameraZ(0), #PB_Absolute) EndIf RotateCamera(0, MouseY, MouseX, 0, #PB_Relative) EndIf EndIf If ExamineKeyboard() If KeyboardReleased(#PB_Key_F5) InitBlendMaps() EndIf If KeyboardPushed(#PB_Key_Left) KeyX = -#CameraSpeed ElseIf KeyboardPushed(#PB_Key_Right) KeyX = #CameraSpeed Else KeyX = 0 EndIf If KeyboardPushed(#PB_Key_Up) KeyY = -#CameraSpeed ElseIf KeyboardPushed(#PB_Key_Down) KeyY = #CameraSpeed Else KeyY = 0 EndIf Modify = 0 If KeyboardPushed(#PB_Key_PageUp) Modify = 1 ElseIf KeyboardPushed(#PB_Key_PageDown) Modify = -1 EndIf EndIf If Modify And Selected For ty = #TerrainMiniY To #TerrainMaxiY For tx = #TerrainMiniX To #TerrainMaxiX DoTerrainModify(tx, ty, PickX(), PickY(), PickZ(), 0.02, TimeSinceLastFrame * Modify) Next Next UpdateTerrain(0) EndIf TimeSinceLastFrame = RenderWorld() * 0.2 / 1000 FlipBuffers() Until KeyboardPushed(#PB_Key_Escape) End EndIf Else CompilerIf #PB_Compiler_OS <> #PB_OS_Windows Or Subsystem("OpenGL") ; ; Terrain on Linux/OSX and Windows with OpenGL needs CG toolkit from nvidia ; It can be freely downloaded and installed from this site: https://developer.nvidia.com/cg-toolkit-download ; MessageRequester("Error","Can't initialize engine3D (Please ensures than CG Toolkit from nvidia is correcly installed)") CompilerElse MessageRequester("Error","Can't initialize engine3D") CompilerEndIf EndIf Procedure InitBlendMaps() minHeight1.f = 70 fadeDist1.f = 40 minHeight2.f = 70 fadeDist2.f = 15 For ty = #TerrainMiniY To #TerrainMaxiY For tx = #TerrainMiniX To #TerrainMaxiX Size = TerrainTileLayerMapSize(0, tx, ty) For y = 0 To Size-1 For x = 0 To Size-1 Height.f = TerrainTileHeightAtPosition(0, tx, ty, 1, x, y) val.f = (Height - minHeight1) / fadeDist1 Clamp(@val, 0, 1) SetTerrainTileLayerBlend(0, tx, ty, 1, x, y, val) val.f = (Height - minHeight2) / fadeDist2 Clamp(@val, 0, 1) SetTerrainTileLayerBlend(0, tx, ty, 2, x, y, val) Next Next UpdateTerrainTileLayerBlend(0, tx, ty, 1) UpdateTerrainTileLayerBlend(0, tx, ty, 2) Next Next EndProcedure Procedure Clamp(*var.float, min.f, max.f) If *var\f < min *var\f = min ElseIf *var\f > max *var\f = max EndIf EndProcedure Procedure.f Min(a.f, b.f) If a < b ProcedureReturn a Else ProcedureReturn b EndIf EndProcedure Procedure.f Max(a.f, b.f) If a > b ProcedureReturn a Else ProcedureReturn b EndIf EndProcedure Procedure DoTerrainModify(tx, ty, wx.f, wy.f, wz.f, mBrushSizeTerrainSpace.f, TimeElapsed.f) terrainSize.f = TerrainTileSize(0, tx, ty) - 1 Pointx.f = TerrainTilePointX(0, tx, ty, wx, wy, wz) Pointy.f = TerrainTilePointY(0, tx, ty, wx, wy, wz) startx = (Pointx - mBrushSizeTerrainSpace) * terrainSize starty = (Pointy - mBrushSizeTerrainSpace) * terrainSize endx = (Pointx + mBrushSizeTerrainSpace) * terrainSize endy = (Pointy + mBrushSizeTerrainSpace) * terrainSize startx = Max(startx, 0) starty = Max(starty, 0) endx = Min(endx, terrainSize) endy = Min(endy, terrainSize) For y = starty To endy For x = startx To endx tsXdist.f = (x / terrainSize) - Pointx tsYdist.f = (y / terrainSize) - Pointy weight.f = Min(1.0, Sqr(tsYdist * tsYdist + tsXdist * tsXdist) / (0.5 * mBrushSizeTerrainSpace)) weight = 1.0 - (weight * weight) addedHeight.f = weight * 250.0 * TimeElapsed newheight.f = GetTerrainTileHeightAtPoint(0, tx, ty, x, y) + addedHeight SetTerrainTileHeightAtPoint(0, tx, ty, x, y, newheight) Next x Next y EndProcedure Procedure DisplayPolygon(Px.f, Py.f, Pz.f, Rayon.f) Define.l i, Color = RGB(255, 255, 0) Define.f Angle, Sx, Sy, Sz, Sx1, Sy1, Sz1, Py1, Delta = 2 For i = 0 To #NbSommet-2 Sx = Cos(Angle) * Rayon Sz = Sin(Angle) * Rayon Angle + 2.0 * #PI / #NbSommet Sx1 = Cos(Angle) * Rayon Sz1 = Sin(Angle) * Rayon Py = TerrainHeight(0, Px + Sx, Pz + Sz) + Delta Py1 = TerrainHeight(0, Px + Sx1, Pz + Sz1) + Delta CreateLine3D(i, Px + Sx, Py, Pz + Sz, Color, Px + Sx1, Py1, Pz + Sz1, Color) Next i Py = TerrainHeight(0, Px + Cos(0) * Rayon, Pz + Sin(0) * Rayon) + Delta CreateLine3D(i, Px + Sx1, Py1, Pz + Sz1, Color, Px + Cos(0) * Rayon, Py, Pz + Sin(0) * Rayon, Color) EndProcedure