1. ------------------------------------------------------------------------- 
  2. --  GLOBE_3D - GL - based, real - time, 3D engine 
  3. -- 
  4. --  Copyright (c) Gautier de Montmollin 2001 .. 2012 
  5. --  SWITZERLAND 
  6. --  Copyright (c) Rod Kay 2006 .. 2008 
  7. --  AUSTRALIA 
  8. -- 
  9. --  Permission is hereby granted, free of charge, to any person obtaining a copy 
  10. --  of this software and associated documentation files (the "Software"), to deal 
  11. --  in the Software without restriction, including without limitation the rights 
  12. --  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
  13. --  copies of the Software, and to permit persons to whom the Software is 
  14. --  furnished to do so, subject to the following conditions: 
  15.  
  16. --  The above copyright notice and this permission notice shall be included in 
  17. --  all copies or substantial portions of the Software. 
  18.  
  19. --  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
  20. --  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
  21. --  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
  22. --  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
  23. --  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
  24. --  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
  25. --  THE SOFTWARE. 
  26.  
  27. -- N.  : this is the MIT License, as found 12 - Sep - 2007 on the site 
  28. -- http://www.opensource.org/licenses/mit - license.php 
  29.  
  30. ------------------------------------------------------------------------- 
  31.  
  32. -- 
  33. -- Added "List_status" and "List_Id" to the Object_3D. 
  34. -- by default the Display_One routine will now generate a GL command list 
  35. -- instead of sending the command each time explicitely. 
  36. -- To disable this feature, set Object_3D.List_Status to "No_List". 
  37. -- If memory is not sufficient to hold a list, the Display_One routine will 
  38. -- automatically default back to "No_List". 
  39. -- 
  40. -- Uwe R. Zimmer, July 2011 
  41. -- 
  42. -- 
  43. -- Added an alternative 
  44. -- display face routine which is optimized to produce a shorter list 
  45. -- of GL commands. Runs slower than the original Display face routine 
  46. -- yet needs to be executed only once. 
  47. -- 
  48. -- Uwe R. Zimmer, July 2011 
  49. -- 
  50. -- Cleaned up the whole code base (including the whole GL base) to address 
  51. -- _every_ warning and style message. Restructed the code in places to 
  52. -- take advantage of Ada 2012. No identifier hides any other in the surrounding 
  53. -- scope any more. Compound assignments and function-expressions have been 
  54. -- used frequently to make the code leaner and safer. The code will no longer 
  55. -- compile under Ada 2005 or earlier though. 
  56. -- 
  57. -- Uwe R. Zimmer, September 2013 
  58. -- 
  59.  
  60. with GL, 
  61.      GL.Geometry, 
  62.      GL.Frustums, 
  63.      GL.Skinned_Geometry, 
  64.      GL.Materials; 
  65.  
  66. use GL; 
  67.  
  68. with Zip; 
  69.  
  70. with Ada.Text_IO; 
  71. with Ada.Numerics.Generic_Elementary_Functions; 
  72. with Ada.Strings.Unbounded; 
  73. with Ada.Unchecked_Deallocation; 
  74. with Ada.Containers.Hashed_Maps; 
  75. with Ada.Strings.Unbounded.Hash; 
  76.  
  77. package GLOBE_3D is 
  78.  
  79.    subtype Ident is String (1 .. 40); 
  80.    -- Identifiers for naming things (textures, objects, . .. ) 
  81.    -- Identifiers are case insensitive and stored as UPPER_CASE 
  82.  
  83.    empty  : constant Ident := (others => ' '); 
  84.  
  85.    -- Set the name of Zip archives containing the data. 
  86.    -- 
  87.    -- If an item is not found in the level (local) data, it is 
  88.    -- searched in the global data. The idea is to set the global 
  89.    -- data once in the execution of the program, and change the local data 
  90.    -- upon context change (e.g., in a game, a change of level). 
  91.    procedure Set_local_data_name  (s : String); 
  92.    procedure Set_level_data_name  (s : String) renames Set_local_data_name; 
  93.    procedure Set_global_data_name (s : String); 
  94.  
  95.    data_file_not_found : exception; 
  96.  
  97.    -- List of textures ID's, correspond to files in 
  98.    -- the archives and to GL's "names" 
  99.    type Image_ID is new Integer range -1 .. Integer'Last; 
  100.    null_image : constant Image_ID := -1; 
  101.  
  102.    subtype Real is GL.Double; 
  103.    package REF is new Ada.Numerics.Generic_Elementary_Functions (Real); 
  104.    package RIO is new Ada.Text_IO.Float_IO (Real); 
  105.  
  106.    subtype Vector_3D is GL.Double_Vector_3D; 
  107.    type  p_Vector_3D is access all Vector_3D; 
  108.  
  109.    type Vector_4D is array (0 .. 3) of Real; 
  110.  
  111.    subtype Point_3D is Vector_3D; 
  112.  
  113.    type Matrix    is array (Positive range <>, Positive range <>) of aliased Real; 
  114.    type Matrix_33 is new Matrix (1 .. 3, 1 .. 3); 
  115.    type Matrix_44 is new Matrix (1 .. 4, 1 .. 4); 
  116.  
  117.    Id_33 : constant Matrix_33 := ((1.0, 0.0, 0.0), 
  118.                                   (0.0, 1.0, 0.0), 
  119.                                   (0.0, 0.0, 1.0)); 
  120.  
  121.    type Point_3D_array   is array (Positive range <>) of aliased Point_3D; 
  122.    type p_Point_3D_array is access Point_3D_array; 
  123.    type Vector_3D_array  is array (Natural range <>) of Vector_3D; 
  124.  
  125.    type Natural_Index_array is array (Natural range <>) of aliased Natural;   -- tbd : make GL.unsigned_Int (or unsigned_Short)? 
  126.  
  127.    ---------------------------------------------------------------- 
  128.    -- Portal rendering definitions (methods in GLOBE_3D.Portals) -- 
  129.    ---------------------------------------------------------------- 
  130.  
  131.    type Rectangle is record 
  132.       X1, Y1, X2, Y2 : Integer; 
  133.    end record; 
  134.  
  135.    subtype Clipping_area is Rectangle; 
  136.  
  137.    -- ^ Cheap but fast portal culling & clipping method with rectangles. 
  138.    --   Usually, a bit too much is displayed. 
  139.    --   With graphics cards as of 2005 + , it doesn't matter at all 
  140.    --   The important aspect is the culling of the objects when the 
  141.    --   intersection is empty. 
  142.  
  143.    type Clipping_data is record 
  144.       Eye_Position     : aliased Point_3D; 
  145.       view_direction   : Vector_3D; 
  146.       max_dot_product  : Real;         -- depends on the field of view 
  147.       main_clipping    : Clipping_area; 
  148.    end record; 
  149.  
  150.    -- Camera 
  151.    -- 
  152.  
  153.    fairly_Far                   : constant := 50_000.0; 
  154.    default_field_of_view_Angle  : constant :=     55.0; 
  155.  
  156.    type Camera is tagged 
  157.       record 
  158.          Clipper              : Clipping_data := (Eye_Position    => (0.0,  0.0,  5.0), 
  159.                                                   view_direction  => (0.0,  0.0, -1.0), 
  160.                                                   max_dot_product => 0.0, 
  161.                                                   main_clipping   => (0, 0, 0, 0)); 
  162.          World_Rotation       : Matrix_33 := Id_33; 
  163.          Speed                : Vector_3D := (0.0, 0.0, 0.0); 
  164.          rotation_Speed       : Vector_3D := (0.0, 0.0, 0.0); 
  165.          compose_rotations    : Boolean := True; 
  166.          -- True : apply successive rotations from rotation_Speed directly 
  167.          --       to world_Rotation. Good for totally free 3D movement, no gravity. 
  168.          --       Drawback : rotations around x axis, then y, then x, .. . induce a 
  169.          --       rotation around z (the nose) which is x rotated around y. 
  170.          -- False : world_Rotation is set as XYZ_rotation of the rotation vector below; 
  171.          --        x, y, z keep separate. 
  172.          -- Cf implementation in the package Actors 
  173.          rotation             : Vector_3D := (0.0, 0.0, 0.0); 
  174.          -- ^ this vector is updated, whatever the state of 'compose_rotations' 
  175.  
  176.          FOVy                 : Real  := default_field_of_view_Angle;  -- field of view angle (deg) in the y direction 
  177.          Aspect               : Real;                                  -- x/y aspect ratio 
  178.  
  179.          near_plane_Distance  : Real  := 1.0;                          -- distance to the near clipping plane 
  180.          near_plane_Width     : Real; 
  181.          near_plane_Height    : Real; 
  182.  
  183.          far_plane_Distance   : Real  := fairly_Far;                   -- distance to the far clipping plane 
  184.          far_plane_Width      : Real; 
  185.          far_plane_Height     : Real; 
  186.  
  187.          Projection_Matrix    : Matrix_44; 
  188.  
  189.          frustum_Planes       : GL.Frustums.plane_Array; 
  190.       end record; 
  191.  
  192.    type p_Camera is access all Camera'Class; 
  193.  
  194.    -- 'Visual' class hierarchy 
  195.    -- 
  196.  
  197.    type Visual is abstract tagged 
  198.       record 
  199.          ID                      : Ident := "-Nameless-                              "; 
  200.          --                                  1234567890123456789012345678901234567890 
  201.  
  202.          Centre                  : Point_3D  := (0.0, 0.0, 0.0); -- vertex coords are relative to the centre. 
  203.          Centre_Camera_Space     : Point_3D;                     -- the visuals 'centre' in camera space. 
  204.          rotation                : Matrix_33 := Id_33; 
  205.  
  206.          is_Terrain              : Boolean   := False; 
  207.       end record; 
  208.  
  209.    type p_Visual is access all Visual'Class; 
  210.    type Visual_array is array (Positive range <>) of p_Visual; 
  211.  
  212.    procedure Destroy        (o      : in out Visual) is abstract; 
  213.    procedure Free           (o      : in out p_Visual); 
  214.  
  215.    procedure Pre_calculate  (o      : in out Visual) is abstract; 
  216.  
  217.    procedure set_Alpha      (o      : in out Visual; 
  218.                              Alpha  :        GL.Double) is abstract; 
  219.  
  220.    function  is_Transparent (o      :        Visual) return Boolean is abstract; 
  221.    -- 
  222.    -- returns 'True' if any part of the 'visual' is potentially transparent. 
  223.  
  224.    function face_Count (o  : Visual) return Natural                   is abstract; 
  225.    function Bounds     (o  : Visual) return GL.Geometry.Bounds_record is abstract; 
  226.  
  227.    function skinned_Geometrys (o  : Visual) return GL.Skinned_Geometry.skinned_Geometrys; 
  228.  
  229.    procedure Display (o           : in out Visual; 
  230.                       clip        :        Clipping_data) is abstract; 
  231.  
  232.    procedure Set_name (o : in out Visual'class; new_name : String); 
  233.    -- Give a new name (no need of space - filling) to the object 
  234.  
  235.    function Get_name (o : Visual'class) return String; 
  236.  
  237.    function Width  (o : Visual'class) return Real; 
  238.    function Height (o : Visual'class) return Real; 
  239.    function Depth  (o : Visual'class) return Real; 
  240.  
  241.    null_Visuals  : constant Visual_array (1 .. 0) := (others => null); 
  242.  
  243.    procedure render (the_Visuals  : Visual_array; the_Camera  : Camera); 
  244.    -- 
  245.    -- clears the color buffer and renders each of the visuals. 
  246.  
  247.    -- Map_of_Visuals 
  248.    -- 
  249.    -- We define here a way of finding quickly a Visual's access 
  250.    -- through its identifier. 
  251.    -- 
  252.    type Map_of_Visuals is private; 
  253.    -- One can begin with empty_map, then Add Visuals one per one: 
  254.    function empty_map return Map_of_Visuals; 
  255.    procedure Add (to_map : in out Map_of_Visuals; what : p_Visual); 
  256.    Duplicate_name : exception; 
  257.    -- One can also get a map of an array of visuals in one go: 
  258.    function Map_of (va : Visual_array) return Map_of_Visuals; 
  259.  
  260.    -- original G3D Object class 
  261.    -- 
  262.  
  263.    type Object_3D; 
  264.    type p_Object_3D is access all Object_3D'Class; 
  265.  
  266.    ------------------- 
  267.    -- Define a face -- 
  268.    ------------------- 
  269.  
  270.    type Skin_Type is (texture_only, 
  271.                       colour_only, 
  272.                       coloured_texture, 
  273.                       material_only, 
  274.                       material_texture, 
  275.                       invisible); 
  276.  
  277.    type Set_of_Skin is array (Skin_Type) of Boolean; 
  278.  
  279.    is_textured : constant Set_of_Skin := 
  280.      (texture_only | coloured_texture | material_texture => True, 
  281.       others => False); 
  282.  
  283.    null_colour : constant GL.Material_Float_vector := (0.0, 0.0, 0.0, 0.0); 
  284.  
  285.    subtype Idx_3_array is Natural_Index_array (1 .. 3); 
  286.  
  287.    subtype Idx_4_array is Natural_Index_array (1 .. 4); 
  288.    type Idx_4_array_array is array (Positive range <>) of Idx_4_array; 
  289.  
  290.    type Map_idx_pair is record U, V : aliased GL.Double; end record; 
  291.    type Map_idx_pair_array is array (Natural range <>) of Map_idx_pair; 
  292.    subtype Map_idx_pair_4_array is Map_idx_pair_array (1 .. 4); 
  293.  
  294.    type Face_type is record 
  295.       P             : Idx_4_array;  -- indices of the edges (anticlockwise) 
  296.       -- one of them can be 0 (triangle); then the 
  297.       -- "missing" edge indicates how to put texture 
  298.       -- *** Portals : 
  299.       connecting    : p_Object_3D := null; -- object behind - if there is one 
  300.  
  301.       -- *** Surface 
  302.       skin          : Skin_Type; 
  303.       mirror        : Boolean := False;  -- mirror just behind the skin ? 
  304.       alpha         : GL.Double := 1.0; 
  305.       -- alpha in [0;1] for blending colours and textures. 
  306.       -- NB : when this value (or all of material colours) is equal to 
  307.       --     one, the blending for transparency is switched off to gain 
  308.       --     speed; GLOBE_3D can switch on the blending again when loading 
  309.       --     a texture that has an alpha layer 
  310.       -- *** > colour part (data ignored when irrelevant): 
  311.       colour        : GL.RGB_Color; 
  312.       -- *** > material part (data ignored when irrelevant): 
  313.       material      : GL.Materials.Material_type := 
  314.         GL.Materials.neutral_material; 
  315.       -- *** > texture - mapping part (data ignored when irrelevant): 
  316.       texture       : Image_ID := null_image; 
  317.       --  Alternative to setting an Image_id, if it is not known at 
  318.       --  time of building the object : use Texture_name_hint, then 
  319.       --  Rebuild_links 
  320.       -- 
  321.       --    Whole texture or part of one ? 
  322.       whole_texture : Boolean := True; 
  323.       --    - in case of a whole texture, automatic mapping, we just need 
  324.       --      to know how many times is it tiled: 
  325.       repeat_U, 
  326.       repeat_V      : Positive := 1; 
  327.       --    - in case of a partial texture (e.g. for a texture spread 
  328.       --      across several faces), we need a deterministic mapping: 
  329.       texture_edge_map : 
  330.       Map_idx_pair_4_array; 
  331.    end record; 
  332.  
  333.    type Face_array is array (Natural range <>) of aliased Face_type; 
  334.    type p_Face_array is access Face_array; 
  335.  
  336.    subtype Edge_count is Positive range 3 .. 4; 
  337.  
  338.    -- Invariants : things that don't change during the object's life 
  339.  
  340.    type Face_invariant_type is private; -- GLOBE_3D - internal, nothing for users 
  341.  
  342.    type Face_invariant_array is array (Natural range <>) of Face_invariant_type; 
  343.  
  344.    type Object_3D_list; 
  345.    type p_Object_3D_list is access Object_3D_list; 
  346.    type Object_3D_list is record 
  347.       objc : p_Object_3D; 
  348.       next : p_Object_3D_list; 
  349.    end record; 
  350.  
  351.    type Object_3D_array is array (Positive range <>) of p_Object_3D; 
  352.    type p_Object_3D_array is access Object_3D_array; 
  353.  
  354.    ----------------------------------- 
  355.    -- Now : the Object_3D definition -- 
  356.    ----------------------------------- 
  357.  
  358.    type List_Cases  is (No_List, Generate_List, Is_List); 
  359.    subtype List_Ids is Positive; 
  360.  
  361.    -- 
  362.    -- Added "List_status" and "List_Id" to the Object_3D. 
  363.    -- by default the Display_One routine will now generate a GL command list 
  364.    -- instead of sending the command each time explicitely. 
  365.    -- To disable this feature, set Object_3D.List_Status to "No_List". 
  366.    -- If memory is not sufficient to hold a list, the Display_One routine will 
  367.    -- automatically default back to "No_List". 
  368.    -- 
  369.    -- Uwe R. Zimmer, July 2011 
  370.    -- 
  371.    type Object_3D (Max_points, Max_faces : Integer) is new Visual with record 
  372.       Point           : Point_3D_array  (1 .. Max_points);  -- vertices 
  373.       edge_vector     : Vector_3D_array (1 .. Max_points);  -- normals for lighting 
  374.       face            : Face_array (1 .. Max_faces); 
  375.       sub_objects     : p_Object_3D_list := null; 
  376.       -- List of objects to be drawn AFTER the 
  377.       -- object itself e.g., things inside a room 
  378.       pre_calculated  : Boolean := False; 
  379.       List_Status     : List_Cases := Generate_List; 
  380.       -- private: 
  381.       List_Id         : List_Ids; 
  382.       Face_Invariant  : Face_invariant_array (1 .. Max_faces); 
  383.       Bounds          : GL.Geometry.Bounds_record; 
  384.       transparent     : Boolean := False; 
  385.    end record; -- Object_3D 
  386.  
  387.    overriding procedure Destroy        (o  : in out Object_3D); 
  388.    overriding procedure set_Alpha      (o  : in out Object_3D; Alpha  : GL.Double); 
  389.    overriding function  is_Transparent (o  :        Object_3D) return Boolean; 
  390.    overriding function  face_Count     (o  :        Object_3D) return Natural; 
  391.    overriding function  Bounds         (o  :        Object_3D) return GL.Geometry.Bounds_record; 
  392.  
  393.    procedure Check_object (o : Object_3D); 
  394.    -- Check object for invalid or duplicate vertices 
  395.  
  396.    procedure Texture_name_hint ( 
  397.                                 o    : in out Object_3D; 
  398.                                 face :        Positive; 
  399.                                 name :        String 
  400.                                ); 
  401.    -- Indicate a texture's name that can be resolved later by Rebuild_links 
  402.  
  403.    procedure Portal_name_hint ( 
  404.                                o    : in out Object_3D; 
  405.                                face :        Positive; 
  406.                                name :        String 
  407.                               ); 
  408.    -- Indicate a portal's name that can be resolved later by Rebuild_links 
  409.  
  410.    procedure Rebuild_links ( 
  411.                             o            : in out Object_3D'Class; -- object to be relinked 
  412.                             neighbouring :        Map_of_Visuals;  -- neighbourhood 
  413.                             tolerant_obj :        Boolean;         -- tolerant on missing objects 
  414.                             tolerant_tex :        Boolean          -- tolerant on missing textures 
  415.                            ); 
  416.    -- Does nothing when texture or object name is empty 
  417.    Portal_connection_failed : exception; 
  418.  
  419.    bad_vertex_number, duplicated_vertex, 
  420.    duplicated_vertex_location : exception; 
  421.    point_unmatched, too_many_adjacences : exception; 
  422.    bad_edge_number : exception; 
  423.  
  424.    overriding procedure Pre_calculate (o : in out Object_3D); 
  425.    -- Done automatically at first display, but sometimes 
  426.    -- it's better to do it before : operation can be long! 
  427.  
  428.    ------------------------------------------------------------ 
  429.    -- Display of a whole scene, viewed from a certain object -- 
  430.    ------------------------------------------------------------ 
  431.  
  432.    overriding procedure Display ( 
  433.                                  o           : in out Object_3D; 
  434.                                  clip        :        Clipping_data 
  435.                                 ); 
  436.    -- - "out" for o because object might be pre_calculated if not yet 
  437.    -- - clip: 
  438.    --     allows to cull rendering of neighbouring objects that are not 
  439.    --     visible from current point of view; also avoids infinite 
  440.    --     recursion in case of mutually connected objects. 
  441.    -- - neighbouring objects being drawn more than once, e.g. two parts 
  442.    --     visible through two portals, is admissible with adequate clipping. 
  443.  
  444.    -------------------------------- 
  445.    -- Display of a single object -- 
  446.    -------------------------------- 
  447.  
  448.    procedure Display_one (o : in out Object_3D); 
  449.    -- Display only this object and not connected objects 
  450.    -- "out" for o because object might be pre_calculated if not yet 
  451.  
  452.    -- Abstract windowing management 
  453.    -- 
  454.  
  455.    type Window is abstract tagged 
  456.       record 
  457.          Camera  : aliased GLOBE_3D.Camera; 
  458.       end record; 
  459.  
  460.    type p_Window is access all Window'Class; pragma No_Strict_Aliasing (p_Window); 
  461.  
  462.    procedure Enable  (Self       : in out Window) is abstract; 
  463.    procedure Freshen (Self       : in out Window; 
  464.                       time_Step  :        GLOBE_3D.Real; 
  465.                       Extras     :        GLOBE_3D.Visual_array := GLOBE_3D.null_Visuals) is abstract; 
  466.  
  467.    -- Exceptions 
  468.    -- 
  469.  
  470.    Missing_level_data  : exception; 
  471.    Missing_global_data : exception; 
  472.  
  473.    Missing_texture : exception; 
  474.    Missing_object  : exception; 
  475.  
  476.    zero_normal : exception; 
  477.    zero_summed_normal : exception; 
  478.    zero_averaged_normal : exception; 
  479.  
  480.    -------------- 
  481.    -- Lighting -- 
  482.    -------------- 
  483.  
  484.    subtype Light_count is Natural range 0 .. 8; 
  485.    -- GL supports up to 8 sources. 
  486.    subtype Light_ident is Light_count range 1 .. Light_count'Last; 
  487.  
  488.    type Light_definition is record 
  489.       position, ambient, diffuse, specular : GL.Light_Float_vector; 
  490.    end record; 
  491.  
  492.    procedure Define (which : Light_ident; as : Light_definition); 
  493.  
  494.    procedure Switch_lights (on : Boolean); 
  495.    procedure Switch_light (which : Light_ident; on : Boolean); 
  496.  
  497.    procedure Reverse_light_switch (which : Light_ident); 
  498.  
  499.    function Is_light_switched (which : Light_ident) return Boolean; 
  500.  
  501.    ---------- 
  502.    -- Misc -- 
  503.    ---------- 
  504.  
  505.    function Image (r : Real) return String; 
  506.  
  507.    function Coords (p : Point_3D) return String; 
  508.  
  509.    procedure Angles_modulo_360 (v : in out Vector_3D); 
  510.  
  511.    -------------------------------- 
  512.    -- Free heap - allocated memory -- 
  513.    -------------------------------- 
  514.  
  515.    procedure Dispose is 
  516.      new Ada.Unchecked_Deallocation (Point_3D_array, p_Point_3D_array); 
  517.  
  518.    procedure Dispose is 
  519.      new Ada.Unchecked_Deallocation (Face_array, p_Face_array); 
  520.  
  521.    --------------------------------------------------------------- 
  522.    -- Trash : provisory variables for some development checkings -- 
  523.    --------------------------------------------------------------- 
  524.  
  525.    -- info_?_ .. .  : ?= letter; change letter to clean - up debug infos 
  526.  
  527.    info_b_real1, 
  528.    info_b_real2 : Real := 123.0; 
  529.    info_b_vect  : Vector_3D := (others => 123.0); 
  530.    info_b_bool1, 
  531.    info_b_bool2 : Boolean := False; 
  532.    info_b_clip  : Clipping_area := (0, 0, 0, 0); 
  533.    info_b_pnt   : array (0 .. 4) of Point_3D := (others => (others => 123.0)); 
  534.    info_b_ntl1, 
  535.    info_b_ntl2, 
  536.    info_b_ntl3  : Natural := 0; 
  537.    info_b_str1  : Ada.Strings.Unbounded.Unbounded_String := 
  538.      Ada.Strings.Unbounded.Null_Unbounded_String; 
  539.  
  540. private 
  541.  
  542.    type p_String is access String; 
  543.  
  544.    type Face_invariant_type is record 
  545.       P_compact    : Idx_4_array; 
  546.       -- indices of the edges (anticlockwise), 
  547.       -- in compact range  : 1 .. 3 for triangle 
  548.       last_edge    : Edge_count; 
  549.       UV_extrema   : Map_idx_pair_4_array; 
  550.       -- mapping of texture edges according to an eventual 
  551.       -- 0 in P (triangle). Compact range  : 1 .. 3 for triangle 
  552.       normal       : Vector_3D; 
  553.       blending     : Boolean; -- is any alpha < 1 ? 
  554.       connect_name : Ident := empty; 
  555.       -- ^ Used for loading connected objects. 
  556.       --   When the object group has been loaded, that name is set; 
  557.       --   the face (f).connecting accesses can be resolved using 
  558.       --   the face_invariant (f).connect_name . 
  559.       texture_name : Ident := empty; 
  560.       -- ^ face (f).texture must be resolved using 
  561.       --   face_invariant (f).texture_name . 
  562.       portal_seen  : Boolean := False; 
  563.       -- ^ always False, except during Display to avoid possible infinite 
  564.       --   recursion; reset to False at the end of Display. 
  565.    end record; 
  566.  
  567.    -- A few global variables - shocking! Don't look, it's private here : - ) 
  568.  
  569.    -- Name of Zip archives containing the Level / Global data 
  570.    -- If an item is not found in the level data, it is 
  571.    -- searched in the global one 
  572.    level_data_name   : Ada.Strings.Unbounded.Unbounded_String := 
  573.      Ada.Strings.Unbounded.To_Unbounded_String ("*undefined_level_data*"); 
  574.    global_data_name  : Ada.Strings.Unbounded.Unbounded_String := 
  575.      Ada.Strings.Unbounded.To_Unbounded_String ("*undefined_global_data*"); 
  576.  
  577.    -- Corresponding zip file infos for quick search 
  578.    zif_level, zif_global : Zip.Zip_info; 
  579.  
  580.    procedure Load_if_needed (zif : in out Zip.Zip_info; name : String); 
  581.  
  582.    -- General support functions available to child packages . .. 
  583.    -- 
  584.  
  585.    -- blending support 
  586.    -- 
  587.    function Is_to_blend (m : GL.Double)                  return Boolean; 
  588.    function Is_to_blend (m : GL.C_Float)                 return Boolean; 
  589.    function Is_to_blend (m : GL.Material_Float_vector)   return Boolean; 
  590.    function Is_to_blend (m : GL.Materials.Material_type) return Boolean; 
  591.  
  592.    -- material support 
  593.    -- 
  594.    procedure Set_Material (m : GL.Materials.Material_type); 
  595.  
  596.    -- Maps of Visuals - quick dictionary search 
  597.    -- 
  598.    package Visuals_Mapping is new Ada.Containers.Hashed_Maps 
  599.      (Key_Type        => Ada.Strings.Unbounded.Unbounded_String, 
  600.       Element_Type    => p_Visual, 
  601.       Hash            => Ada.Strings.Unbounded.Hash, 
  602.       Equivalent_Keys => Ada.Strings.Unbounded."="); 
  603.  
  604.    type Map_of_Visuals is new Visuals_Mapping.Map with null record; 
  605.  
  606. end GLOBE_3D;