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