Hi guys, As you may know, I try to implement a Terrain Rendering class to Minib3D, and after some problem I had have with quadtree terrains I have found a java source for simple roaming. Now I have converted this code to BMax to go with Minib3D. But there are several problems I don't know where they come from:
First the original source is located here: http://homepage.mac.com/jhuwaldt/java/3DStuff/ROAMApp/ROAMApp.html
this is how i converted it to BMax:
As a Heightfile every image which is power of 2 will work.
No my problem:
As you will see, the test app will wirst start a 2d mode, which I have used to check if the triangles are draw right. That's because in the 3d context there appear no triangle also if they where rendered. The next problem is, that there seems to be no update, so the triangles are not really splitted and the triangles are always th same.
Maybe someone with greater experience in Java could take a look to this both sources and maybe he finds out what i was (i lack of java experience) converting wrong.
thx klepto2
First the original source is located here: http://homepage.mac.com/jhuwaldt/java/3DStuff/ROAMApp/ROAMApp.html
this is how i converted it to BMax:
SuperStrict Import "minib3d.bmx" Global Splitted:Int = 0 Type TTerrain Field gMapXSize:Int Field gMApYSize:Int Field gMapDiagSize:Int Field gGridSpace:Float = 4 Field gNumPatchesperXSide:Int Field gNumPatchesperYSide:Int Field gPatchSize:Int Field RecurseDepth:Int = 8 Field gHeightmap:THeightmap Field minAlt:Int Field maxalt:Int Field colorfactor:Float Field gPatches:TPatch[,] Field gNextTriNode:Int = 0 Field POOL_SIZE:Int = 25001 Field gTriPool:TTriTreeNode[] Field gNumTrisRendered:Int = 0 Field gDesiredTris:Int = 5000 Field gFrameVariance:Int = 2 Field ViewPosition:Float[3] Field Mesh:TMesh Field Surface:TSurface Function Create:TTerrain(Url:Object , PatchSize:Int , gridSpacing:Float) 'ToDo Loading Routine einbauen ' ' ' Local T:TTerrain = New TTerrain T.gHeightmap = THeightmap.Load(Url) Local Height:Int = T.gHeightmap.GetHeight() Local Width:Int = T.gHeightmap.GetWidth() If Width Mod Patchsize <> 0 Then Throw "Heightmap width must be (patchsize*n + 1)." If Height Mod Patchsize <> 0 Then Throw "Heightmap height must be (patchsize*n + 1)." T.gMapXSize = Width T.gMapYSize = Height T.gMapDiagSize = Int(Sqr(Width * Width + Height * Height) ) T.gNumPatchesperXSide = Width / patchsize T.gNumPatchesperYSide = Height / Patchsize T.gPatchsize = patchsize T.gPatches = New TPatch[T.gNumPatchesperXSide , T.GnumPatchesperYSide] T.RecurseDepth = 1 Shl (2 * T.Log2(Patchsize) - 1) Print T.RecurseDepth T.gTriPool = T.genTriTreeNodePool(T.Pool_Size) T.MinALt = T.gHeightmap.minAlt T.maxAlt = T.gHeightmap.MaxAlt T.gGridSpace = gridspacing T.ViewPosition[0] = 0 T.ViewPosition[1] = 0 T.ViewPosition[2] = 0 T.Mesh = CreateMesh() T.Surface = CreateSurface(T.Mesh) T.Init() T.MarkChanged(0,T.gMapySize-1,T.gmapxsize-1,0) Return T End Function Method getLOD:Int() Return gDesiredTris End Method Method setLOD:Int(LOD:Int) If Lod < 4000 Then Lod = 4000 gDesiredtris = LOD End Method Method TrisRendered:Int() Return gNumTrisRendered End Method Method getFrameVariance:Int() Return gFrameVariance End Method Method markchanged(_Top:Int , _Left:Int , _Bottom:Int , _Right:Int) For Local Y:Int = 0 To gNumPatchesPerYSide - 1 For Local X:Int = 0 To gNumPatchesPerXSide - 1 Local P:TPatch = gPatches[Y , X] Local ptop:Int = P.getOffsetX() Local pLeft:Int = P.GetOffSetY() Local pbottom:Int = pTop + gPatchsize Local pRight:Int = pLeft + gPatchsize If (Pleft < _Right And pright > _left ) And (ptop < _bottom And pbottom > _top) Then Print "dirty" p.MarkDirty() End If Next Next End Method Method Init() For Local Y:Int = 0 To gNumPatchesPerYSide - 1 For Local X:Int = 0 To gNumPatchesPerXSide - 1 Local P:TPatch = TPatch.Create(x * gPatchSize , Y * gPatchSize,Self) P.ComputeVariance() gPatches[Y , X] = P Next Next End Method Method Update(ViewPosition:Float[])'Cam:TEntity) 'Surface.ClearSurface() Self.ViewPosition = ViewPosition 'ViewPosition[0] = EntityX(Cam) 'ViewPosition[1] = entityY(Cam) 'ViewPosition[2] = EntityZ(Cam) 'TODO: Culling Functions gNextTriNode = 0 gNumTrisRendered = 0 For Local Y:Int = 0 To gNumPatchesPerYSide - 1 For Local X:Int = 0 To gNumPatchesPerXSide - 1 Local P:TPatch = gPatches[Y , X] P.Reset() 'P.SetVisibility() If P.isDirty() = True Then P.ComputeVariance() If P.GetVisible() = True Then If X > 0 Then P.GetBaseLeft().LeftNeighbor = gPatches[Y , X - 1].GetBaseRight() Else P.getBaseLeft().LeftNeighbor = Null EndIf If X < gnumPatchesPerXSide-1 Then P.GetBaseRight().LeftNeighbor = gPatches[Y , X + 1].GetBaseLeft() Else P.getBaseRight().LeftNeighbor = Null EndIf If Y > 0 Then P.GetBaseLeft().RightNeighbor = gPatches[Y -1, X ].GetBaseRight() Else P.getBaseLeft().RightNeighbor = Null EndIf If Y < gNumPatchesperYSide-1 Then P.GetBaseRight().RightNeighbor = gPatches[Y+1 , X].GetBaseLeft() Else P.getBaseRight().RightNeighbor = Null EndIf EndIf Next Next Tessellate(ViewPosition) End Method Method Tessellate(ViewPosition:Float[]) Local viewPosX:Int = (viewPosition[0] / gGridSpace) Local viewPosY:Int = (viewPosition[2] / gGridSpace) For Local i:Int = 0 To gNumPatchesPerYSide -1 For Local j:Int = 0 To gNumPatchesPerXSide -1 Local P:TPatch = gPatches[i , j] If P.GetVisible() = True Then P.Tessellate(viewposX , viewposY) Next Next End Method Method Render() For Local P:TPatch = EachIn gPatches If P.GetVisible() = True Then P.Render() Next If Abs(gNumTrisRendered - gDesiredTris) > 250 Then gFrameVariance:+ (gNumTrisRendered - gDesiredTris) * 10 / Float(gDesiredTris) EndIf If gFrameVariance < 0 Then gFrameVariance = 0 EndIf End Method Method allocateTriNode:TTriTreeNode() Local pTri:TTriTreeNode = Null If gNextTriNode < POOL_SIZE pTri = gTriPool[gNextTriNode] gNextTriNode:+ 1 pTri.LeftChild = Null pTri.RightChild = Null EndIf Return pTri End Method Method genTriTreeNodePool:TTriTreeNode[](Size:Int) Local pool:TTriTreeNode[] = New TTriTreeNode[Size] For Local I:Int = 0 To Size-1 Pool[i] = New TTriTreeNode Next Return Pool End Method Method log2:Int(number:Int) 'Print Int(Log(Number) / Log(2) ) Return Int(Log(Number) / Log(2) ) End Method End Type Type TTriTreeNode Field LeftChild:TTriTreeNode Field RightChild:TTriTreeNode Field BaseNeighbor:TTriTreeNode Field LeftNeighbor:TTriTreeNode Field RightNeighbor:TTriTreeNode End Type Type TPatch Field offsetx:Int Field offsety:Int Field Variance_Depth:Int Field varianceLeft:Int[] Field varianceRight:Int[] Field currentVariance:Int[] Field ViewPosX:Int Field ViewPosY:Int Field varianceDirty:Int Field isVisible:Int Field baseLeft:TTriTreeNode = New TTriTreeNode Field baseRight:TTriTreeNode = New TTriTreeNode Field Terrain:TTerrain Function Create:TPatch(heightX:Int , HeightY:Int, T:TTerrain) Local P:TPatch = New TPatch 'P.Reset() P.baseLeft.RightNeighbor = Null P.baseLeft.LeftNeighbor = Null P.baseRight.RightNeighbor = Null P.baseRight.LeftNeighbor = Null P.baseLeft.LeftChild = Null P.baseLeft.RightChild = Null P.baseRight.LeftChild = Null P.baseLeft.LeftChild = Null P.BaseLeft.BaseNeighbor = P.BaseRight P.BaseRight.BaseNeighbor = P.BaseLeft P.offsetX = heightX P.offsetY = heightY P.Variance_Depth = Sqr(T.gPatchSize) + 1 P.VarianceLeft = New Int[1 Shl P.Variance_Depth] P.VarianceRight = New Int[1 Shl P.Variance_Depth] 'Print P.VarianceLeft.Length P.varianceDirty = True P.isVisible = True P.Terrain = T Return P End Function Method reset() isvisible = True 'Variancedirty = True baseleft.LeftChild = Null baseleft.RightChild = Null baseright.LeftChild = Null Baseright.RightChild = Null BaseLeft.BaseNeighbor = BaseRight BaseRight.BaseNeighbor = BaseLeft baseLeft.RightNeighbor = Null baseLeft.LeftNeighbor = Null baseRight.Rightneighbor = Null BaseRight.LeftNeighbor = Null End Method Method ComputeVariance() Local offYpPSize:Int = offsetY + Terrain.gPatchsize Local offXpPSize:Int = offsetX + Terrain.gPatchSize Local leftZ:Int = Terrain.gHeightmap.get(offsetX , OffYpPSize) Local rightZ:Int = Terrain.gHeightmap.get(offXpPSize , offsetY) Local apexZ:Int = Terrain.gHeightmap.get(offsetX , offsetY) currentvariance = varianceLeft recursComputeVariance(0 , Terrain.gPatchSize , leftZ , Terrain.gPatchSize , 0 , rightZ , 0 , 0 , apexZ , 1) rightZ = apexZ apexZ = leftZ leftZ = RightZ apexZ = Terrain.gHeightmap.get(OffxpPSize , OffYppSize) currentvariance = varianceRight recursComputeVariance(Terrain.gPatchsize , 0 , leftZ , 0 , Terrain.gPatchsize , rightZ , Terrain.gPatchsize , Terrain.gPatchsize , apexZ , 1) variancedirty = False End Method Method recursComputeVariance:Int(leftX:Int , LeftY:Int , LeftZ:Int , rightX:Int , RightY:Int , RightZ:Int , apexX:Int , apexY:Int , apexZ:Int, Node:Int) Local CenterX:Int = (LeftX + RightX) Shr 1 Local CenterY:Int = (leftY + RightY) Shr 1 Local CenterZ:Int = Terrain.gHeightmap.get(offsetx + centery , offsety + centery) Local myVariance:Int = Abs(centerZ - ( (leftZ + rightZ) Shr 1) ) If Abs(leftx - rightx) >= 8 Or Abs(leftY - Righty) >= 8 Then myVariance = Max(myVariance , recursComputeVariance(apexX , apexY , apexZ , leftX , leftY , LeftZ , centerX , centerY , centerZ , node Shl 1) ) ' Print myVariance myVariance = Max(myVariance , recursComputeVariance(rightX , righty , rightZ , apexX , apexY , apexZ , CenterX,CenterY , CenterZ , 1 + (node Shl 1) ) ) EndIf If node < (1 Shl Variance_Depth) = True currentVariance[node] = (1 + myVariance) '* 1024 * 2 End If Return MyVariance End Method Method tessellate(viewposX:Int , ViewPosY:Int) Self.ViewPosX = ViewPosX Self.ViewPosY = ViewPosY CurrentVariance = varianceLeft Local pSize:Int = Terrain.gPatchsize Local oXpPSize:Int = offsetX + pSize Local oYpPSize:Int = offsetY + pSize recursTessellate(baseleft , offsetX , oypPsize , oXpPSize , offsetY , offsetX , offsetY , 1) currentVariance = varianceRight recursTessellate(baseRight , oxppsize , offsety , offsetx , oyppsize , oxppsize , oyppsize , 1) End Method Method recursTessellate(tri:TTriTreeNode,leftX:Int,leftY:Int,rightX:Int,rightY:Int,apexX:Int,apexY:Int,node:Int ) Local triVariance:Int=0; Local centerX:Int = (leftX + rightX) Shr 1'; // Compute X coordinate of center of Hypotenuse Local centerY:Int = (leftY + rightY) Shr 1'; // Compute Y coord... If ( node < (1 Shl VARIANCE_DEPTH) ) Then '// Calculate approximate distance from view position To center of triangle. Local dx:Int = centerX - viewPosX Local dy:Int = centerY - viewPosY Local distance:Int = 1 + distanceApprox( dx , dy ) Print distance '// Egads! A division? What's this world coming to! '// This should be replaced with a faster operation. '// Take both distance And variance into consideration triVariance = currentVariance[node]/distance EndIf '// If we do Not have variance info For this node, Then we must have gotten '// here by splitting, so Continue down To the lowest level. '// Or If we are Not below the variance tree, test For variance. If ( (node >= (1 Shl VARIANCE_DEPTH)) Or (triVariance > Terrain.gFrameVariance)) Then '// Split this triangle. split(tri) '// If this triangle was split, Try To split it's children as well. '// Tessellate all the way down To one vertex per height Field entry If ( tri.LeftChild <> Null And node < Terrain.recurseDepth) Then recursTessellate( tri.LeftChild, apexX, apexY, leftX, leftY,centerX, centerY, node Shl 1 ) recursTessellate( tri.RightChild, rightX, rightY, apexX, apexY,centerX, centerY, 1+(node Shl 1) ) EndIf EndIf End Method Method Split(Tri:TTriTreeNode) 'DebugStop() If Tri.LeftChild <> Null Then Return Splitted:+1 If tri.BaseNeighbor <> Null And tri.BaseNeighbor.BaseNeighbor <> tri Then split(tri.baseNeighbor) tri.LeftChild = Terrain.allocateTriNode() tri.RightChild = Terrain.allocateTriNode() EndIf If tri.LeftChild = Null Or tri.RightChild = Null Then tri.Leftchild = Null tri.RightChild = Null Return EndIf tri.LeftChild.BaseNeighbor = tri.LeftNeighbor tri.LeftChild.LeftNeighbor = tri.RightChild tri.RightChild.BaseNeighbor = tri.RightNeighbor tri.RightChild.RightNeighbor = tri.LeftChild If (tri.LeftNeighbor <> Null) Then If (tri.LeftNeighbor.BaseNeighbor = tri) tri.LeftNeighbor.BaseNeighbor = tri.LeftChild Else If (tri.LeftNeighbor.LeftNeighbor = tri) tri.LeftNeighbor.LeftNeighbor = tri.LeftChild Else If (tri.LeftNeighbor.RightNeighbor = tri) tri.LeftNeighbor.RightNeighbor = tri.LeftChild EndIf EndIf If (tri.RightNeighbor <> Null) If (tri.RightNeighbor.BaseNeighbor = tri) tri.RightNeighbor.BaseNeighbor = tri.RightChild Else If (tri.RightNeighbor.RightNeighbor = tri) tri.RightNeighbor.RightNeighbor = tri.RightChild Else If (tri.RightNeighbor.LeftNeighbor = tri) tri.RightNeighbor.LeftNeighbor = tri.RightChild EndIf EndIf If (tri.BaseNeighbor <> Null) If ( tri.BaseNeighbor.LeftChild <> Null ) tri.BaseNeighbor.LeftChild.RightNeighbor = tri.RightChild tri.BaseNeighbor.RightChild.LeftNeighbor = tri.LeftChild tri.LeftChild.RightNeighbor = tri.BaseNeighbor.RightChild tri.RightChild.LeftNeighbor = tri.BaseNeighbor.LeftChild Else split( tri.BaseNeighbor) EndIf Else tri.LeftChild.RightNeighbor = Null tri.RightChild.LeftNeighbor = Null EndIf 'EndIf End Method Method Render() recursRender(baseLeft,0,Terrain.gPatchSize,Terrain.gPatchSize,0,0,0) recursRender(baseRight , Terrain.gPatchSize , 0 , 0 , Terrain.gPatchSize , Terrain.gPatchSize , Terrain.gPatchSize) 'Print "Render Done ----------------------------------------------------" End Method Method recursRender(tri:TTriTreeNode, leftX:Int,leftY:Int,rightX:Int, rightY:Int,apexX:Int, apexY:Int) If ( tri.LeftChild <> Null) Then Local centerX:Int = (leftX + rightX) Shr 1 Local centerY:Int = (leftY + rightY) Shr 1 recursRender(tri.LeftChild, apexX, apexY, leftX, leftY, centerX, centerY ) recursRender(tri.RightChild, rightX, rightY, apexX, apexY, centerX, centerY ) Else Terrain.gNumTrisRendered:+1 Local leftZ:Float = Terrain.gHeightMap.get(offsetX + leftX, offsetY + leftY); Local rightZ:Float = Terrain.gHeightMap.get(offsetX + rightX, offsetY + rightY); Local apexZ:Float = Terrain.gHeightMap.get(offsetX + apexX, offsetY + apexY); 'Left 'gl.glVertex3f( leftX, leftZ, leftY ); Local v0:Int Terrain.Surface.AddVertex(OffsetX + leftX , leftZ , OffsetY + leftY , 0 , 0) 'Print (OffsetX + leftX) + " : " +(OffsetY + leftY) 'Print leftx + " : " + LeftZ + " : " + Leftx 'Right 'gl.glVertex3f( rightX, rightZ, rightY ); Local v1:Int Terrain.Surface.AddVertex(OffSetX+ rightX, rightZ, OffsetY+rightY ,0,1) 'APEX VERTEX 'gl.glVertex3f( apexX, apexZ, apexY ); Local v2:Int Terrain.Surface.AddVertex(OffSetX + apexX , apexZ , OffsetY+apexY ,1,1) DrawTriangle(offsetX+leftX , OffsetY+leftY,OffsEtX+rightX ,OffsetY+rightY,+OffSetX+apexX , OffSetY+apexY) Terrain.Surface.AddTriangle(v0,v1,v2) EndIf End Method Method DrawTriangle(x1:Int , y1:Int , x2:Int , y2:Int , x3:Int , y3:Int) DrawLine x1 , y1 , x2 , y2 DrawLine x1 , y1 , x3 , y3 DrawLine x2 , y2 , x3 , y3 End Method Method getBaseLeft:TTriTreeNode() Return baseLeft End Method Method getBaseRight:TTriTreeNode() Return baseRight End Method Method getOffsetX:Int() Return offsetX End Method Method getOffsetY:Int() Return offsetY End Method Method isDirty:Int() Return varianceDirty End Method Method markDirty() varianceDirty = True End Method Method GetVisible:Int() Return isVisible End Method Method setVisibility:Int() Return True End Method Method orientation:Int( pX:Int, pY:Int, qX:Int, qY:Int, rX:Int,rY:Int ) Local aX:Int = qX - pX Local aY:Int = qY - pY Local bX:Int = rX - pX Local bY:Int = rY - pY Local d:Int = aX*bY - aY*bX Return ( d <= 0 ) End Method End Type Function distanceApprox:Int(dx:Int, dy:Int) Local maxc:Int = Abs(dx)'dx > 0 ? dx:-dx'; // Math.abs(dx); Local minc:Int = Abs(dy)'dy > 0 ? dy:-dy'; // Math.abs(dy); If (maxc < minc) Then Local temp:Int = maxc maxc = minc; minc = temp EndIf minc = minc Shr 2 maxc:+minc Return maxc End Function Type THeightMap Field hm:Int[,] Field undefined:Int Field minAlt:Int = 257 Field maxAlt:Int = 0 Field width:Int Field height:Int Function Load:THeightmap(url:Object) Local T:THeightmap= New THeightmap Local Pix:TPixmap = LoadPixmap(url) Local BRes:Float = PixmapWidth(Pix) If PixmapWidth(Pix) <> PixmapHeight(Pix) Then Throw "Not Quadatic!" T.hm = New Int[PixmapWidth(Pix)+1, PixmapHeight(Pix)+1] ' Loading HeightValues Local r:Int , g:Int , b:Int Local avg:Int For Local x:Int = 0 To BRes - 1 For Local Y:Int = 0 To Bres - 1 Local C:Int = ReadPixel(pix , x , y) r=(C & $00FF0000) Shr 16 g=(C & $FF00) Shr 8 b=(C & $FF) avg = (r * 0.299) + (g * 0.587) + (b * 0.114) T.hm[x , y] = avg If avg < T.minalt Then T.minalt = avg If avg > t.maxalt Then T.maxalt = avg Next Next T.Width = PixmapWidth(Pix) T.Height = PixmapHeight(Pix) Return T End Function Method Get:Int(X:Int , Y:Int) Return hm[x , y] End Method Method GetWidth:Int() Return Width End Method Method GetHeight:Int() Return Height End Method End Type Function Distance2D#(x0# , y0# , x1# , y1#) Local dx# = x0-x1 Local dy# = y0-y1 Return Sqr(dx*dx + dy*dy) End Function 'Test app Function SampleMouse() Local curMouseX:Int, curMouseY:Int curMouseX = MouseX() curMouseY = MouseY() MouseXSpeed2=curMouseX - prevMouseX MouseYSpeed2=curMouseY - prevMouseY If Abs(centerX - curMouseX) > movementZone Or Abs(centerY - curMouseY) > movementZone Then MoveMouse centerX, centerY prevMouseX = centerX - MouseXSpeed2 prevMouseY = centerY - MouseYSpeed2 Else prevMouseX = curMouseX prevMouseY = curMouseY EndIf End Function Graphics 800 , 600 , 0 , 2 'Local T:TMesh = Q.BuildMesh() 'ScaleEntity(Q.Mesh , 400 , 40 , 400) Local Q:TTerrain = TTerrain.Create("height.bmp" , 32 , 4) Global oldmx:Int Global oldmy:Int Const SAFEZONE:Int = 0 ' set this high to disable repositioning; set to 0 to always reposition Global MouseXSpeed2:Int , MouseYSpeed2:Int , prevMouseX:Int , prevMouseY:Int , movementZone:Int movementzone = Safezone Global CenterX:Int = GraphicsWidth() / 2 Global CenterY:Int = GraphicsHeight() / 2 Global W:Byte = False Local old_ms:Int = MilliSecs() Local fps:Int Local renders:Int While Not KeyHit(Key_Escape) Cls Local MX:Int = MouseX() Local MY:Int = MouseY() 'SetScale 4,4 Q.Update([Float(MX),0.0,Float(MY)]) Q.Render() Splitted =0 renders=renders+1 If MilliSecs()-old_ms>=1000 old_ms=MilliSecs() fps=renders renders=0 EndIf DrawText "FPS : " + FPS + " Split : " + Splitted, GraphicsWidth() - 200 , 40 DrawText " Split : " + Splitted, GraphicsWidth() - 200 , 60 Flip Wend Graphics3D 800 , 600 , 0 , - 1 TGlobal.WireFrame(True) Global Cam:TCamera = CreateCamera() Global L:TLight = CreateLight(1) CameraRange cam , 1 , 80000 'CameraFogMode(cam,0) 'CameraFogRange(cam,500 , 80000) 'CameraFogColor(cam ,128,128,255) CameraCLSColor(cam , 128 , 128 , 255) Global brush:TTexture = LoadTexture("color.jpg") 'Local detail:TTexture = LoadTexture("detail1.jpg",8) 'Local alpha:TTexture = LoadTexture("rock01.jpg",8) 'Local sand:TTexture = LoadTexture("sand1.jpg" , 8) 'scaleTexture(detail , 0.01 , 0.01) 'Q.Mesh.EntityTexture(detail ,, 1) Q.Mesh.EntityTexture(brush ,, 0) AmbientLight 90,90,90 LightColor l,200,200,100 RotateEntity l,60,-90,0 PositionEntity(L , 0 , 90000 , 0) PositionEntity(Cam , EntityX(Q.Mesh) , -800 , EntityZ(Q.Mesh)) PointEntity(Cam,Q.Mesh) Q.Update([0.0,0.0,0.0]) While Not KeyHit(KEY_EScape) SampleMouse() If KeyDown(KEY_UP) Then MoveEntity(Cam , 0 , 0 , 26) If KeyDown(KEY_DOWN) Then MoveEntity(Cam , 0 , 0 , -26) If KeyDown(KEY_Left) Then MoveEntity(Cam , -26, 0 , 0) If KeyDown(KEY_Right) Then MoveEntity(Cam , 26, 0 , 0) If KeyDown(KEY_A) Then MoveEntity(Cam , 0 , 26 , 0) If KeyDown(KEY_Y) Then MoveEntity(Cam , 0 , - 26 , 0) If KeyHit(Key_W) Then WireFrame(Not W) W = Not W EndIf TurnEntity(cam , MouseYSpeed2 * 0.5 , - MouseXSpeed2 * 0.5 , 0) 'PointEntity(Cam,Q.Mesh) 'For Local I:Int = 0 To 20 ' If Rand(0,1000) > 990 Then ' Q.Find(Rand(1 , Q.MatrixSize - 1) , Rand(1 , Q.MatrixSize - 1) ).Split() ' ElseIf Rand(0,1000) < 1 ' Q.Find(Rand(1 , Q.MatrixSize - 1) , Rand(1 , Q.MatrixSize - 1) ).UnSplit() ' EndIf 'Next 'Q.Detail(EntityX(Cam),EntityY(Cam),EntityZ(Cam)) ' Q.Update(Cam) 'Q.Tessellate() Splitted = 0 Q.Update([Float(EntityX(Cam)),0.0,Float(EntityZ(Cam))]) Q.Render() 'ScaleEntity(T,400,40,400) Updateworld() RenderWorld() renders = renders + 1 'MoveMouse(CenterX,CenterY) If MilliSecs()-old_ms>=1000 old_ms=MilliSecs() fps=renders renders=0 EndIf DebugText 20 , 20,"FPS: " + fps + " Quads: " + Q.gPatches.Length DebugText 20 , 40,EntityX(Cam) + " : " + EntityZ(cam) DebugText 20 , 60 , EntityX(Cam) / 400 + " : " + EntityZ(cam) / 400 DebugText 20 , 80 , "TerraTris: " + Q.TrisRendered() DebugText 20 , 100 , "Splits : " + Splitted Flip 0 Wend
As a Heightfile every image which is power of 2 will work.
No my problem:
As you will see, the test app will wirst start a 2d mode, which I have used to check if the triangles are draw right. That's because in the 3d context there appear no triangle also if they where rendered. The next problem is, that there seems to be no update, so the triangles are not really splitted and the triangles are always th same.
Maybe someone with greater experience in Java could take a look to this both sources and maybe he finds out what i was (i lack of java experience) converting wrong.
thx klepto2