/// <summary>
        ///
        /// </summary>
        /// <param name="control"></param>
        public override void Load(Control control)
        {
            base.Load(control);

            camera = new PerspectiveCamera(27, control.Width / (float)control.Height, 5, 3500);
            this.camera.Position.Z = 2750;

            scene     = new Scene();
            scene.Fog = new Fog((Color)colorConvertor.ConvertFromString("#050505"), 2000, 3500);

            //

            const int Particles = 500000;

            var positions = new float[Particles * 3];
            var colors    = new float[Particles * 3];

            var n = 1000; var n2 = n / 2; // particles spread in the cube

            for (var i = 0; i < positions.Length; i += 3)
            {
                // positions

                var x = Mat.Random() * n - n2;
                var y = Mat.Random() * n - n2;
                var z = Mat.Random() * n - n2;

                positions[i + 0] = x;
                positions[i + 1] = y;
                positions[i + 2] = z;

                // colors

                var vx = (x / n) + 0.5f;
                var vy = (y / n) + 0.5f;
                var vz = (z / n) + 0.5f;

                colors[i + 0] = vx;
                colors[i + 1] = vy;
                colors[i + 2] = vz;
            }

            var geometry = new BufferGeometry();

            geometry.AddAttribute("position", new BufferAttribute <float>(positions, 3));
            geometry.AddAttribute("color", new BufferAttribute <float>(colors, 3));

            geometry.ComputeBoundingSphere();

            //

            var material = new PointCloudMaterial()
            {
                Size = 15, VertexColors = Three.VertexColors
            };

            particleSystem = new PointCloud(geometry, material);
            scene.Add(particleSystem);

            //

            renderer.SetClearColor(scene.Fog.Color);
        }
示例#2
0
        public override void Reset()
        {
            Active.ForEach(req =>
            {
                req.Readback.WaitForCompletion();
                req.TextureSet.Release();
            });
            Active.Clear();

            Jobs.ForEach(job => job.Complete());
            Jobs.Clear();

            foreach (var tex in AvailableRenderTextures)
            {
                tex.Release();
            }
            ;
            AvailableRenderTextures.Clear();

            foreach (var tex in AvailableTextures)
            {
                Destroy(tex);
            }
            ;
            AvailableTextures.Clear();

            if (PointCloudBuffer != null)
            {
                PointCloudBuffer.Release();
                PointCloudBuffer = null;
            }

            if (Points.IsCreated)
            {
                Points.Dispose();
            }

            AngleStart = 0.0f;
            // Assuming center of view frustum is horizontal, find the vertical FOV (of view frustum) that can encompass the tilted Lidar FOV.
            // "MaxAngle" is half of the vertical FOV of view frustum.
            if (VerticalRayAngles.Count == 0)
            {
                MaxAngle = Mathf.Abs(CenterAngle) + FieldOfView / 2.0f;

                StartLatitudeAngle = 90.0f + MaxAngle;
                //If the Lidar is tilted up, ignore lower part of the vertical FOV.
                if (CenterAngle < 0.0f)
                {
                    StartLatitudeAngle -= MaxAngle * 2.0f - FieldOfView;
                }
                EndLatitudeAngle = StartLatitudeAngle - FieldOfView;
            }
            else
            {
                LaserCount         = VerticalRayAngles.Count;
                StartLatitudeAngle = 90.0f - VerticalRayAngles.Min();
                EndLatitudeAngle   = 90.0f - VerticalRayAngles.Max();
                FieldOfView        = StartLatitudeAngle - EndLatitudeAngle;
                MaxAngle           = Mathf.Max(StartLatitudeAngle - 90.0f, 90.0f - EndLatitudeAngle);
            }

            float startLongitudeAngle = 90.0f + HorizontalAngleLimit / 2.0f;

            SinStartLongitudeAngle = Mathf.Sin(startLongitudeAngle * Mathf.Deg2Rad);
            CosStartLongitudeAngle = Mathf.Cos(startLongitudeAngle * Mathf.Deg2Rad);

            // The MaxAngle above is the calculated at the center of the view frustum.
            // Because the scan curve for a particular laser ray is a hyperbola (intersection of a conic surface and a vertical plane),
            // the vertical FOV should be enlarged toward left and right ends.
            float startFovAngle = CalculateFovAngle(StartLatitudeAngle, startLongitudeAngle);
            float endFovAngle   = CalculateFovAngle(EndLatitudeAngle, startLongitudeAngle);

            MaxAngle = Mathf.Max(MaxAngle, Mathf.Max(startFovAngle, endFovAngle));

            // Calculate sin/cos of latitude angle of each ray.
            if (SinLatitudeAngles.IsCreated)
            {
                SinLatitudeAngles.Dispose();
            }
            if (CosLatitudeAngles.IsCreated)
            {
                CosLatitudeAngles.Dispose();
            }
            SinLatitudeAngles = new NativeArray <float>(LaserCount, Allocator.Persistent);
            CosLatitudeAngles = new NativeArray <float>(LaserCount, Allocator.Persistent);


            int totalCount = LaserCount * MeasurementsPerRotation;

            PointCloudBuffer = new ComputeBuffer(totalCount, UnsafeUtility.SizeOf <Vector4>());
            PointCloudMaterial?.SetBuffer("_PointCloud", PointCloudBuffer);

            Points = new NativeArray <Vector4>(totalCount, Allocator.Persistent);

            CurrentLaserCount = LaserCount;
            CurrentMeasurementsPerRotation = MeasurementsPerRotation;
            CurrentFieldOfView             = FieldOfView;
            CurrentVerticalRayAngles       = new List <float>(VerticalRayAngles);
            CurrentCenterAngle             = CenterAngle;
            CurrentMinDistance             = MinDistance;
            CurrentMaxDistance             = MaxDistance;

            IgnoreNewRquests = 0;

            // If VerticalRayAngles array is not provided, use uniformly distributed angles.
            if (VerticalRayAngles.Count == 0)
            {
                float deltaLatitudeAngle = FieldOfView / LaserCount;
                int   index = 0;
                float angle = StartLatitudeAngle;
                while (index < LaserCount)
                {
                    SinLatitudeAngles[index] = Mathf.Sin(angle * Mathf.Deg2Rad);
                    CosLatitudeAngles[index] = Mathf.Cos(angle * Mathf.Deg2Rad);
                    index++;
                    angle -= deltaLatitudeAngle;
                }
            }
            else
            {
                for (int index = 0; index < LaserCount; index++)
                {
                    SinLatitudeAngles[index] = Mathf.Sin((90.0f - VerticalRayAngles[index]) * Mathf.Deg2Rad);
                    CosLatitudeAngles[index] = Mathf.Cos((90.0f - VerticalRayAngles[index]) * Mathf.Deg2Rad);
                }
            }

            int   count = Mathf.CeilToInt(HorizontalAngleLimit / (360.0f / MeasurementsPerRotation));
            float deltaLongitudeAngle = (float)HorizontalAngleLimit / (float)count;

            SinDeltaLongitudeAngle = Mathf.Sin(deltaLongitudeAngle * Mathf.Deg2Rad);
            CosDeltaLongitudeAngle = Mathf.Cos(deltaLongitudeAngle * Mathf.Deg2Rad);

            // Enlarged the texture by some factors to mitigate alias.
            RenderTextureHeight = 16 * Mathf.CeilToInt(2.0f * MaxAngle * LaserCount / FieldOfView);
            RenderTextureWidth  = 8 * Mathf.CeilToInt(HorizontalAngleLimit / (360.0f / MeasurementsPerRotation));

            // View frustum size at the near plane.
            float frustumWidth  = 2 * MinDistance * Mathf.Tan(HorizontalAngleLimit / 2.0f * Mathf.Deg2Rad);
            float frustumHeight = 2 * MinDistance * Mathf.Tan(MaxAngle * Mathf.Deg2Rad);

            XScale = frustumWidth / RenderTextureWidth;
            YScale = frustumHeight / RenderTextureHeight;

            // construct custom aspect ratio projection matrix
            // math from https://www.scratchapixel.com/lessons/3d-basic-rendering/perspective-and-orthographic-projection-matrix/opengl-perspective-projection-matrix

            float v = 1.0f / Mathf.Tan(MaxAngle * Mathf.Deg2Rad);
            float h = 1.0f / Mathf.Tan(HorizontalAngleLimit * Mathf.Deg2Rad / 2.0f);
            float a = (MaxDistance + MinDistance) / (MinDistance - MaxDistance);
            float b = 2.0f * MaxDistance * MinDistance / (MinDistance - MaxDistance);

            var projection = new Matrix4x4(
                new Vector4(h, 0, 0, 0),
                new Vector4(0, v, 0, 0),
                new Vector4(0, 0, a, -1),
                new Vector4(0, 0, b, 0));

            SensorCamera.nearClipPlane    = MinDistance;
            SensorCamera.farClipPlane     = MaxDistance;
            SensorCamera.projectionMatrix = projection;
        }