Code archives/3D Graphics - Mesh/minib3d - converted terrain functions
This code has been declared by its author to be Public Domain code.
Download source code
| I'm not exactly sure what it does, because the desciption was in Russian, but it uses something called roam to optimize terrain generation from an heightmap. You'll need to supply a (!) 512x512 (!) file called 'heightmap.bmp'. For other image sizes, change MinimumTileSize. And you'll need minib3d installed. |
'terrain
Import sidesign.minib3d
Graphics3D 640,480,0,2
Global RoamMaxHeightError#=3.0
Global MinimumTileSize=64
light=CreateLight()
RoamTerrainMaxHeight#=40.96
HmapImage:TPixmap=LoadPixmap("heightmap4.bmp")
Global RoamTerrainWidth=PixmapWidth(HmapImage)-1
Global RoamTerrainHeight#[RoamTerrainWidth+1+1,RoamTerrainWidth+1+1]
For PixX=0 To RoamTerrainWidth
For PixY=0 To RoamTerrainWidth
Pixel=ReadPixel(HmapImage,PixX,PixY)
RedColor=Pixel & $FF
RoamTerrainHeight#(PixX,PixY)=((RedColor/255.0))*RoamTerrainMaxHeight
Next
Next
RoamMaxTriangles=RoamTerrainWidth*RoamTerrainWidth*2-1
Global RoamBaseNeighbor%[RoamMaxTriangles*10+1]
Global RoamBaseNeighborFlag%[RoamMaxTriangles*10+1]
'---
Function FindTriBaseNeighbor(Number)
If RoamBaseNeighbor(number)>0
Return
EndIf
If Number<4
Select Number
Case 1
RoamBaseNeighbor(Number)=1
RoamBaseNeighborFlag(Number)=1 '????? ? ?????? ?????????
Case 2
RoamBaseNeighbor(Number)=0 '??? ??????
RoamBaseNeighborFlag(Number)=0
Case 3
RoamBaseNeighbor(Number)=0 '??? ??????
RoamBaseNeighborFlag(Number)=0
End Select
Return
EndIf
Parent=Number Shr 1
ParentLeftChild=(Parent Shl 1)
ParentRightChild=(Parent Shl 1)+1
PraParent=Parent Shr 1
PraParentLeftChild=(PraParent Shl 1)
PraParentRightChild=(PraParent Shl 1)+1
If Number=ParentLeftChild And Parent=PraParentLeftChild
'??????? ??????? ??????? ??????? ??????? ???????????,
PraParentRightChildRightChild=(PraParentRightChild Shl 1)+1
'??????? ???????? ??????? ????????? ???????? ????????????
RoamBaseNeighbor(Number)=PraParentRightChildRightChild
RoamBaseNeighborFlag(Number)=0
'??????? ?????????? ???????? ????? ??????? ?????????
'??????? ??????? ??????? ??????? ???????????
RoamBaseNeighbor(PraParentRightChildRightChild)=Number
RoamBaseNeighborFlag(PraParentRightChildRightChild)=0
Return
EndIf
'??? ?? ?????? No3 , ?? ? ???????? ???????
If Number=ParentRightChild And Parent=PraParentRightChild
'??????? ?????? ??????? ?????? ??????? ???????????,
PraParentLeftChildLeftChild=(PraParentLeftChild Shl 1)
'??????? ???????? ??????? ????????? ???????? ????????????
RoamBaseNeighbor(Number)=PraParentLeftChildLeftChild
RoamBaseNeighborFlag(Number)=0
'??????? ?????????? ???????? ????? ??????? ?????????
'?????? ??????? ?????? ??????? ???????????
RoamBaseNeighbor(PraParentLeftChildLeftChild)=Number
RoamBaseNeighborFlag(PraParentLeftChildLeftChild)=0
Return
EndIf
'?????? ????????? ???? ?? ? ??????????? ????? ?????????
PraParentBaseNeighbor=RoamBaseNeighbor(PraParent)
PraParentBaseNeighborFlag=RoamBaseNeighborFlag(PraParent)
'???? ???, ?? ? ? ???????? ???? ?? ?????
If PraParentBaseNeighbor=0
RoamBaseNeighbor(Number)=0
RoamBaseNeighborFlag(Number)=0
Return
EndIf
'???????? ?????? No4
'???? ??????? ??????????? ????? ???????, ? ???????? - ?????
If Number=ParentRightChild And Parent=PraParentLeftChild
'??????? ????? ????? ??????? ??????? ??????? ?????? ????????? ???????????
PraParentBaseNeighborRightChild=(PraParentBaseNeighbor Shl 1)+1
PraParentBaseNeighborRightChildLeftChild=(PraParentBaseNeighborRightChild Shl 1)
'??????? ? ?????? ? ???????? ???? ?? ????? ???????????
RoamBaseNeighbor(Number)=PraParentBaseNeighborRightChildLeftChild
RoamBaseNeighborFlag(Number)=PraParentBaseNeighborFlag
' ? ????????
RoamBaseNeighbor(PraParentBaseNeighborRightChildLeftChild)=Number
RoamBaseNeighborFlag(PraParentBaseNeighborRightChildLeftChild)=PraParentBaseNeighborFlag
Return
EndIf
'?????? ???????? ????????? ?????? No4 ????????
'????? ??????? ??????????? ????? ???????, ? ???????? - ??????
If Number=ParentLeftChild And Parent=PraParentRightChild
'??????? ????? ????? ??????? ??????? ??????? ?????? ????????? ???????????
PraParentBaseNeighborLeftChild=(PraParentBaseNeighbor Shl 1)
PraParentBaseNeighborLeftChildRightChild=(PraParentBaseNeighborLeftChild Shl 1)+1
'??????? ? ?????? ? ???????? ???? ?? ????? ???????????
RoamBaseNeighbor(Number)=PraParentBaseNeighborLeftChildRightChild
RoamBaseNeighborFlag(Number)=PraParentBaseNeighborFlag
' ? ????????
RoamBaseNeighbor(PraParentBaseNeighborLeftChildRightChild)=Number
RoamBaseNeighborFlag(PraParentBaseNeighborLeftChildRightChild)=PraParentBaseNeighborFlag
EndIf
End Function
'??????????????? ??????? ???? ????????????? ? ????? ?? ??????? ?????????
For CurrentNumber=1 To RoamMaxTriangles
FindTriBaseNeighbor(CurrentNumber)
Next
'??? ??????????? ????? ????? ????? ?? ????? ????????
Global RoamCriticalTriLevel=RoamTerrainWidth*RoamTerrainWidth-1
'??????? ????? ?????? ??? ???????? ?????????? ?????? ?????????????
Global RoamTriangle[1+1]
RoamTriangle(0)=CreateBank(RoamTerrainWidth*RoamTerrainWidth*2) '????? 0 - ?????? ??????? ???????????
RoamTriangle(1)=CreateBank(RoamTerrainWidth*RoamTerrainWidth*2) '????? 1 - ????? ?????? ???????????
'??????????? ???????????
Global MinTileSizeLevel=2^(RoamTerrainWidth/MinimumTileSize)
' ???????, ???????????? ????? ?? ???? ??????????? ??? ???
Function RoamBreakTriangle(x0,z0,x1,z1,x2,z2,Number,Branch)
'???? ??????????? ?????? ? ????? ???????? ????????????????
If Number>RoamCriticalTriLevel
'???????? ??? ?? ????? ? ???????
PokeByte(RoamTriangle(Branch),Number,0)
Return
EndIf
'???? ??????????? ?????? ? ????? ????????????? ?????????? ???????????
If Number<MinTileSizeLevel
'??????? ?????????? ??????????? ?????
xC=(x0+x2)/2
zC=(z0+z2)/2
'??????? ????????
LeftChild=(Number Shl 1)
RightChild=(Number Shl 1)+1
'???????? ??????????? ??? ????????
PokeByte(RoamTriangle(Branch),Number,1)
'???????? ??????? ?????????? ??? ????????
RoamBreakTriangle(x1,z1,xC,zC,x0,z0,LeftChild,Branch)
RoamBreakTriangle(x2,z2,xC,zC,x1,z1,RightChild,Branch)
'???????, ????? ?? ?????? ?????? ?????????
Return
EndIf
'???? ??????????? ??? ??????? ??? ??????? (? ???????? ForceSplit)
'?? ???? ????????? ??? ????????
If PeekByte(RoamTriangle(Branch),Number)=1
xC=(x0+x2)/2
zC=(z0+z2)/2
LeftChild=(Number Shl 1)
RightChild=(Number Shl 1)+1
RoamBreakTriangle(x1,z1,xC,zC,x0,z0,LeftChild,Branch)
RoamBreakTriangle(x2,z2,xC,zC,x1,z1,RightChild,Branch)
Return
EndIf
'????? ?????????? ???????? ???????? ???? ??????????? ????????? ???
'?? ????????? ??????????? - ??? ???????? ??????????? ??????
xC=(x0+x2)/2
zC=(z0+z2)/2
'??????????? ??????
DeltaHeight#=Abs(RoamTerrainHeight(xC,zC)-(RoamTerrainHeight(x0,z0)+RoamTerrainHeight(x2,z2))*0.5)
'???? ??? ?????? ???????????? ?????? ?? ?????????
If DeltaHeight>=RoamMaxHeightError
' - " -"
xC=(x0+x2)/2
zC=(z0+z2)/2
LeftChild=(Number Shl 1)
RightChild=(Number Shl 1)+1
PokeByte(RoamTriangle(Branch),Number,1)
RoamBreakTriangle(x1,z1,xC,zC,x0,z0,LeftChild,Branch)
RoamBreakTriangle(x2,z2,xC,zC,x1,z1,RightChild,Branch)
' ???? ? ???????????? ???? ????? ????????? ?? ?????????
' ??? ??????????? ???????? (?? ????)
If RoamBaseNeighbor(Number)>0
'???????? ???????? ??? ????????????? ????? ????????? ????? ????? Xor
RoamForceSplitTri(RoamBaseNeighbor(Number),Branch ~ RoamBaseNeighborFlag(Number))
EndIf
EndIf
End Function
'???????, ??????????? ?????? ????????? ????????????
Function RoamForceSplitTri(Number,Branch)
'???? ??????????? ??? ?????? ?? ???????
If PeekByte(RoamTriangle(Branch),Number)=1
Return
EndIf
'???????? ??? ????????
PokeByte(RoamTriangle(Branch),Number,1)
'??????? ??????? ??? ?????? ?????????
If RoamBaseNeighbor(Number)>0
RoamForceSplitTri(RoamBaseNeighbor(Number),Branch ~ RoamBaseNeighborFlag(Number))
EndIf
'? ????????? ? ????????
Parent=Number Shr 1
RoamForceSplitTri(Parent,Branch)
End Function
'??????? ???
Global Terrain=CreateMesh()
'???????? ??? ? ????? ????
PositionEntity Terrain,-0.5*RoamTerrainWidth,0,-0.5*RoamTerrainWidth
'????? ???????? ? ?????????
tex=LoadTexture("sand.jpg")
ScaleTexture tex,14,14
'EntityTexture Terrain,tex
'??????? ??????? ? ?????? ?????????
Global RoamSurface=CreateSurface(Terrain)
Global RoamVertex[RoamTerrainWidth+1,RoamTerrainWidth+1]
'??????? ????????? ??????????? ?? ????? ??????
Function RoamCreateTriangle(x0,z0,x1,z1,x2,z2,Number,Branch)
'???? ??????????? ??????, ?? ???????? ? ??? ????????
If PeekByte(RoamTriangle(Branch),Number)=1
xC=(x0+x2)/2
zC=(z0+z2)/2
LeftChild=(Number Shl 1)
RightChild=(Number Shl 1)+1
RoamCreateTriangle(x1,z1,xC,zC,x0,z0,LeftChild,Branch)
RoamCreateTriangle(x2,z2,xC,zC,x1,z1,RightChild,Branch)
Return
Else
'??? ??????? ??????????
'????????? ?????? ?? ??????? 0
If RoamVertex(x0,z0)=0
RoamVertex(x0,z0)=AddVertex(RoamSurface,x0,RoamTerrainHeight(x0,z0),z0,x0,z0)
EndIf
'????????? ?????? ?? ??????? 1
If RoamVertex(x1,z1)=0
RoamVertex(x1,z1)=AddVertex(RoamSurface,x1,RoamTerrainHeight(x1,z1),z1,x1,z1)
EndIf
'????????? ?????? ?? ??????? 2
If RoamVertex(x2,z2)=0
RoamVertex(x2,z2)=AddVertex(RoamSurface,x2,RoamTerrainHeight(x2,z2),z2,x2,z2)
EndIf
'???????
AddTriangle (RoamSurface,RoamVertex(x0,z0),RoamVertex(x1,z1),RoamVertex(x2,z2))
EndIf
End Function
Function CreateLand()
'??????? ????? ?????? ????? ?????? ?????????????
'FreeBank RoamTriangle(0)
'FreeBank RoamTriangle(1)
'? ??????? ?????? ??????
RoamTriangle(0)=CreateBank(RoamTerrainWidth*RoamTerrainWidth*2)
RoamTriangle(1)=CreateBank(RoamTerrainWidth*RoamTerrainWidth*2)
'??????????? ?????? ?????????
Global RoamVertex[RoamTerrainWidth+1,RoamTerrainWidth+1]
'??????? ??????? ? ??????? ??????? 0
ClearSurface RoamSurface,1,1
AddVertex RoamSurface,0,0,0
'????????? ????????????
RoamBreakTriangle(0,RoamTerrainWidth,RoamTerrainWidth,RoamTerrainWidth,RoamTerrainWidth,0,1,0)
RoamBreakTriangle(RoamTerrainWidth,0,0,0,0,RoamTerrainWidth,1,1)
'??????? ????????????
RoamCreateTriangle(0,RoamTerrainWidth,RoamTerrainWidth,RoamTerrainWidth,RoamTerrainWidth,0,1,0)
RoamCreateTriangle(RoamTerrainWidth,0,0,0,0,RoamTerrainWidth,1,1)
'????????? ???????
UpdateNormals(Terrain)
ScaleEntity Terrain, 10, 4, 10
PositionEntity Terrain, 0, 0, 0
End Function
CreateLand()
ScaleMesh terrain, 1, 5, 1
tex2 = LoadTexture("heightmap.bmp")
ScaleTexture tex2, 512, 512
EntityTexture terrain, tex2
EntityType terrain, 2
'CreateOctree(terrain, 200, 5)
cam = CreateCamera()
CameraRange cam, 1, 10000
EntityType cam, 1
EntityRadius cam, 2.0
PositionEntity cam, 0, 150, 0
'used by fps
Local old_ms:Int = MilliSecs()
Local renders:Int
Local fps:Int
'setup collisions
Collisions 1, 2, 2
Repeat
Wireframe KeyDown(KEY_W)
If KeyDown(KEY_LEFT) Then MoveEntity cam, -1, 0, 0
If KeyDown(KEY_RIGHT) Then MoveEntity cam, +1, 0, 0
If KeyDown(KEY_DOWN) Then MoveEntity cam, 0, 0, -1
If KeyDown(KEY_UP) Then MoveEntity cam, 0, 0, +1
If KeyDown(KEY_A) Then MoveEntity cam, 0, +1, 0
If KeyDown(KEY_Z) Then MoveEntity cam, 0, -1, 0
UpdateWorld
RenderWorld
renders :+ 1
If MilliSecs() -old_ms >= 1000
old_ms = MilliSecs()
fps = renders
renders = 0
EndIf
Text 0, 20, "FPS: " + String(fps)
Flip 0
Until KeyHit(KEY_ESCAPE)
End |