blitznerd: Here you go:
When calling ShowShadow(), be sure to specify a shadow texture (which is applied to the terrain), because the current system can't render it for you yet.
CreateTerrainDecal(mesh, surface, x1#, z1#, x2#, z2#, pitch#, yaw#, roll#) is also useful for applying other decals to the terrain, like the shell craters.
Grisu: Thanks for the suggestions :) I hope to add some of those in the future. For now, you can download some nice mods others have made for BattleTanks II (add-on tanks and maps) here:
[a http://www.bundysoft.com/dokuwiki/doku.php?id=projects:johnj#battletanks_ii]BattleTanks II Expansion Packs[/a]
(scroll down to "Expansion Packs & Add-Ons")
If you want to create your own maps for BattleTanks II, read this:
[a http://www.bundysoft.com/dokuwiki/doku.php?id=projects:johnj:expanding_battletanks_ii]BattleTanks II Map-Making[/a]
;Terrain Shadow Library ;Copyright (C) 2006 John Judnich ;NOTE: Any shadow may not span more than SHADOW_TILES terrain tiles ;TODO: ;+ Ignore update of shadows behind camera ;+ Add frame-skip optimization with interpolated fill-in ; Add automatic shadow contour rendering Const SHADOW_TILES = 256 Const Y_OFFSET# = .7 Const EDGE_Y_OFFSET# = .3 Global ShadowTerrain Global ShadowTerrainScale# Global ShadowPivot Global ShadowFrameSkip = 1 Global FrameCount = 0 Type TerrainShadow Field Entity Field LastX#, LastY#, LastZ# Field LastPitch#, LastYaw#, LastRoll# Field Size# Field ShadowTexture Field ShadowMesh Field ShadowSurface Field ViewDist# Field Visible Field Hidden Field Alpha# Field Scale# End Type ;This initializes the shadow system, making it ready for use. Basically, this just ;sets a variable to a terrain so the shadow system knows what to cast the shadows on. ;Optionally, you can set FrameSkip to adjust how many frames must elapse before the ;shadow mesh is regenerated to fit the terrain's shape. 0 will keep the shadow up to ;date at all times, while higher values may cause some visual "glitches" (mostly on ;mountainous terrains where the shape under the shadow caster changes constantly), ;although the shadow system will run much faster. The default value for FrameSkip is ;1, which works well for almost any terrains. Function ShadowsInit(Terrain, TerrainScale#, FrameSkip = 1) ShadowTerrain = Terrain ShadowTerrainScale# = TerrainScale ShadowFrameSkip = FrameSkip FrameCount = FrameSkip If ShadowPivot = 0 Then ShadowPivot = CreatePivot() End Function ;Use this function to turn on shadows for a specified entity. After calling this function, ;you should see it's shadow on your terrain (as long as you be sure to call UpdateShadows() ;before RenderWorld. "ShadowTexure" provides the option to specify your own shadow, instead ;of letting the shadow system automatically render it. Specifying your own shadow can improve ;loading time with many many entities. Note: When specifying a custom shadow image, you only ;need to do it once - after you do, you can omit the ShadowTexture parameter. Function ShowShadow(Entity, ShadowTexture = 0) objnum = Int(EntityName$(Entity)) obj.TerrainShadow = Object.TerrainShadow(objnum) If obj = Null Or ShadowTexture <> 0 Then ;If there is no shadow for Entity, or it's texture is being changed, then make a new one ;If the shadow texture is being changed, delete the shadow and start over If obj <> Null Then DeleteShadow(Entity) ;Create a new shadow obj.TerrainShadow = New TerrainShadow NameEntity Entity, Handle(obj) obj\Entity = Entity obj\Size = MeshWidth(Entity) depth# = MeshDepth(Entity) If depth > obj\Size Then obj\Size = depth obj\ShadowMesh = CreateMesh() EntityFX obj\ShadowMesh, 1+32 EntityBlend obj\ShadowMesh, 1 obj\ShadowSurface = CreateSurface(obj\ShadowMesh) HideEntity obj\ShadowMesh obj\Alpha = .7 obj\ViewDist = 0 obj\Scale = 1 obj\Hidden = False obj\Visible = False ;Render the shadow if a texture is not specified, otherwise use the given texture If ShadowTexture = 0 Then ;TODO: Render soft shadow to texture Else obj\ShadowTexture = ShadowTexture End If ;Apply texture EntityTexture obj\ShadowMesh, obj\ShadowTexture Else If obj\Hidden = True Then ;Un-hide the shadow if it already exists ShowEntity obj\ShadowMesh obj\Hidden = False End If End If End Function ;This can be used to temporarily turn off a shadow for an object. If you do not plan to show the ;shadow again, DeleteShadow() can be used instead, which deletes it from memory. Function HideShadow(Entity) objnum = Int(EntityName$(Entity)) obj.TerrainShadow = Object.TerrainShadow(objnum) If obj <> Null Then If obj\Hidden = False Then ;Hide the shadow if it exists HideEntity obj\ShadowMesh obj\Hidden = True End If End If End Function ;This turns off an object's shadow, deleting the shadow from memory. You must also be sure to call ;this function before deleting a shadowed entity, because the shadow system may crash, trying to ;access a deleted object when rendering the shadow. Function DeleteShadow(Entity) objnum = Int(EntityName$(Entity)) obj.TerrainShadow = Object.TerrainShadow(objnum) If obj <> Null Then ;Delete the shadow if it exists FreeEntity obj\ShadowMesh Delete obj Else DebugLog "Warning: Tried to delete a non-existant shadow" End If End Function ;This sets the view distance for a shadow. This can be used to increase performance when you have a ;very large amount of objects casting shadows. To disable the view distance limit, set the view ;distance value to 0. Note: When an object reaches the end of it's view distance, the shadow is not ;instantly hidden, the shadow's visibility varies with the object's distance from the camera. Default: 0 Function ShadowViewDistance(Entity, ViewDistance#) objnum = Int(EntityName$(Entity)) obj.TerrainShadow = Object.TerrainShadow(objnum) obj\ViewDist = ViewDistance End Function ;This sets the alpha (transparency) value of a shadow. Values near 0 produce shadows that are barely visible, ;while values near 1 produce shadows almost completely opaque. Default: 0.6 Function ShadowAlpha(Entity, Alpha#) objnum = Int(EntityName$(Entity)) obj.TerrainShadow = Object.TerrainShadow(objnum) obj\Alpha = Alpha End Function ;You can use this function to adjust the size of an object's shadow. Default: 1.0 Function ShadowScale(Entity, Scale#) objnum = Int(EntityName$(Entity)) obj.TerrainShadow = Object.TerrainShadow(objnum) obj\Scale = Scale End Function ;This is a completely optional function which you can use to pre-load shadows for an image, without ;actually showing them yet. You can use this during your loading screen if you are displaying shadows ;for a very large number of objects, and you are using the shadow system's built-in shadow render ;(which can be slow when preparing many objects' shadows). In most cases, however, this function is ;completely unnecessary and you don't need to use it, since the shadow system will automatically prepare ;an object's shadow the first time you call ShowShadow() for an entity. Function PrepareShadow(Entity, ShadowTexture) objnum = Int(EntityName$(Entity)) obj.TerrainShadow = Object.TerrainShadow(objnum) If obj = Null Then ShowShadow(Entity, ShadowTexture) HideShadow(Entity) End If End Function ;This function updates all object's shadows so they appear correctly on your terrain. It is very important that ;you call this function before RenderWorld each loop or shadows may appear incorrectly. "Cam" must be set to ;your game's main camera for this to operate properly. Function UpdateShadows(cam) FrameCount = FrameCount + 1 If FrameCount > ShadowFrameSkip Then FrameCount = 0 For shadow.TerrainShadow = Each TerrainShadow ;Only consider shadows the user did not hide If shadow\Hidden = False Then x# = EntityX(shadow\Entity, True) y# = EntityY(shadow\Entity, True) z# = EntityZ(shadow\Entity, True) pitch# = EntityPitch(shadow\Entity, True) yaw# = EntityYaw(shadow\Entity, True) roll# = EntityRoll(shadow\Entity, True) ;Calculate shadow alpha If shadow\ViewDist <> 0 Then xd# = EntityX(cam, True) - x yd# = EntityY(cam, True) - y zd# = EntityZ(cam, True) - z dist# = Sqr(xd*xd + yd*yd + zd*zd) alpha# = (shadow\ViewDist - dist) / shadow\ViewDist Else alpha# = 1 End If alpha = alpha * shadow\Alpha If alpha < 0 Then alpha = 0 ;Calculate the visibility status of the shadow If alpha <> 0 Then ;Check if the shadow is behind the camera or not TerrY# = TerrainY(ShadowTerrain, x, EntityY(ShadowTerrain), z) If PointVisible(cam, x, TerrY, z) Then Visible = True Else Visible = False End If Else Visible = False End If ;If the shadow is visible, update it If Visible Then ;Only update the shadow mesh if it's entity has moved/rotated If shadow\Visible <> Visible Or x <> shadow\LastX Or y <> shadow\LastY Or z <> shadow\LastZ Or pitch <> shadow\LastPitch Or yaw <> shadow\LastYaw Or roll <> shadow\LastRoll Then If FrameCount = 0 Then ;Regenerate the shadow mesh CreateTerrainDecal(shadow\ShadowMesh, shadow\ShadowSurface, x-shadow\Size*.5*shadow\Scale*1.4142, z-shadow\Size*.5*shadow\Scale*1.4142, x+shadow\Size*.5*shadow\Scale*1.4142, z+shadow\Size*.5*shadow\Scale*1.4142, pitch#, yaw#, roll#) Else ;"Fake" mesh regeneration TranslateEntity shadow\ShadowMesh, x - shadow\LastX, y - shadow\LastY, z - shadow\LastZ TurnEntity shadow\ShadowMesh, 0, yaw - shadow\LastYaw, 0 End If End If ;Update the alpha EntityAlpha shadow\ShadowMesh, alpha End If ;Hide/show the entity as necessary If shadow\Visible <> Visible Then If Visible Then ShowEntity shadow\ShadowMesh Else HideEntity shadow\ShadowMesh End If shadow\Visible = Visible End If shadow\LastX = x shadow\LastY = y shadow\LastZ = z shadow\LastPitch = pitch shadow\LastYaw = yaw shadow\LastRoll = roll End If Next End Function ;****************** Internal Functions ******************* Dim VertGrid(SHADOW_TILES, SHADOW_TILES) Function CreateTerrainDecal(mesh, surface, x1#, z1#, x2#, z2#, pitch#, yaw#, roll#) ClearSurface surface midx# = (x2 + x1) * .5 midz# = (z2 + z1) * .5 PositionEntity mesh, midx, 0, midz RotateEntity mesh, 0, 0, 0 x1grid = Floor(x1 / ShadowTerrainScale) z1grid = Floor(z1 / ShadowTerrainScale) x2grid = Ceil(x2 / ShadowTerrainScale) z2grid = Ceil(z2 / ShadowTerrainScale) For xg = x1grid To x2grid For zg = z1grid To z2grid edge = False vertx# = xg * ShadowTerrainScale vertz# = zg * ShadowTerrainScale If xg = x1grid Then vertx = x1: edge = True If xg = x2grid Then vertx = x2: edge = True If zg = z1grid Then vertz = z1: edge = True If zg = z2grid Then vertz = z2: edge = True verty# = TerrainY(ShadowTerrain, vertx + EntityX(ShadowTerrain), EntityY(ShadowTerrain), vertz + EntityZ(ShadowTerrain)) vertx# = vertx# + EntityX(ShadowTerrain) vertz# = vertz# + EntityZ(ShadowTerrain) If edge = False Then verty# = verty# + Y_OFFSET Else verty# = verty# + EDGE_Y_OFFSET# u# = (vertx-x1) / (x2-x1) v# = (vertz-z1) / (z2-z1) RotateEntity ShadowPivot, 0, -(yaw+180), 0 ScaleEntity ShadowPivot, 1.4142, 1.4142, 1.4142 TFormVector u - .5, 0, v - .5, ShadowPivot, 0 u# = TFormedX() + .5 v# = TFormedZ() + .5 VertGrid(xg-x1grid, zg-z1grid) = AddVertex(surface, vertx - midx, verty, vertz - midz, u, v) Next Next For xg = 1 To (x2grid-x1grid) For zg = 1 To (z2grid-z1grid) AddTriangle surface, VertGrid(xg, zg), VertGrid(xg, zg-1), VertGrid(xg-1, zg-1) AddTriangle surface, VertGrid(xg-1, zg), VertGrid(xg, zg), VertGrid(xg-1, zg-1) Next Next End Function Function PointVisible(Viewer, x#, y#, z#) TFormPoint x, y, z, 0, Viewer If TFormedZ() <= 0 Then Return False Else Return True End Function
When calling ShowShadow(), be sure to specify a shadow texture (which is applied to the terrain), because the current system can't render it for you yet.
CreateTerrainDecal(mesh, surface, x1#, z1#, x2#, z2#, pitch#, yaw#, roll#) is also useful for applying other decals to the terrain, like the shell craters.
Grisu: Thanks for the suggestions :) I hope to add some of those in the future. For now, you can download some nice mods others have made for BattleTanks II (add-on tanks and maps) here:
[a http://www.bundysoft.com/dokuwiki/doku.php?id=projects:johnj#battletanks_ii]BattleTanks II Expansion Packs[/a]
(scroll down to "Expansion Packs & Add-Ons")
If you want to create your own maps for BattleTanks II, read this:
[a http://www.bundysoft.com/dokuwiki/doku.php?id=projects:johnj:expanding_battletanks_ii]BattleTanks II Map-Making[/a]