orka_b455160b/orka/src/orka/interface/orka-instances.ads

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
--  SPDX-License-Identifier: Apache-2.0
--
--  Copyright (c) 2018 onox <denkpadje@gmail.com>
--
--  Licensed under the Apache License, Version 2.0 (the "License");
--  you may not use this file except in compliance with the License.
--  You may obtain a copy of the License at
--
--      http://www.apache.org/licenses/LICENSE-2.0
--
--  Unless required by applicable law or agreed to in writing, software
--  distributed under the License is distributed on an "AS IS" BASIS,
--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
--  See the License for the specific language governing permissions and
--  limitations under the License.

with Ada.Containers.Indefinite_Holders;

with Orka.Rendering.Buffers.Mapped.Persistent;
with Orka.Types;

generic
   type Partition_Index_Type is mod <>;
package Orka.Instances is
   pragma Preelaborate;

   type Manager is tagged limited private;

   function Create_Manager (Capacity, Parts : Positive) return Manager;
   --  Return a manager that manages a persistent mapped buffer with
   --  Capacity * Parts transforms.

   type Cursor is private;

   function Add_Instance (Object : in out Manager) return Cursor
     with Pre  => Object.Length < Object.Capacity,
          Post => Object.Length'Old + 1 = Object.Length;

   procedure Remove_Instance (Object : in out Manager; Instance : Cursor)
     with Pre  => Object.Length > 0,
          Post => Object.Length'Old - 1 = Object.Length;

   procedure Set_Transform
     (Object   : in out Manager;
      Value    : Orka.Types.Singles.Matrix4;
      Instance : Cursor;
      Part     : Natural)
   with Pre => Part < Object.Parts;

   function Transforms (Object : Manager) return Rendering.Buffers.Bindable_Buffer'Class;

   function Parts (Object : Manager) return Positive;
   --  Return number of parts of each instance

   function Length (Object : Manager) return Natural;
   --  Return current number of instances

   function Capacity (Object : Manager) return Positive;
   --  Return maximum number of instances

   procedure Complete_Frame (Object : in out Manager);

private

   package PMB renames Rendering.Buffers.Mapped.Persistent;

   type Cursor is new Positive;

   subtype Instance is Positive;
   subtype Index is Positive;

   type Instance_Array is array (Index    range <>) of Instance;
   type Indices_Array  is array (Instance range <>) of Index;

   type Instances_Type (Capacity : Positive) is record
      Instances : Instance_Array (1 .. Capacity);
      Indices   : Indices_Array  (1 .. Capacity);
   end record;
   --  Instances is an array containing a contiguous number of instance
   --  ID's that have been added, followed by a contiguous number of ID's
   --  that have been removed. This array is used to quickly determine a
   --  free ID that can be returned by the function Add_Instance.
   --
   --  Indices is an array that is used to look up the position of an
   --  instance ID in Instances in O(1) time. Iterating over Instances
   --  would be an O(n) operation.
   --
   --  For example:
   --
   --  Instances:
   --
   --  1 3 4 | 2 5
   --  -----   ---
   --  added   removed
   --
   --  Indices:
   --
   --  1 4 2 3 5
   --
   --  To add an instance, the '|' is moved to the right and the ID next
   --  to it (2 in the example above) is returned.
   --
   --  To remove an instance, we look up the index of the instance and
   --  then swap its ID with the instance at the end of the array of
   --  added instances. Finally, we move the '|' to the left.
   --
   --  The indices of the two swapped instances are updated in Indices.
   --
   --  For example, given the above array, removing instance 1 results in:
   --
   --    4 3 | 1 2 5
   --    ---   -----
   --  added   removed

   package Instances_Holder is new Ada.Containers.Indefinite_Holders
     (Element_Type => Instances_Type);

   type Manager is tagged limited record
      Added : Natural := 0;
      --  Represents the '|' barrier between the added and removed instances

      Capacity, Parts : Positive;

      Instances : Instances_Holder.Holder;

      Transforms : PMB.Persistent_Mapped_Buffer
        (Kind => Orka.Types.Single_Matrix_Type,
         Mode => Rendering.Buffers.Mapped.Write);
   end record;

end Orka.Instances;