`jGfx Plugin: GInst Example - LOD Terrain with Geomipmapping
`=======================================================================================
`Demonstrates the use of vertex texture fetch to apply height displacement in the vertex shader.
`Uses geomipmapping to create smooth transitions between LOD levels.
Sw = Desktop Width()
Sh = Desktop Height()
Set Display Mode Sw,Sh,32,1
Sync On : Sync Rate 0 
Color Backdrop 0 : Autocam Off
Set Camera Range 10,10000
Position Camera -100, 420, -100
Rotate Camera 25, 45, 0


`Load terrain textures
TerHeightmap = 1
TerNormals = 2
TerDiffuseTex = 3
DetailTex = 4
DetailNormalTex = 5
Load Image "Media\Terrain\Height.bmp",TerHeightmap			`Terrain Heightmap
Load Image "Media\Terrain\Height_n.bmp",TerNormals			`Terrain Normals
Load Image "Media\Terrain\Diffuse.bmp",TerDiffuseTex		`Diffuse
Load Image "Media\Terrain\Detail.tga",DetailTex				`Detail
Load Image "Media\Terrain\Detail_n.png",DetailNormalTex		`Detail Normalmap


`Terrain settings
TerSize# = 2560.0									//Terrain world dimensions
TerHeight# = 255.0									//Height scale
DetTiling = 16										//Detail texture tiling

TerSegRes=64										//Segment Mesh Resolution (LOD0)
TerSegments = Image width(TerHeightmap)/TerSegRes	//num segments along each axis
SegWidth# = TerSize# / TerSegments 					//Size of each terrain segment



`Setup Instance Source Object
ObjectID = 1

`create meshes larger than required; avoids pinholes by adding an overlap between adjacent tiles
LOD0Width# = (SegWidth#/TerSegRes)*(TerSegRes+2) 
Make Object Plane ObjectID,LOD0Width#,LOD0Width#,TerSegRes+2,TerSegRes+2	//LOD 0
Make mesh from object ObjectID, 1
Delete object ObjectID
Make Object ObjectID, 1
Delete Mesh 1

LOD1SegRes = TerSegRes*0.5
LOD1Width# = (SegWidth#/LOD1SegRes)*(LOD1SegRes+2)
Make Object Plane 2,LOD1Width#,LOD1Width#,LOD1SegRes+2,LOD1SegRes+2			//LOD 1
make mesh from object 1,2
delete object 2
append limb 1,1
delete mesh 1

LOD2SegRes = TerSegRes*0.25
LOD2Width# = (SegWidth#/LOD2SegRes)*(LOD2SegRes+2)
Make Object Plane 2,LOD2Width#,LOD2Width#,LOD2SegRes+2,LOD2SegRes+2			//LOD 2
make mesh from object 1,2
delete object 2
append limb 1,1
delete mesh 1


Convert Object FVF ObjectID, 0x002 `XYZ only; Normals are read from texture, UVs and Tangents are calculated within the shader.

Texture Object ObjectID,0,TerHeightmap
Texture Object ObjectID,1,TerNormals
Texture Object ObjectID,2,TerDiffuseTex
Texture Object ObjectID,3,DetailTex
Texture Object ObjectID,4,DetailNormalTex




`Load effect
TerrainFx = 1
//Load Effect "Media\GInst_Terrain.fx", TerrainFx, 0		`Diffuse
Load Effect "Media\GInst_TerrainN.fx", TerrainFx, 0		`Diffuse + Detail Normals

Set Effect Constant Float TerrainFx, "HeightScale", TerHeight#
Set Effect Constant Float TerrainFx, "InvTerrainSize", 1.0/TerSize#
Set Effect Constant Float TerrainFX, "SegmentSize", SegWidth#
Set Effect Constant Float TerrainFx, "DetailTiling", DetTiling




`Create GInst
pGInst = GInst_MakeNew(1) `use batch rendering
GInst_SetObject pGInst, ObjectID
GInst_SetEffect pGInst, TerrainFx

GInst_SetLODLevels pGInst, 3
GInst_SetMeshLOD pGInst, 1, 1
GInst_SetMeshLOD pGInst, 2, 2
GInst_SetLODDistance pGInst, 1, SegWidth#*Sqrt(2.0)
GInst_SetLODDistance pGInst, 2, SegWidth#*(Sqrt(2.0)*2)


`Create a GInstBuffer for each segment
for SegX=0 to TerSegments-1
	for SegZ=0 to TerSegments-1
		pInstBuffer = GInstBuffer_MakeNew( pGInst, 1 )
		PosX# = (SegWidth#*0.5) + SegX*SegWidth#
		PosZ# = (SegWidth#*0.5) + SegZ*SegWidth#
		GInstBuffer_SetPosition pInstBuffer, 1, PosX#, 0, PosZ#
		GInstBuffer_SetScale pInstBuffer, 1, 100.0
		GInstBuffer_UpdateInstance pInstBuffer, 1
		
		`manually set GInstBuffer bounds
		MinX# = PosX#-(SegWidth#*0.5)
		MaxX# = PosX#+(SegWidth#*0.5)
		MinZ# = PosZ#-(SegWidth#*0.5)
		MaxZ# = PosZ#+(SegWidth#*0.5)
		`disable automatic bounds calculation
		GInstBuffer_SetAutoBoundsEnabled  pInstBuffer, 0
		GInstBuffer_SetBounds pInstBuffer, MinX#, 0, MinZ#, MaxX#, TerHeight#, MaxZ#
		
		GInstBuffer_Update pInstBuffer
	next SegZ
next SegX





`TBM setup
TimeSpeed# = 0.25
LastTime = Timer()
Do
	Set Cursor 0,0
	Print "FPS = ",Screen Fps()
	Print "Press spacebar to toggle wireframe"
	
	`TBM
	Now = Timer()
	TimePassed# = (Now-LastTime)*TimeSpeed#
	LastTime = Now
	
	`Toggle Wireframe
	SPKey = SpaceKey()
	If SPKey
		If SPHeld = 0
			SPHeld = 1
			WFMode = 1-WFMode
			If WFMode
				Set effect technique 1, "Wireframe"
			Else
				Set effect technique 1, "Diffuse"
			Endif
		Endif
	Else
		SPHeld = 0
	Endif
	
	
	`Camera Control
	Move Camera (UpKey()-DownKey())*TimePassed#
	Move Camera Right (RightKey()-LeftKey())*TimePassed#
	Rotate Camera Wrapvalue(Camera Angle X()+MouseMoveY()),  Wrapvalue(Camera Angle Y()+MouseMoveX()), 0

	Sync
Loop
