337 lines
12 KiB
Ada
337 lines
12 KiB
Ada
with
|
|
openGL.Camera,
|
|
openGL.Model.billboard.textured,
|
|
openGL.texture_Set,
|
|
|
|
ada.unchecked_Deallocation;
|
|
|
|
package body openGL.Impostor
|
|
is
|
|
---------
|
|
--- Forge
|
|
--
|
|
|
|
procedure destroy (Self : in out Item)
|
|
is
|
|
use openGL.Visual,
|
|
Model,
|
|
Texture;
|
|
|
|
the_Model : Model.view := Self.Visual.Model;
|
|
the_Texture : Texture.Object := Model.billboard.textured.view (the_Model).Texture;
|
|
begin
|
|
free (the_Texture);
|
|
free (the_Model);
|
|
free (Self.Visual);
|
|
end destroy;
|
|
|
|
|
|
procedure free (Self : in out View)
|
|
is
|
|
procedure deallocate is new ada.unchecked_Deallocation (Item'Class, View);
|
|
begin
|
|
if Self /= null then
|
|
destroy (Self.all);
|
|
deallocate (Self);
|
|
end if;
|
|
end free;
|
|
|
|
|
|
|
|
--------------
|
|
--- Attributes
|
|
--
|
|
|
|
procedure Visual_is (Self : in out Item; Now : in openGL.Visual.view)
|
|
is
|
|
begin
|
|
Self.Visual := Now;
|
|
end Visual_is;
|
|
|
|
|
|
function Visual (Self : access Item) return openGL.Visual.view
|
|
is
|
|
begin
|
|
return Self.Visual;
|
|
end Visual;
|
|
|
|
|
|
|
|
function get_Target (Self : in Item) return openGL.Visual.view
|
|
is
|
|
begin
|
|
return Self.Target;
|
|
end get_Target;
|
|
|
|
|
|
procedure set_Target (Self : in out Item; Target : in openGL.Visual.view)
|
|
is
|
|
use type openGL.Visual.view;
|
|
|
|
Width : constant Real := Target.Model.Bounds.Ball * 2.00;
|
|
Height : constant Real := Target.Model.Bounds.Ball * 2.00;
|
|
|
|
begin
|
|
if Self.Visual = null
|
|
then
|
|
Self.Visual := new openGL.Visual.item;
|
|
end if;
|
|
|
|
Self.Target := Target;
|
|
Self.is_Terrain := Target.is_Terrain;
|
|
|
|
Self.Visual.Model_is (Model.billboard.textured.Forge.new_Billboard (Size => (Width => Width,
|
|
Height => Height),
|
|
Plane => Model.billboard.xy,
|
|
Texture => null_Asset,
|
|
texture_Details => texture_Set.to_Details ([1 => null_Asset])).all'Access);
|
|
Self.Visual.Transform_is (Target.Transform);
|
|
-- Self.Visual.model_Transform_is (Target.model_Transform);
|
|
end set_Target;
|
|
|
|
|
|
|
|
function target_camera_Distance (Self : in Item'Class) return Real
|
|
is
|
|
begin
|
|
return Self.target_camera_Distance;
|
|
end target_camera_Distance;
|
|
|
|
|
|
function is_Valid (Self : in Item'Class) return Boolean
|
|
is
|
|
begin
|
|
return Self.is_Valid;
|
|
end is_Valid;
|
|
|
|
|
|
function never_Updated (Self : in Item'Class) return Boolean
|
|
is
|
|
begin
|
|
return Self.never_Updated;
|
|
end never_Updated;
|
|
|
|
|
|
function frame_Count_since_last_update (Self : in Item'Class) return Natural
|
|
is
|
|
begin
|
|
return Natural (Self.freshen_Count);
|
|
end frame_Count_since_last_update;
|
|
|
|
|
|
function face_Count (Self : in Item) return Natural
|
|
is
|
|
pragma unreferenced (Self);
|
|
begin
|
|
return 1;
|
|
end face_Count;
|
|
|
|
|
|
procedure set_Alpha (Self : in out Item; Alpha : in Real)
|
|
is
|
|
begin
|
|
null; -- TODO
|
|
end set_Alpha;
|
|
|
|
|
|
function Bounds (Self : in Item) return openGL.Bounds
|
|
is
|
|
pragma Unreferenced (Self);
|
|
begin
|
|
return (others => <>); -- TODO
|
|
end Bounds;
|
|
pragma Unreferenced (Bounds);
|
|
|
|
|
|
function is_Transparent (Self : in Item) return Boolean
|
|
is
|
|
pragma unreferenced (Self);
|
|
begin
|
|
return True;
|
|
end is_Transparent;
|
|
|
|
|
|
-- Update trigger configuration.
|
|
--
|
|
|
|
procedure set_freshen_count_update_trigger_Mod (Self : in out Item; To : in Positive)
|
|
is
|
|
begin
|
|
Self.freshen_count_update_trigger_Mod := Counter (To);
|
|
end set_freshen_count_update_trigger_Mod;
|
|
|
|
|
|
function get_freshen_count_update_trigger_Mod (Self : in Item) return Positive
|
|
is
|
|
begin
|
|
return Positive (Self.freshen_count_update_trigger_Mod);
|
|
end get_freshen_count_update_trigger_Mod;
|
|
|
|
|
|
|
|
procedure set_size_update_trigger_Delta (Self : in out Item; To : in Positive)
|
|
is
|
|
begin
|
|
Self.size_update_trigger_Delta := gl.glSizeI (To);
|
|
end set_size_update_trigger_Delta;
|
|
|
|
|
|
function get_size_update_trigger_Delta (Self : in Item) return Positive
|
|
is
|
|
begin
|
|
return Positive (Self.size_update_trigger_Delta);
|
|
end get_size_update_trigger_Delta;
|
|
|
|
|
|
|
|
function general_Update_required (Self : access Item; the_Camera_Site : in Vector_3;
|
|
the_pixel_Region : in pixel_Region) return Boolean
|
|
is
|
|
pragma unreferenced (the_pixel_Region);
|
|
|
|
use linear_Algebra_3d;
|
|
use type gl.GLsizei;
|
|
|
|
Camera_has_moved : constant Boolean := the_Camera_Site /= Self.prior_camera_Position;
|
|
Target_has_moved : constant Boolean := get_Translation (Self.Target.Transform) /= Self.prior_target_Position;
|
|
-- Target_has_moved : constant Boolean := get_Translation (Self.Target.model_Transform) /= Self.prior_target_Position;
|
|
|
|
begin
|
|
Self.freshen_Count := Self.freshen_Count + 1;
|
|
|
|
if Self.freshen_Count > Self.freshen_count_update_trigger_Mod
|
|
then
|
|
return True;
|
|
end if;
|
|
|
|
if Camera_has_moved
|
|
and then abs (Angle (the_Camera_Site,
|
|
Self.prior_target_Position,
|
|
Self.prior_camera_Position)) > to_Radians (15.0)
|
|
then
|
|
return True;
|
|
end if;
|
|
|
|
if Target_has_moved
|
|
and then abs (Angle (get_Translation (Self.Target.Transform),
|
|
-- and then abs (Angle (get_Translation (Self.Target.model_Transform),
|
|
Self.prior_camera_Position,
|
|
Self.prior_target_Position)) > to_Radians (15.0)
|
|
then
|
|
return True;
|
|
end if;
|
|
|
|
|
|
if Self.prior_pixel_Region.Width > 40 -- Ignore target rotation triggered updates when target is small on screen.
|
|
and then Self.prior_pixel_Region.Height > 40 --
|
|
and then Self.prior_target_Rotation /= get_Rotation (Self.Target.Transform)
|
|
-- and then Self.prior_target_Rotation /= get_Rotation (Self.Target.model_Transform)
|
|
then
|
|
return True;
|
|
end if;
|
|
|
|
return False;
|
|
end general_Update_required;
|
|
|
|
|
|
|
|
function size_Update_required (Self : access Item; the_pixel_Region : in pixel_Region) return Boolean
|
|
is
|
|
use GL;
|
|
use type gl.GLsizei;
|
|
begin
|
|
return abs (the_pixel_Region.Width - Self.prior_Width_Pixels) > Self.size_update_trigger_Delta
|
|
or abs (the_pixel_Region.Height - Self.prior_Height_pixels) > Self.size_update_trigger_Delta;
|
|
end size_Update_required;
|
|
|
|
|
|
|
|
function get_pixel_Region (Self : access Item'Class; camera_Spin : in Matrix_3x3;
|
|
camera_Site : in Vector_3;
|
|
camera_projection_Transform : in Matrix_4x4;
|
|
camera_Viewport : in linear_Algebra_3d.Rectangle) return pixel_Region
|
|
is
|
|
use linear_Algebra_3D;
|
|
|
|
-- target_Centre : constant Vector_3 := camera_Spin * ( get_Translation (Self.Target.model_Transform)
|
|
target_Centre : constant Vector_3 := camera_Spin * ( get_Translation (Self.Target.Transform)
|
|
- camera_Site);
|
|
|
|
target_lower_Left : constant Vector_3 := target_Centre - [Self.Target.Model.Bounds.Ball,
|
|
Self.Target.Model.Bounds.Ball,
|
|
0.0];
|
|
|
|
target_Centre_proj : constant Vector_4 := target_Centre * camera_projection_Transform;
|
|
target_Lower_Left_proj : constant Vector_4 := target_lower_Left * camera_projection_Transform;
|
|
|
|
target_Centre_norm : constant Vector_3 := [target_Centre_proj (1) / target_Centre_proj (4),
|
|
target_Centre_proj (2) / target_Centre_proj (4),
|
|
target_Centre_proj (3) / target_Centre_proj (4)];
|
|
|
|
target_Lower_Left_norm : constant Vector_3 := [target_Lower_Left_proj (1) / target_Lower_Left_proj (4),
|
|
target_Lower_Left_proj (2) / target_Lower_Left_proj (4),
|
|
target_Lower_Left_proj (3) / target_Lower_Left_proj (4)];
|
|
|
|
target_Centre_norm_0to1 : constant Vector_3 := [target_Centre_norm (1) * 0.5 + 0.5,
|
|
target_Centre_norm (2) * 0.5 + 0.5,
|
|
target_Centre_norm (3) * 0.5 + 0.5];
|
|
|
|
target_Lower_Left_norm_0to1 : constant Vector_3 := [target_Lower_Left_norm (1) * 0.5 + 0.5,
|
|
target_Lower_Left_norm (2) * 0.5 + 0.5,
|
|
target_Lower_Left_norm (3) * 0.5 + 0.5];
|
|
|
|
viewport_Width : constant Integer := camera_Viewport.Max (1) - camera_Viewport.Min (1) + 1;
|
|
viewport_Height : constant Integer := camera_Viewport.Max (2) - camera_Viewport.Min (2) + 1;
|
|
|
|
Width : constant Real := 2.0 * Real (viewport_Width) * ( target_Centre_norm_0to1 (1)
|
|
- target_Lower_Left_norm_0to1 (1));
|
|
|
|
Width_pixels : constant gl.glSizei := gl.glSizei ( Integer (Real (viewport_Width) * target_Lower_Left_norm_0to1 (1) + Width)
|
|
- Integer (Real (viewport_Width) * target_Lower_Left_norm_0to1 (1))
|
|
+ 1);
|
|
|
|
Height : constant Real := 2.0 * Real (viewport_Height) * ( target_Centre_norm_0to1 (2)
|
|
- target_Lower_Left_norm_0to1 (2));
|
|
|
|
Height_pixels : constant gl.glSizei := gl.glSizei ( Integer (Real (viewport_Height) * target_Lower_Left_norm_0to1 (2) + Height)
|
|
- Integer (Real (viewport_Height) * target_Lower_Left_norm_0to1 (2))
|
|
+ 1);
|
|
use type gl.GLsizei;
|
|
|
|
begin
|
|
Self.all.target_camera_Distance := abs (target_Centre); -- NB: Cache distance from camera to target.
|
|
|
|
return (X => gl.glInt (target_Lower_Left_norm_0to1 (1) * Real (Viewport_Width)) - 0,
|
|
Y => gl.glInt (target_Lower_Left_norm_0to1 (2) * Real (viewport_Height)) - 0,
|
|
Width => Width_pixels + 0,
|
|
Height => Height_pixels + 0);
|
|
end get_pixel_Region;
|
|
|
|
|
|
--------------
|
|
-- Operations
|
|
--
|
|
|
|
procedure update (Self : in out Item; the_Camera : access Camera.item'Class;
|
|
texture_Pool : in texture.Pool_view)
|
|
is
|
|
pragma unreferenced (the_Camera, texture_Pool);
|
|
use openGL.Visual;
|
|
|
|
-- Width_size : constant openGL.texture.Size := to_Size (Natural (Self.current_Width_pixels));
|
|
-- Height_size : constant openGL.texture.Size := to_Size (Natural (Self.current_Height_pixels));
|
|
|
|
-- texture_Width : constant gl.glSizei := power_of_2_Ceiling (Natural (Self.current_Width_pixels ));
|
|
-- texture_Height : constant gl.glSizei := power_of_2_Ceiling (Natural (Self.current_Height_pixels));
|
|
|
|
the_Model : constant Model.billboard.textured.view := Model.billboard.textured.view (Self.Visual.Model);
|
|
-- GL_Error : Boolean;
|
|
|
|
begin
|
|
Self.Visual.all := Self.Target.all;
|
|
Self.Visual.Model_is (the_Model.all'Access);
|
|
end update;
|
|
|
|
|
|
end openGL.Impostor;
|