234 lines
9.6 KiB
Ada
234 lines
9.6 KiB
Ada
with
|
|
physics.Model,
|
|
Physics,
|
|
|
|
openGL.Model.terrain,
|
|
openGL.IO,
|
|
|
|
ada.unchecked_Deallocation,
|
|
ada.unchecked_Conversion;
|
|
|
|
package body gel.Terrain
|
|
is
|
|
type Heightfield_view is access all physics.Heightfield;
|
|
|
|
type height_Map_view is access all opengl.height_Map;
|
|
type height_map_Grid is array (math.Index range <>,
|
|
math.Index range <>) of height_Map_view;
|
|
|
|
|
|
function Width (Self : in opengl.height_Map) return math.Real
|
|
is
|
|
begin
|
|
return math.Real (self'Length (2) - 1);
|
|
end Width;
|
|
|
|
|
|
function Depth (Self : in opengl.height_Map) return math.Real
|
|
is
|
|
begin
|
|
return math.Real (self'Length (1) - 1);
|
|
end Depth;
|
|
|
|
|
|
|
|
function new_Terrain (World : in gel.World.view;
|
|
heights_File : in String;
|
|
texture_File : in String := "";
|
|
Scale : in math.Vector_3 := (1.0, 1.0, 1.0)) return access gel.Sprite.Grid
|
|
is
|
|
use Math;
|
|
|
|
the_Pixels : opengl.IO.height_Map_view := opengl.IO.to_height_Map (openGL.to_Asset (heights_File));
|
|
|
|
tile_Width : constant Positive := 8 * 32 - 1;
|
|
tile_Depth : constant Positive := 8 * 32 - 1;
|
|
|
|
total_Width : constant Real := Real (the_Pixels'Length (2) - 1) * Scale (1);
|
|
total_Depth : constant Real := Real (the_Pixels'Length (1) - 1) * Scale (3);
|
|
|
|
base_Centre : constant Vector_3 := (0.0, 0.0, 0.0);
|
|
|
|
|
|
function Grid_last (total_Size, tile_Size : in Positive) return math.Index
|
|
is
|
|
Last : constant math.Index := math.Index ( 1
|
|
+ (total_Size - 1) / tile_Size);
|
|
begin
|
|
return Last;
|
|
end Grid_last;
|
|
|
|
|
|
the_heightmap_Grid : height_map_Grid (1 .. Grid_last (the_Pixels'Length (1), tile_Depth),
|
|
1 .. Grid_last (the_Pixels'Length (2), tile_Width));
|
|
|
|
the_Sprite_Grid : constant gel.Sprite.Grid_view := new gel.Sprite.Grid (the_heightmap_Grid'Range (1),
|
|
the_heightmap_Grid'Range (2));
|
|
|
|
procedure free is new ada.unchecked_Deallocation (opengl.height_Map,
|
|
opengl.IO.height_Map_view);
|
|
|
|
procedure flip (Self : opengl.IO.height_Map_view)
|
|
is
|
|
use type opengl.Index_t;
|
|
|
|
the_Map : opengl.IO.height_Map_view := new opengl.height_Map' (Self.all);
|
|
|
|
begin
|
|
for Row in Self'Range (1)
|
|
loop
|
|
for Col in Self'Range (2)
|
|
loop
|
|
Self (Row, Col) := the_Map (Self'Last (1) - Row + 1, Col);
|
|
end loop;
|
|
end loop;
|
|
|
|
free (the_Map);
|
|
end flip;
|
|
|
|
|
|
begin
|
|
flip (the_Pixels.all'unchecked_Access);
|
|
|
|
-- Create each grid elements 'heightmap'.
|
|
--
|
|
declare
|
|
use openGL;
|
|
|
|
row_First, row_Last,
|
|
col_First, col_Last : math.Index; -- Row and col ranges for each sub-matrix.
|
|
|
|
begin
|
|
for Row in the_sprite_Grid'Range (1)
|
|
loop
|
|
row_First := math.Index (tile_Depth - 1) * (Row - 1) + 1;
|
|
row_Last := math.Index'Min (row_First + math.Index (tile_Depth - 1),
|
|
math.Index (the_Pixels'Last (1)));
|
|
|
|
for Col in the_sprite_Grid'Range (2)
|
|
loop
|
|
col_First := math.Index (tile_Width - 1) * (Col - 1) + 1;
|
|
col_Last := math.Index'Min (col_First + math.Index (tile_Width - 1),
|
|
math.Index (the_Pixels'Last (2)));
|
|
|
|
the_heightmap_Grid (Row, Col)
|
|
:= new opengl.height_Map' (Region (the_Pixels.all, (Index_t (row_First), Index_t (row_Last)),
|
|
(Index_t (col_First), Index_t (col_Last))));
|
|
end loop;
|
|
end loop;
|
|
end;
|
|
|
|
-- Create the Sprite for each grid element.
|
|
--
|
|
declare
|
|
site_X_offset,
|
|
site_Z_offset : Real := 0.0;
|
|
site_Y_Offset : Real;
|
|
|
|
tile_X_Offset : Real := 0.0;
|
|
tile_Z_Offset : Real := total_Depth;
|
|
|
|
tile_X_Scale : Real;
|
|
tile_Z_Scale : Real;
|
|
|
|
begin
|
|
for Row in the_sprite_Grid'Range (1)
|
|
loop
|
|
site_X_offset := 0.0;
|
|
|
|
tile_X_Offset := 0.0;
|
|
tile_Z_Offset := tile_Z_Offset - Depth (the_heightmap_Grid (Row, 1).all) * Scale (3);
|
|
|
|
for Col in the_sprite_Grid'Range (2)
|
|
loop
|
|
tile_Z_Scale := Depth (the_heightmap_Grid (Row, 1).all) / total_Depth;
|
|
tile_X_Scale := Width (the_heightmap_Grid (Row, Col).all) / total_Width;
|
|
|
|
declare
|
|
the_Region : constant height_Map_view := the_heightmap_Grid (Row, Col);
|
|
the_height_Range : constant opengl.Vector_2 := openGL.height_Extent (the_Region.all);
|
|
|
|
Tiling : constant opengl.texture_Transform_2d
|
|
:= (S => (opengl.Real (tile_X_Offset / total_Width) / opengl.Real (tile_X_Scale * Scale (1)),
|
|
opengl.Real (tile_X_Scale * Scale (1))),
|
|
T => (opengl.Real (tile_Z_Offset / total_Depth) / opengl.Real (tile_Z_Scale * Scale (3)),
|
|
opengl.Real (tile_Z_Scale * Scale (3))));
|
|
|
|
the_ground_Model : constant access openGL.Model.terrain.item
|
|
:= openGL.Model.terrain.new_Terrain (heights_Asset => openGL.to_Asset (heights_File),
|
|
Row => Row,
|
|
Col => Col,
|
|
Heights => the_Region.all'Access,
|
|
color_Map => openGL.to_Asset (texture_File),
|
|
Tiling => Tiling);
|
|
|
|
function to_Physics is new ada.unchecked_Conversion (height_Map_view,
|
|
physics.Model.Heightfield_view);
|
|
-- Heightfield_view);
|
|
|
|
the_ground_physics_Model : constant physics.Model.view
|
|
:= new physics.Model.item' (Id => physics.null_model_Id,
|
|
-- Site => Origin_3d,
|
|
Scale => Scale,
|
|
shape_Info => (physics.Model.Heightfield,
|
|
Heights => to_Physics (the_Region),
|
|
height_range => (the_height_Range (1),
|
|
the_height_Range (2))),
|
|
Shape => null,
|
|
Mass => 0.0,
|
|
Friction => 0.5,
|
|
Restitution => 0.5,
|
|
is_Tangible => True);
|
|
|
|
the_height_Extents : constant opengl.Vector_2 := opengl.height_Extent (the_Region.all);
|
|
the_Sprite : gel.Sprite.view renames the_sprite_Grid (Row, Col);
|
|
the_Site : vector_3;
|
|
begin
|
|
-- the_ground_Model.Scale := (Scale (1),
|
|
-- Scale (2),
|
|
-- Scale (3));
|
|
|
|
the_Site := (0.0, 0.0, 0.0);
|
|
|
|
the_Sprite := gel.Sprite.Forge.new_Sprite ("Terrain" & Row'Image & Col'Image,
|
|
sprite.World_view (World),
|
|
the_Site,
|
|
the_ground_Model,
|
|
the_ground_physics_Model,
|
|
owns_Graphics => True,
|
|
owns_Physics => True);
|
|
|
|
site_y_Offset := math.Real ( the_height_Extents (1)
|
|
+ (the_height_Extents (2) - the_height_Extents (1)) / 2.0);
|
|
|
|
-- the_sprite_Grid (Row, Col).Site_is (the_Site + base_Centre);
|
|
the_Sprite. Site_is (the_Site + base_Centre);
|
|
the_Sprite.Scale_is (Scale);
|
|
|
|
tile_X_Offset := tile_X_Offset + Width (the_heightmap_Grid (Row, Col).all) * Scale (1);
|
|
|
|
if Col /= the_sprite_Grid'Last (2)
|
|
then
|
|
site_X_offset := site_X_offset
|
|
+ Width (the_heightmap_Grid (Row, Col ).all) * Scale (1) / 2.0
|
|
+ Width (the_heightmap_Grid (Row, Col + 1).all) * Scale (1) / 2.0;
|
|
end if;
|
|
end;
|
|
end loop;
|
|
|
|
if Row /= the_sprite_Grid'Last (1)
|
|
then
|
|
site_Z_offset := site_Z_offset + Depth (the_heightmap_Grid (Row, 1).all) * Scale (3) / 2.0
|
|
+ Depth (the_heightmap_Grid (Row + 1, 1).all) * Scale (3) / 2.0;
|
|
end if;
|
|
end loop;
|
|
end;
|
|
|
|
free (the_Pixels);
|
|
|
|
return the_Sprite_Grid;
|
|
end new_Terrain;
|
|
|
|
|
|
end gel.Terrain;
|