private static ThreadGroup StartCPU(DataType type, HeadsetModel headset, ElectrodePattern pattern, ElectrodeLayout layout, string path) { // declare colour matrix and electrodes (if needed) var matrix = new Color[headset.GetWidth(), headset.GetHeight()]; var electrodes = type == DataType.Phosphene ? pattern.GetElectrodePositions(layout) : default; // setup threadGroup var threadGroup = new ThreadGroup(); threadGroup.OnAllThreadsFinished += () => { EditorCallback.InvokeOnMainThread(() => { var asset = headset.CreateTexture(); asset.SetPixels(matrix.Flatten(false, true, true)); asset.Apply(); SaveAsset(asset, path); }); }; // generate the texture asynchronously threadGroup.ProcessArray(headset.GetWidth(), (i) => { var n = headset.GetHeight(); for (int j = 0; j < n; j++) { switch (type) { case DataType.Phosphene: matrix[i, j] = PhospheneMatrix.CalculatePoint(i, j, headset, electrodes).ToColour(); matrix[i, j] = AddRandomSeeds(matrix[i, j]); break; case DataType.Axon: matrix[i, j] = AxonMatrix.CalculatePoint(i, j, headset).Colour; break; } } }); // provide caller with threadGroup for completion statistics return(threadGroup); }
public static Texture2D CreateTexture(this HeadsetModel headset) { var texture = new Texture2D(headset.GetWidth(), headset.GetHeight(), TextureFormat.RGBAFloat, false, true) { anisoLevel = 0, filterMode = FilterMode.Point }; return(texture); }
/// <summary> /// Pixel (i, j) -> Visual Angle (um) /// </summary> public static Vector2 PixelToRetina(int i, int j, HeadsetModel headset) { var horizontalDiameter = headset.GetRetinalDiameter(Axis.Horizontal); var verticalDiameter = headset.GetRetinalDiameter(Axis.Vertical); var x = ((float)i / headset.GetWidth() - .5f) * horizontalDiameter; var y = ((float)j / headset.GetHeight() - .5f) * verticalDiameter; return(new Vector2(x, y)); }
/// <summary> /// Retinal position (um) -> Pixel (i, j) /// </summary> public static Vector2 RetinaToPixel(Vector2 retina, HeadsetModel headset) { var horizontalDiameter = headset.GetRetinalDiameter(Axis.Horizontal); var verticalDiameter = headset.GetRetinalDiameter(Axis.Vertical); var x = (retina.x / horizontalDiameter + .5f) * headset.GetWidth(); var y = (retina.y / verticalDiameter + .5f) * headset.GetHeight(); return(new Vector2(x, y)); }
void OnGUI() { UnityGUI.Header("Coordinates"); headset = UnityGUI.Enum("Headset", headset); UnityGUI.Space(); UnityGUI.BeginHorizontal(); UnityGUI.Label(" ", "X", UnityGUI.BoldLabel); UnityGUI.Label("Y", UnityGUI.BoldLabel); UnityGUI.EndHorizontal(); UnityGUI.BeginHorizontal(); UnityGUI.Label("Resolution", headset.GetWidth().ToString()); UnityGUI.Label(headset.GetHeight().ToString()); UnityGUI.EndHorizontal(); UnityGUI.BeginHorizontal(); UnityGUI.Label("Field of View", ((int)headset.GetFieldOfView(Axis.Horizontal)).ToString()); UnityGUI.Label(((int)headset.GetFieldOfView(Axis.Vertical)).ToString()); UnityGUI.EndHorizontal(); UnityGUI.BeginHorizontal(); UnityGUI.Label("Diameter (um)", ((int)headset.GetRetinalDiameter(Axis.Horizontal)).ToString()); UnityGUI.Label(((int)headset.GetRetinalDiameter(Axis.Vertical)).ToString()); UnityGUI.EndHorizontal(); UnityGUI.Space(); Draw("Pixel", ref pixel); Draw("Visual Angle", ref angle); Draw("Retina (um)", ref retina); Draw("Polar", ref polar); UnityGUI.Separator(); UnityGUI.Header("Electrode Count"); UnityGUI.BeginChangeCheck(); pattern = UnityGUI.Enum("Pattern", pattern); layout = UnityGUI.Enum("Layout", layout); fieldOfView = UnityGUI.Float("Field of View", fieldOfView); var changed = UnityGUI.EndChangeCheck(); if (changed) { numElectrodes = pattern.GetElectrodePositions(layout, fieldOfView).Length; } UnityGUI.Space(); UnityGUI.Label("Electode Count", numElectrodes.ToString()); }
public static RenderTexture CreateRenderTexture(this HeadsetModel headset) { var texture = new RenderTexture(headset.GetWidth(), headset.GetHeight(), 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear) { anisoLevel = 0, antiAliasing = 1, enableRandomWrite = true, filterMode = FilterMode.Point }; texture.Create(); return(texture); }
/* * Public methods */ public static AxonPoint[,] CalculateMatrix(HeadsetModel headset) { var width = headset.GetWidth(); var height = headset.GetHeight(); var matrix = new AxonPoint[width, height]; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { matrix[i, j] = CalculatePoint(i, j, headset); } } return(matrix); }
public static Vector2[,] CalculateMatrix(HeadsetModel headset, Vector2[] electrodes) { var width = headset.GetWidth(); var height = headset.GetHeight(); var matrix = new Vector2[width, height]; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { matrix[i, j] = CalculatePoint(i, j, headset, electrodes); } } return(matrix); }
/* * Private methods */ private static void StartGPU(DataType type, HeadsetModel headset, ElectrodePattern pattern, ElectrodeLayout layout, string path) { var shader = LoadAsset <ComputeShader>($"{type}"); var kernel = shader.FindKernel("CSMain"); var electrodeBuffer = default(ComputeBuffer); if (type == DataType.Phosphene) { var electrodes = pattern.GetElectrodePositions(layout); electrodeBuffer = new ComputeBuffer(electrodes.Length, sizeof(float) * 2); electrodeBuffer.SetData(electrodes); shader.SetBuffer(kernel, "_electrodes", electrodeBuffer); } var texture = headset.CreateRenderTexture(); shader.SetTexture(kernel, "_result", texture); shader.SetVector("_headset_diameter", headset.GetRetinalDiameter()); shader.SetVector("_headset_resolution", headset.GetResolution()); shader.Dispatch(kernel, headset.GetWidth() / 8, headset.GetHeight() / 8, 1); electrodeBuffer?.Dispose(); Texture2D asset = texture.ToTexture2D(TextureFormat.RGBAFloat, true); texture.Release(); asset.anisoLevel = 0; asset.filterMode = FilterMode.Point; if (type == DataType.Phosphene) { AddRandomSeeds(asset); } SaveAsset(asset, path); }
public static float GetAspectRatio(this HeadsetModel headset) { return((float)headset.GetWidth() / headset.GetHeight()); }
public override void GetDimensions(out int width, out int height) { width = headset.GetWidth(); height = headset.GetHeight(); }