# CorgEng.UtilityTypes ## Contents [toc] ## Summary Utility types provide useful functionality to other modules. ## Batches Batches provide an efficient data structure for instanced rendering. Batches work similar to lists in that you can add and remove elements from them, however internally they are a list of arrays of a set size which can easilly be passed to openGL's drawInstanced call. Batches use bindable properties to automatically update if a value they reference is updated. ```csharp= int[] BatchVectorSizes { get; } ``` The size of the vectors in the batch. A value of { 3, 2, 1 } indicates that the batch stores 3 things: a vec3, a vec2 and a float. ```csharp= void Add(IBatchElement<Self> element) ``` Adds a batch element to the batch. ```csharp= void Remove(IBatchElement<Self> element) ``` Removes the specified element from the batch. ```csharp= void Update(int batchIndex, int groupIndex, Vector<float> newValue) ``` Updates a single property of the batch with a new value. Automatically called due to the usage of bindable properties, so shouldn't need to be called from outside. ```csharp= float[] GetArray(int batchIndex, int groupIndex) ``` Gets the array stored within the provided batch and group. Can be passed to glDrawArraysInstanced(); ### Batch Elements Holds information about what batch it contains as well as the value the element contains. Requires a bindable property in the constructor, and will automatically update the batch when that bindable property is altered. The only reason to keep a reference to a batch element is to remove it from the batch when it is no longer needed. ## Bindable Properties Bindable properties provide a way to create a property which will automatically trigger a callback when its value is changed. They are required for batches and rendering, since if the property of something changes (for example if a renderable object changes position) then the batch needs to be updated to reflect that change. ```csharp= IBindableProperty<float> bindableFloatProperty = new BindableProperty<float>(3.14f); bindableFloatProperty.ValueChanged += (object target, EventArgs args) => { Log.WriteLine("Beep!"); } Log.WriteLine(bindableFloatProperty.Value); bindableFloatProperty.Value = 4; Log.WriteLine(bindableFloatProperty.Value); ``` Result: ``` 3.14 Beep! 4 ``` ## Vectors Vectors provide a way of storing generic types together. ### Construction Creating a vector requires a type to be passed in via the generic type of the vector, as well as the initial values of the vector. The initial values will determine the vector's dimensions, so even if the vector is using the default type values, they should be passed in the constructor. ```csharp= //Numerical Types Vector<int> integerVector = new Vector<int>(0, 10, 6); //3 dimension vector Vector<float> floatVector = new Vector<float>(0.5f, 7.4f); //2 dimension vector //Odd types Vector<bool> booleanVector = new Vector<bool>(false); //1 dimension vector ``` ### Accessing #### Via Index ```csharp= Vector<int> pos = new Vector<int>(1, 2, 3, 6); //Get values Log.WriteLine(pos[0]); //1 Log.WriteLine(pos[1]); //2 Log.WriteLine(pos[2]); //3 Log.WriteLine(pos[3]); //6 //Set values pos[0] = 5; pos[2] = 8; ``` Vectors can be accessed similarly to arrays via an index. This can throw an index out of bounds exception if the vector is not of the same size. These can be used to set the values of the vector too. #### X, Y, Z Properties ```csharp= Vector<int> pos = new Vector<int>(1, 2, 3); //Get values Log.WriteLine(pos.X); //1 Log.WriteLine(pos.Y); //2 Log.WriteLine(pos.Z); //3 //Set values pos.X = 5; pos.Y = 10; pos.Z = -4; ``` Vectors can be accessed via the X, Y and Z properties which will return the 0th, 1st and 2nd element accordingly. Note that if the vector is less than 3 elements, an index out of bounds exception may be thrown. X, Y, Z are prefered over indexing for positional vectors as they provide cleaner code and are easier to read. The X,Y,Z properties can also be used to set the values of the vector. ### Vector Operations //TODO: !!Remove dynamic from vectors and use (T)(object) casting instead!! #### IgnoreZ Returns a 2 dimensional vector containing the X and Y of the current vector. Does not affect the original vector. #### SetZ Returns a 3 dimensional vector containing the X and Y of the current vector as well as a provided Z value. Does not affect the original vector. #### Copy Creates a copy of the original vector and returns it. > Why is this even needed when vectors are structs?? #### MoveTowards Moves the current vector towards a target vector with a set speed (in units per second) as well as the delta time of the last call (in seconds). Returns the new vector, and an out variable that indicates how much extra movement was lost due to reaching the target before fully completing a move. Extra distance will always be 0 unless the target position was reached, in which case it will indicate how much distance could have been moved had the target position been further away. Does not affect the original vector. #### DotProduct Performs the dot product of 2 vectors and returns it. #### Casting Vectors can be cast to Vector\<int>, Vector\<float>, Vector\<double> and Vector\<long>. When casting the type of the vector being cast must be able to be convertable to the new type. (integer can be converted to float, so you can cast a Vector\<int> to a Vector\<float>.) #### Length Returns the length of the vector using pythagorus' formula. The vector must be of a type that can be cast to dynamic. $$Length = \sqrt{v_1^2*v_2^2*...*v_n^2}$$