Przeglądaj źródła

Rendering is now fast, but not very nice.
IVideoDataSource needs access to IntPtr to vertexBuffer and Elements cant draw themselves.
Needs some more refactoring, but works ok.

Daniel Kauth 11 lat temu
rodzic
commit
bc9accdbe8

+ 4 - 1
bbiwarg/DataSource/IVideoDataSource.cs

@@ -78,6 +78,9 @@ namespace bbiwarg.DataSource
         Vector[] getFingerTipPositions3D(uint handIndex);
         Vector[] getFingerTipPositions2D(uint handIndex);
         HandSide getHandSide(uint handIndex);
-        VertexArray getVertexArray();
+        void createVertexArray();
+        
+        //TODO: implement properly
+        void setVertexBuffer(IntPtr vertexBuffer);
     }
 }

+ 28 - 14
bbiwarg/DataSource/IisuDataSource.cs

@@ -43,6 +43,9 @@ namespace bbiwarg.DataSource
         private int width;
         private int height;
 
+        //TODO
+        private IntPtr vertexBuffer;
+
         /*
          * Creates an Iisu data source.
          * params:
@@ -129,7 +132,7 @@ namespace bbiwarg.DataSource
         {
             device.Start();
             updateFrame();
-        }
+         }
 
         public void stop()
         {
@@ -356,28 +359,21 @@ namespace bbiwarg.DataSource
             }
         }
 
-        public VertexArray getVertexArray()
+        public void createVertexArray()
         {
-            float[] vertexData = new float[3 * width * height];
-            Color[] colors = new Color[width * height];
-
             int index = 0;
             for (int x = 0; x < width; x++)
             {
                 for (int y = 0; y < height; y++)
                 {
                     int depth = currentImage.getDepth(x, y);
-                    create3DVertexFrom2D(x, y, depth, vertexData, 3 * index);
-                    colors[index] = currentImage.getColor(x, y);
-
+                    create3DVertexFrom2D(x, y, depth, index, currentImage.getColor(x, y));
                     index++;
                 }
             }
-    
-            return new VertexArray(vertexData, colors);
         }
 
-        private void create3DVertexFrom2D(float pixelX, float pixelY, int depth, float[] vertexData, int index)
+        private void create3DVertexFrom2D(float pixelX, float pixelY, int depth, int index, Color c)
         {
             float convertedDepth = depth / 1000f; // mm into m
 
@@ -391,9 +387,27 @@ namespace bbiwarg.DataSource
             float x = relX * z;
             float y = relY * z;
 
-            vertexData[index + 0] = x;
-            vertexData[index + 1] = y;
-            vertexData[index + 2] = z;
+            int i4 = (3 * sizeof(float) + 4 * sizeof(byte)) / sizeof(float) * index;
+            int i16 = (3 * sizeof(float) + 4 * sizeof(byte)) * index;
+            unsafe
+            {
+                byte* vertexArrayB = (byte*)vertexBuffer.ToPointer();
+                float* vertexArrayF = (float*)vertexBuffer.ToPointer();
+
+                vertexArrayF[i4 + 0] = x;
+                vertexArrayF[i4 + 1] = y;
+                vertexArrayF[i4 + 2] = -z;
+
+                vertexArrayB[i16 + 12] = c.R;
+                vertexArrayB[i16 + 13] = c.G;
+                vertexArrayB[i16 + 14] = c.B; 
+                vertexArrayB[i16 + 15] = c.A; 
+            }
+        }
+
+        public void setVertexBuffer(IntPtr vertexBuffer)
+        {
+            this.vertexBuffer = vertexBuffer;
         }
     }
 }

+ 110 - 187
bbiwarg/Graphics/Output.cs

@@ -1,223 +1,146 @@
-using System;
+using System;
 using System.Collections.Generic;
-using System.Diagnostics;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using OpenTK;
-using OpenTK.Graphics.OpenGL;
-using MathNet.Numerics.LinearAlgebra.Single;
-using bbiwarg.DataSource;
-
-
-namespace bbiwarg.Graphics
-{
-    class Output : GameWindow
-    {
-        private IVideoDataSource source;
-        private Point[] depthPixels;
-        private ImageData currentImage;
-
-        private List<IGraphicElement> graphicElements = new List<IGraphicElement>();
-        private int VBOid = new int();
-        private int IBOid = new int();
-        private float[] vertices = new float[0];
-        private uint[] triangles = new uint[0];
-
-        private Point palmPoint;
-        private Point[] fingerPoints;
-
-
-        public Output(IVideoDataSource source)
-        {
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using OpenTK;
+using OpenTK.Graphics.OpenGL;
+using MathNet.Numerics.LinearAlgebra.Single;
+using bbiwarg.DataSource;
+
+
+namespace bbiwarg.Graphics
+{
+    class Output : GameWindow
+    {
+        private IVideoDataSource source;
+        
+        private uint imageBufferId, pointBufferId;
+
+        public Output(IVideoDataSource source)
+        {
             this.source = source;
-            currentImage = source.getImageData();
-        }
-
-        protected override void OnLoad(EventArgs e)
-        {
-            base.OnLoad(e);
-            Title = "OutputTest";
+        }
+
+        protected override void OnLoad(EventArgs e)
+        {
+            base.OnLoad(e);
+            Title = "OutputTest";
             GL.ClearColor(Color.Black);
 
-            initializeDepthPixels();
-            //initBuffers();
-        }
-
-        protected override void OnRenderFrame(FrameEventArgs e)
-        {
-            base.OnRenderFrame(e);
-            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
-            Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, -Vector3.UnitZ, Vector3.UnitY);
-            GL.MatrixMode(MatrixMode.Modelview);
+            initBuffers();
+        }
+
+        protected override void OnRenderFrame(FrameEventArgs e)
+        {
+            base.OnRenderFrame(e);
+            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
+            Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, -Vector3.UnitZ, Vector3.UnitY);
+            GL.MatrixMode(MatrixMode.Modelview);
             GL.LoadMatrix(ref modelview);
 
-            source.releaseFrame();
+            source.releaseFrame();
             source.updateFrame();
-            currentImage = source.getImageData();
 
-            updateDepthPixels();
+            Stopwatch sw = new Stopwatch();
+            sw.Start();
 
-            foreach (IGraphicElement graphicElement in graphicElements) {
-                graphicElement.draw();
-            }
-
-            //updateBuffer();
-            //drawBuffer();
-
-            SwapBuffers();
-        }
-
-        protected override void OnResize(EventArgs e)
-        {
-            base.OnResize(e);
-            GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
-            Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 3, Width / (float)Height, 0.01f, 3.0f);
-            GL.MatrixMode(MatrixMode.Projection);
-            GL.LoadMatrix(ref projection);
-        }
+            GL.EnableClientState(ArrayCap.VertexArray);
+            GL.EnableClientState(ArrayCap.ColorArray);
 
-        private void initializeDepthPixels()
-        {
-            VertexArray vertexArray = source.getVertexArray();
-            int numVertices = vertexArray.getNumVertices();
-            depthPixels = new Point[numVertices];
-
-            float size = 0.002f;
-            for (int i = 0; i < numVertices; i++) {
-                Vertex vertex = vertexArray.getVertex(i);
-                Color color = vertexArray.getColor(i);
-                Point pixel = new Point(vertex, color, size);
-                depthPixels[i] = pixel;
-                graphicElements.Add(pixel);
-            }
+            GL.BindBuffer(BufferTarget.ArrayBuffer, imageBufferId);
+            source.setVertexBuffer(GL.MapBuffer(BufferTarget.ArrayBuffer, BufferAccess.WriteOnly));
+            source.createVertexArray();
+            GL.UnmapBuffer(BufferTarget.ArrayBuffer);
 
-            Vector palmPosition = source.getPalmPosition3D(1);
-            Vertex palmVertex = new Vertex(palmPosition[0], palmPosition[2], palmPosition[1]);
-            palmPoint = new Point(palmVertex, Color.Yellow, 0.005f);
-            graphicElements.Add(palmPoint);
+            GL.VertexPointer(3, VertexPointerType.Float, 3 * sizeof(float) + 4 * sizeof(byte), IntPtr.Zero);
+            GL.ColorPointer(4, ColorPointerType.UnsignedByte, 3 * sizeof(float) + 4 * sizeof(byte), 3 * sizeof(float));
 
-            fingerPoints = new Point[5];
-            for (int i = 0; i < 5; i++)
-            {
-                fingerPoints[i] = new Point(new Vertex(0f, 0f, 0f), Color.Yellow, 0.005f);
-            }
-        }
+            ImageData data = source.getImageData();
 
-        private void updateDepthPixels()
-        {
-            VertexArray vertexArray = source.getVertexArray();
-            int numVertices = vertexArray.getNumVertices();
+            GL.PointSize(3.0f);
+            GL.DrawArrays(PrimitiveType.Points, 0, data.getHeight() * data.getWidth());
 
-            for (int i = 0; i < numVertices; i++)
-            {
-                depthPixels[i].position = vertexArray.getVertex(i);
-                depthPixels[i].color = vertexArray.getColor(i);
-            }
-            Vector palmPosition = source.getPalmPosition3D(1);
-            palmPoint.position.x = palmPosition[0];
-            palmPoint.position.y = palmPosition[2];
-            palmPoint.position.z = palmPosition[1];
 
+            // draw points
+            float[] pointData;
             
-            Vector[] fingerPositions = source.getFingerTipPositions3D(1);
             DetectionStatus[] fingerStatus = source.getFingerStatus(1);
-            for(int i=0; i<5; i++) {
-                if(fingerStatus[i] == DetectionStatus.Tracked) {
-                   fingerPoints[i].position.x = fingerPositions[i][0];
-                   fingerPoints[i].position.y = fingerPositions[i][2];
-                   fingerPoints[i].position.z = fingerPositions[i][1];
-                } 
-                else if(fingerStatus[i] == DetectionStatus.Detected) {
-                    graphicElements.Add(fingerPoints[i]);
-                    fingerPoints[i].position.x = fingerPositions[i][0];
-                    fingerPoints[i].position.y = fingerPositions[i][2];
-                    fingerPoints[i].position.z = fingerPositions[i][1];
-                }
-                else if(fingerStatus[i] == DetectionStatus.Inactive && graphicElements.IndexOf(fingerPoints[i]) > -1) {
-                    graphicElements.Remove(fingerPoints[i]);
-                }
+            int numFingersDetected = 0;
+            for (int i = 0; i < fingerStatus.Length; ++i)
+            {
+                if (fingerStatus[i] == DetectionStatus.Detected || fingerStatus[i] == DetectionStatus.Tracked)
+                    ++numFingersDetected;
             }
 
-            
-        }
-
-        private void initBuffers()
-        {
-            GL.EnableClientState(ArrayCap.VertexArray);
-
-            GL.GenBuffers(1, out VBOid);
-            GL.GenBuffers(1, out IBOid);
-
-            GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid);
-            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StreamDraw);
-            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
-
+            pointData = new float[(4 + 3) * (1 + numFingersDetected)];
+            Color y = Color.Yellow;
+            Vector palmPosition = source.getPalmPosition3D(1);
 
-            GL.BindBuffer(BufferTarget.ElementArrayBuffer, IBOid);
-            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(triangles.Length * sizeof(int)), triangles, BufferUsageHint.StaticDraw);
-            GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
-        }
+            pointData[0] = palmPosition[0];
+            pointData[1] = palmPosition[2];
+            pointData[2] = -palmPosition[1];
 
-        public void updateBuffer()
-        {
-            List<float> verticesData = new List<float>();
-            List<uint> triangleData = new List<uint>();
+            pointData[3] = y.R / 255.0f;
+            pointData[4] = y.G / 255.0f;
+            pointData[5] = y.B / 255.0f;
+            pointData[6] = y.A / 255.0f;
 
-            foreach (IGraphicElement graphicElement in graphicElements)
+            int index = 7;
+            Vector[] fingerPositions = source.getFingerTipPositions3D(1);
+            for (int i = 0; i < fingerStatus.Length; ++i)
             {
-                List<Vector> elementVertices = graphicElement.getVertices();
-                uint[] elementTriangles = graphicElement.getTriangleIndices();
-                Color elementColor = graphicElement.getColor();
-
-                uint c = (uint)verticesData.Count / 6;
-                foreach (Vector elementVertex in elementVertices)
-                {
-                    verticesData.AddRange(convertColor(elementColor));
-                    verticesData.AddRange(elementVertex);
-                }
-                for (int i = 0; i < elementTriangles.Length; i++)
+                if (fingerStatus[i] == DetectionStatus.Detected || fingerStatus[i] == DetectionStatus.Tracked)
                 {
-                    triangleData.Add(elementTriangles[i] + c);
+                    pointData[index + 0] = fingerPositions[i][0];
+                    pointData[index + 1] = fingerPositions[i][2];
+                    pointData[index + 2] = -fingerPositions[i][1];
+
+                    pointData[index + 3] = y.R / 255.0f;
+                    pointData[index + 4] = y.G / 255.0f;
+                    pointData[index + 5] = y.B / 255.0f;
+                    pointData[index + 6] = y.A / 255.0f;
+                    index += 7;
                 }
             }
 
-            vertices = verticesData.ToArray();
-            triangles = triangleData.ToArray();
-
-
-            GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid);
-            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StreamDraw);
             GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
+            GL.BindBuffer(BufferTarget.ArrayBuffer, pointBufferId);
+            GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(pointData.Length * sizeof(float)), pointData, BufferUsageHint.DynamicDraw);
+            GL.VertexPointer(3, VertexPointerType.Float, (4 + 3) * sizeof(float), IntPtr.Zero);
+            GL.ColorPointer(4, ColorPointerType.Float, (4 + 3) * sizeof(float), 3 * sizeof(float));
 
-            GL.BindBuffer(BufferTarget.ElementArrayBuffer, IBOid);
-            GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(triangles.Length * sizeof(int)), triangles, BufferUsageHint.StaticDraw);
-            GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
-
-        }
-
-        private void drawBuffer()
-        {
-            GL.BindBuffer(BufferTarget.ArrayBuffer, VBOid);
-            GL.BindBuffer(BufferTarget.ElementArrayBuffer, IBOid);
+            GL.PointSize(10f);
+            GL.DrawArrays(PrimitiveType.Points, 0, pointData.Length / (4 + 3));
 
-            GL.InterleavedArrays(InterleavedArrayFormat.C3fV3f, 0, IntPtr.Zero);
-            GL.DrawElements(BeginMode.Triangles, triangles.Length, DrawElementsType.UnsignedInt, 0);
+            sw.Stop();
+            Console.WriteLine(sw.ElapsedMilliseconds);
 
-            GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
-            GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
+            SwapBuffers();
         }
 
-        private List<float> convertColor(Color color)
+        protected override void OnResize(EventArgs e)
         {
-            List<float> result = new List<float>();
-            result.Add(color.R / 255f);
-            result.Add(color.G / 255f);
-            result.Add(color.B / 255f);
-            return result;
+            base.OnResize(e);
+            GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
+            Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 3, Width / (float)Height, 0.01f, 3.0f);
+            GL.MatrixMode(MatrixMode.Projection);
+            GL.LoadMatrix(ref projection);
         }
 
-        
-    }
-}
+        private void initBuffers()
+        {
+            GL.GenBuffers(1, out imageBufferId);
+            GL.GenBuffers(1, out pointBufferId);
+
+            ImageData data = source.getImageData();
+
+            GL.BindBuffer(BufferTarget.ArrayBuffer, imageBufferId);
+            GL.BufferData(BufferTarget.ArrayBuffer, 
+                          (IntPtr)((3 * sizeof(float) + 4  * sizeof(byte)) * data.getWidth() * data.getHeight()), 
+                          IntPtr.Zero, BufferUsageHint.StreamDraw);
+        } 
+    }
+}

+ 1 - 0
bbiwarg/bbiwarg.csproj

@@ -21,6 +21,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>