예제 #1
0
        void    AddObstacleSquare(float2 _P, float2 _D, float2 _radius)
        {
            float2 X = new float2(_D.x / _radius.x, _D.y / _radius.x);
            float2 Y = new float2(-_D.y / _radius.y, _D.x / _radius.y);

            float2 C = m_boxCenter - _P;

            C = new float2(C.Dot(X), C.Dot(Y));

            for (int i = 0; i < PIXELS_COUNT; i++)
            {
                float  angle = (float)(2.0 * Math.PI * i / PIXELS_COUNT);
                float2 wsV   = new float2((float)Math.Cos(angle), (float)Math.Sin(angle));
                float2 V     = new float2(wsV.Dot(X), wsV.Dot(Y));

                // Compute the intersection with the unit box centered in 0
                float  t0 = (C.x + Math.Sign(V.x)) / -V.x;
                float2 I0 = C + t0 * V;
                float2 N0 = new float2(-Math.Sign(V.x), 0.0f);
                if (Math.Abs(I0.y) > 1.0f)
                {
                    t0 = float.MaxValue;
                }

                float  t1 = (C.y + Math.Sign(V.y)) / -V.y;
                float2 I1 = C + t1 * V;
                float2 N1 = new float2(0.0f, -Math.Sign(V.y));
                if (Math.Abs(I1.x) > 1.0f)
                {
                    t1 = float.MaxValue;
                }

                float  t;                       // Math.Min( t0, t1 )
                float2 N;
                if (t0 < t1)
                {
                    t = t0;
                    N = N0;
                }
                else
                {
                    t = t1;
                    N = N1;
                }
                if (t < 0.0f || t > m_Pixels[i].Distance)
                {
                    continue;
                }

                float2 wsN = (N.x * _radius.x * _radius.x * X + N.y * _radius.y * _radius.y * Y).Normalized;

                m_Pixels[i].Distance = t;
                m_Pixels[i].Position = m_boxCenter + t * wsV;
                m_Pixels[i].Normal   = wsN;
            }
        }
예제 #2
0
        private void panelOutput_MouseMove(object sender, MouseEventArgs e)
        {
            // Transform mouse position into node space
            float2 mousePosition = Client2Pos(e.Location);
            float  nodeRadius    = 0.01f * 0.5f * (m_CB_Main.m._cameraSize.x + m_CB_Main.m._cameraSize.y);              // Radius adapts to camera size
            float  sqNodeRadius  = nodeRadius * nodeRadius;

            // Identify any node under the mouse
            m_SB_NodeSims[0].Read();

            m_displayText = null;
            m_CB_Main.m._hoveredNodeIndex = ~0U;
            for (int nodeIndex = 0; nodeIndex < m_nodesCount; nodeIndex++)
            {
                float2 nodePosition = m_SB_NodeSims[0].m[nodeIndex].m_position;
                float2 delta        = nodePosition - mousePosition;
                float  sqDistance   = delta.Dot(delta);
                if (sqDistance > sqNodeRadius)
                {
                    continue;
                }

                // Found it!
                ProtoParser.Neuron selectedNeuron = m_graph[nodeIndex];
                m_displayText          = selectedNeuron.m_name != null ? selectedNeuron.m_name : selectedNeuron.Parents[0].m_name + "()";
                m_selectedNodePosition = nodePosition;

                m_CB_Main.m._hoveredNodeIndex = (uint)nodeIndex;
                break;
            }

            m_CB_Main.UpdateData();
        }
예제 #3
0
        void    CheckCrash(float2 _oldPos)
        {
            for (int i = 0; i < m_landscape.Count - 1; i++)
            {
                float2 P0 = m_landscape[i];
                float2 P1 = m_landscape[i + 1];
                float2 D  = (P1 - P0).Normalized;
                float2 N  = new float2(-D.y, D.x);

                float2 Dir       = Pos - _oldPos;
                float  dirLength = Dir.Length;
                Dir *= dirLength != 0.0f ? 1.0f / dirLength : 0.0f;
                float hitDistance = (P0 - Pos).Dot(N) / Dir.Dot(N);
                if (hitDistance < 0.0f || hitDistance > dirLength)
                {
                    continue;                           // Outside our ship's trajectory
                }
                float2 HitPos = Pos + hitDistance * Dir;
//				float	dot = (HitPos - P0).Dot( N );	// Must be 0!
                if (HitPos.x < P0.x || HitPos.x > P1.x)
                {
                    continue;                           // Outside of landscape segment
                }
                if (Math.Abs(Vel.y) >= 40.0f)
                {
                    throw new Exception("Crash!");
                }
                else
                {
                    MessageBox.Show("SUCCESS!");
                }
            }
        }
예제 #4
0
파일: Form1.cs 프로젝트: vr3d/GodComplex
        void    AddObstacleRound(float2 _P, float2 _D, float2 _radius)
        {
            float2 X = new float2(_D.x / _radius.x, _D.y / _radius.x);
            float2 Y = new float2(-_D.y / _radius.y, _D.x / _radius.y);

            float2 C = m_boxCenter - _P;

            C = new float2(C.Dot(X), C.Dot(Y));

            for (int i = 0; i < PIXELS_COUNT; i++)
            {
                float  angle = (float)(2.0 * Math.PI * i / PIXELS_COUNT);
                float2 wsV   = new float2((float)Math.Cos(angle), (float)Math.Sin(angle));
                float2 V     = new float2(wsV.Dot(X), wsV.Dot(Y));

                // Compute the intersection with the unit circle centered in 0
                float c     = C.Dot(C) - 1.0f;
                float b     = C.Dot(V);
                float a     = V.Dot(V);
                float Delta = b * b - a * c;
                if (Delta < 0.0f)
                {
                    continue;
                }

                Delta = (float)Math.Sqrt(Delta);
                float t0 = (-b - Delta) / a;
                float t1 = (-b + Delta) / a;
                float t  = Math.Min(t0, t1);
                if (t < 0.0f || t > m_Pixels[i].Distance)
                {
                    continue;
                }

                float2 I   = C + t * V;                 // Hit in local space, also the normal
                float2 wsN = (I.x * _radius.x * _radius.x * X + I.y * _radius.y * _radius.y * Y).Normalized;

                m_Pixels[i].Distance = t;
                m_Pixels[i].Position = m_boxCenter + t * wsV;
                m_Pixels[i].Normal   = wsN;
            }
        }
예제 #5
0
파일: Form1.cs 프로젝트: vr3d/GodComplex
            // Cuts the interval with another plane
            public void             Cut(Plane _P)
            {
                float  ViewDist = m_Direction.Dot(_P.m_Normal);
                float2 D        = m_Position - _P.m_Position;
                float  Dist     = D.Dot(_P.m_Normal);
                float  t        = -Dist / ViewDist;

                if (ViewDist > 0.0f)
                {
                    m_Min = Math.Max(m_Min, t);
                }
                else
                {
                    m_Max = Math.Min(m_Max, t);
                }
            }
예제 #6
0
        private void panelOutput_MouseMove(object sender, MouseEventArgs e)
        {
            // Transform mouse position into node space
            float2 mousePosition = Client2Pos(e.Location);
            float  nodeRadius    = 0.01f * 0.5f * (m_CB_Main.m._cameraSize.x + m_CB_Main.m._cameraSize.y);              // Radius adapts to camera size
            float  sqNodeRadius  = nodeRadius * nodeRadius;

            // Identify any node under the mouse
            m_SB_Nodes.Read();

            m_displayText = null;
            m_CB_Main.m._hoveredNodeIndex = ~0U;
            for (int nodeIndex = 0; nodeIndex < m_nodesCount; nodeIndex++)
            {
                float2 nodePosition = m_SB_Nodes.m[nodeIndex].m_position;
                float2 delta        = nodePosition - mousePosition;
                float  sqDistance   = delta.Dot(delta);
                if (sqDistance > sqNodeRadius)
                {
                    continue;
                }

                // Found it!
                ProtoParser.Neuron selectedNeuron = m_graph[nodeIndex];
                if (selectedNeuron.m_name != null)
                {
                    m_displayText = selectedNeuron.m_name;
                }
                else
                {
                    m_displayText = "*" + selectedNeuron.Parents[0].m_name;
                }

                if (selectedNeuron.m_value is ProtoParser.NeuronValue)
                {
                    // Show value
                    m_displayText += "( ";
                    m_displayText += (selectedNeuron.m_value as ProtoParser.NeuronValue).m_valueMean != null ? (selectedNeuron.m_value as ProtoParser.NeuronValue).m_valueMean : "<null>";
                    m_displayText += " )";
                }

                // Show value
                if (radioButtonShowTemperature.Checked)
                {
                    m_SB_HeatSource.Read();
                    float heat = m_SB_HeatSource.m[m_nodesCount * integerTrackbarControlShowQuerySourceIndex.Value + m_neuron2ID[selectedNeuron]];
                    m_displayText += " = " + heat.ToString("G4");
                }
                else if (radioButtonShowBarycentrics.Checked)
                {
                    GetBarycentricsBuffer();
                    float heat = m_SB_HeatBarycentrics.m[m_nodesCount * integerTrackbarControlShowQuerySourceIndex.Value + m_neuron2ID[selectedNeuron]];
                    m_displayText += " = " + heat.ToString("G4");
                }
                else if (radioButtonShowResultsBarycentric.Checked)
                {
                    GetBarycentricsBuffer();
                    float heat = ComputeResult(m_neuron2ID[selectedNeuron]);
                    m_displayText += " = " + heat.ToString("G4");
                }
                else if (radioButtonShowResultsSum.Checked)
                {
                    float heatSum = GetSumBuffer().m[m_neuron2ID[selectedNeuron]];
                    m_displayText += " = " + heatSum.ToString("G4");
                }

                m_selectedNodePosition = nodePosition;

                m_CB_Main.m._hoveredNodeIndex = (uint)nodeIndex;
                break;
            }

            m_CB_Main.UpdateData();
        }
예제 #7
0
파일: Form1.cs 프로젝트: vr3d/GodComplex
        // Solves the best planes for the room
        void SolveRoom()
        {
            //////////////////////////////////////////////////////////////////////////
            // Use EM to obtain principal directions
            List <float3> directions = new List <float3>(PIXELS_COUNT);

            for (int i = 0; i < PIXELS_COUNT; i++)
            {
//				if ( m_Pixels[i].Distance < 1e3f )
                directions.Add(new float3(m_Pixels[i].Normal.x, m_Pixels[i].Normal.y, 0.0f));
            }

            int planesCount = integerTrackbarControlResultPlanesCount.Value;

            m_Planes = new Plane[planesCount];
            m_Lobes  = new FitLobe[planesCount];
            for (int i = 0; i < planesCount; i++)
            {
                m_Lobes[i] = new FitLobe();
            }
            PerformExpectationMaximization(directions.ToArray(), m_Lobes, 1000, 1e-6);

            for (int i = 0; i < planesCount; i++)
            {
                m_Planes[i].m_Weight = (float)m_Lobes[i].Alpha;
            }


            //////////////////////////////////////////////////////////////////////////
            // Remove similar planes
            for (int i = 0; i < planesCount - 1; i++)
            {
                FitLobe P0 = m_Lobes[i];
                if (m_Planes[i].m_Dismissed)
                {
                    continue;                           // Already dismissed...
                }
                float3 averageDirection = (float)P0.Alpha * P0.Direction;
                double maxKappa         = P0.Concentration;
                for (int j = i + 1; j < planesCount; j++)
                {
                    FitLobe P1 = m_Lobes[j];
                    if (m_Planes[j].m_Dismissed)
                    {
                        continue;                               // Already dismissed...
                    }
                    float dot = P0.Direction.Dot(P1.Direction);
                    if (dot < floatTrackbarControlSimilarPlanes.Value)
                    {
                        continue;
                    }

                    averageDirection += (float)P1.Alpha * P1.Direction;
                    maxKappa          = Math.Max(maxKappa, P1.Concentration);

                    m_Planes[j].m_Dismissed        = true;              // Dismiss
                    m_Planes[j].m_DismissalReason += " SIMILAR" + i;
                }
                P0.Direction     = averageDirection.Normalized;
                P0.Concentration = maxKappa;
            }


            //////////////////////////////////////////////////////////////////////////
            // Place planes at the best positions
            float maxOrthoDistance = 0.0f;

            for (int planeIndex = 0; planeIndex < planesCount; planeIndex++)
            {
                float2 Normal = new float2(m_Lobes[planeIndex].Direction.x, m_Lobes[planeIndex].Direction.y);
                m_Planes[planeIndex].m_Normal = Normal;

                float sumOrthoDistances0 = 0.0f;
                float sumWeights0        = 0.0f;
                float sumOrthoDistances1 = 0.0f;
                float sumWeights1        = 0.0f;
                for (int i = 0; i < PIXELS_COUNT; i++)
                {
                    float orthoDistance = -(m_Pixels[i].Position - m_boxCenter).Dot(Normal);

                    // Use computed probabilities
                    float weight = (float)probabilities[i, planeIndex];
                    sumOrthoDistances0 += weight * orthoDistance;
                    sumWeights0        += weight;

                    // Use weighted sum
                    float dot = Math.Max(0.0f, Normal.Dot(m_Pixels[i].Normal));
                    dot                 = (float)Math.Pow(dot, floatTrackbarControlWeightExponent.Value);
                    weight              = dot;
                    sumOrthoDistances1 += weight * orthoDistance;
                    sumWeights1        += weight;
                }
                float averageOrthoDistance0 = sumOrthoDistances0 / sumWeights0;
                float averageOrthoDistance1 = sumOrthoDistances1 / sumWeights1;

                // Choose whichever ortho distance is best
                float finalOrthoDistance;
                if (radioButtonBest.Checked)
                {
                    finalOrthoDistance = Math.Max(averageOrthoDistance0, averageOrthoDistance1);
                }
                else
                {
                    finalOrthoDistance = radioButtonProbabilities.Checked ? averageOrthoDistance0 : averageOrthoDistance1;
                }

                maxOrthoDistance = Math.Max(maxOrthoDistance, finalOrthoDistance);

                m_Planes[planeIndex].m_OrthoDistance = finalOrthoDistance;
                m_Planes[planeIndex].m_Position      = m_boxCenter - finalOrthoDistance * Normal;

                if (finalOrthoDistance <= 0.0f)
                {
                    m_Planes[planeIndex].m_Dismissed        = true;
                    m_Planes[planeIndex].m_DismissalReason += " BEHIND";
                }
            }


            //////////////////////////////////////////////////////////////////////////
            // Reconstruct weight
            if (radioButtonNormalAffinity.Checked)
            {
                // Reconstruct weights by normal affinity
                // We do the same operation as the normal weighting to compute ortho distances: dot each pixel with each plane normal and use that as a weight
                for (int planeIndex = 0; planeIndex < planesCount; planeIndex++)
                {
                    float2 Normal = new float2(m_Lobes[planeIndex].Direction.x, m_Lobes[planeIndex].Direction.y);

                    // Use weighted sum
                    float sumWeights = 0.0f;
                    for (int i = 0; i < PIXELS_COUNT; i++)
                    {
                        float weight = Math.Max(0.0f, Normal.Dot(m_Pixels[i].Normal));
                        weight      = (float)Math.Pow(weight, floatTrackbarControlWeightExponent.Value);
                        sumWeights += weight;
                    }
                    float finalWeight = sumWeights / PIXELS_COUNT;
                    m_Lobes[planeIndex].Alpha     = finalWeight;
                    m_Planes[planeIndex].m_Weight = finalWeight;
                }
            }
            else if (radioButtonLargestD.Checked)
            {
                // Choose largest ortho distances
                for (int planeIndex = 0; planeIndex < planesCount; planeIndex++)
                {
                    float weight = Math.Max(0.0f, m_Planes[planeIndex].m_OrthoDistance / maxOrthoDistance);
                    m_Lobes[planeIndex].Alpha     = weight;
                    m_Planes[planeIndex].m_Weight = weight;
                }
            }
            else if (radioButtonWeightHybrid.Checked)
            {
                // Hybrid method combining ortho distance and normal affinity
                for (int planeIndex = 0; planeIndex < planesCount; planeIndex++)
                {
                    float2 Normal = new float2(m_Lobes[planeIndex].Direction.x, m_Lobes[planeIndex].Direction.y);

                    // Use weighted sum
                    float sumWeights = 0.0f;
                    for (int i = 0; i < PIXELS_COUNT; i++)
                    {
                        float weight = Math.Max(0.0f, Normal.Dot(m_Pixels[i].Normal));
                        weight      = (float)Math.Pow(weight, floatTrackbarControlWeightExponent.Value);
                        sumWeights += weight;
                    }
                    float finalWeight = sumWeights / PIXELS_COUNT;
                    finalWeight *= Math.Max(0.0f, m_Planes[planeIndex].m_OrthoDistance / maxOrthoDistance);

                    m_Lobes[planeIndex].Alpha     = finalWeight;
                    m_Planes[planeIndex].m_Weight = finalWeight;
                }
            }


            //////////////////////////////////////////////////////////////////////////
            // Dismiss unimportant planes
            float averageWeight = 0.0f, harmonicAverageWeight = 0.0f, averageConcentration = 0.0f, harmonicAverageConcentration = 0.0f;
            float maxWeight = 0.0f, maxConcentration = 0.0f;
            float minWeight = float.MaxValue, minConcentration = float.MaxValue;
            int   validPlanesCount = 0;

            for (int planeIndex = 0; planeIndex < planesCount; planeIndex++)
            {
                if (m_Planes[planeIndex].m_Dismissed)
                {
                    continue;
                }

                float weight = (float)m_Lobes[planeIndex].Alpha;
                minWeight              = Math.Min(minWeight, weight);
                maxWeight              = Math.Max(maxWeight, weight);
                averageWeight         += weight;
                harmonicAverageWeight += 1.0f / Math.Max(1e-4f, weight);

                float concentration = (float)m_Lobes[planeIndex].Concentration;
                minConcentration              = Math.Min(minConcentration, concentration);
                maxConcentration              = Math.Max(maxConcentration, concentration);
                averageConcentration         += concentration;
                harmonicAverageConcentration += 1.0f / Math.Max(1e-4f, concentration);

                validPlanesCount++;
            }

            validPlanesCount             = Math.Max(1, validPlanesCount);
            averageWeight               /= validPlanesCount;
            harmonicAverageWeight        = validPlanesCount / harmonicAverageWeight;
            averageConcentration        /= validPlanesCount;
            harmonicAverageConcentration = validPlanesCount / harmonicAverageConcentration;
//			float	dismissWeight = 0.5f / validPlanesCount;
            float dismissWeight        = floatTrackbarControlDismissFactor.Value * harmonicAverageWeight;
            float dismissConcentration = floatTrackbarControlDismissFactor.Value * harmonicAverageConcentration;

            // Select the N best planes/Dismiss others
            if (!radioButtonUseBest.Checked)
            {
                for (int planeIndex = 0; planeIndex < planesCount; planeIndex++)
                {
                    bool dismissed = radioButtonDismissKappa.Checked ? m_Lobes[planeIndex].Concentration < dismissConcentration : m_Lobes[planeIndex].Alpha < dismissWeight;
                    if (dismissed)
                    {
                        m_Planes[planeIndex].m_Dismissed        = true;
                        m_Planes[planeIndex].m_DismissalReason += " REJECTED";
                    }
                }
            }

            // Dismiss planes that are totally clipped by others
            DismissClippedPlanes();

            // Dismiss planes above target count
            List <SortedPlane> SortedPlanes = new List <SortedPlane>(planesCount);

            for (int planeIndex = 0; planeIndex < planesCount; planeIndex++)
            {
                SortedPlanes.Add(new SortedPlane()
                {
                    planeIndex = planeIndex, weight = m_Planes[planeIndex].m_Dismissed ? 0.0f : m_Planes[planeIndex].m_Weight
                });
            }

            SortedPlanes.Sort();
            for (int planeIndex = 0; planeIndex < planesCount; planeIndex++)
            {
                SortedPlane SP = SortedPlanes[planeIndex];
                if (!m_Planes[SP.planeIndex].m_Dismissed && planeIndex >= integerTrackbarControlKeepBestPlanesCount.Value)
                {
                    m_Planes[SP.planeIndex].m_Dismissed        = true;
                    m_Planes[SP.planeIndex].m_DismissalReason += " LIMIT";
                }
            }


            //////////////////////////////////////////////////////////////////////////
            // Display info
            string text = "";

            text += "Min, Max, Avg, HAvg Weight = " + minWeight.ToString("G4") + ", " + maxWeight.ToString("G4") + ", " + averageWeight.ToString("G4") + ", " + harmonicAverageWeight.ToString("G4") + " > Dismiss weight = " + dismissWeight + "\r\n";
            text += "Min, Max, Avg, HAvg Kappa = " + minConcentration.ToString("G4") + ", " + maxConcentration.ToString("G4") + ", " + averageConcentration.ToString("G4") + ", " + harmonicAverageConcentration.ToString("G4") + " > Dismiss kappa = " + dismissConcentration + "\r\n\r\n";

            text += planesCount + " Planes:\r\n";
            for (int planeIndex = 0; planeIndex < planesCount; planeIndex++)
            {
                text += "#" + planeIndex + " => { " + m_Lobes[planeIndex].Direction.x.ToString("G4") + ", " + m_Lobes[planeIndex].Direction.y.ToString("G4") + "} D = " + m_Planes[planeIndex].m_OrthoDistance.ToString("G4") + "  -  k=" + m_Lobes[planeIndex].Concentration.ToString("G4") + "  -  weight = " + m_Lobes[planeIndex].Alpha.ToString("G4") + m_Planes[planeIndex].m_DismissalReason + " " + (m_Planes[planeIndex].m_Dismissed ? "(DIS)" : "") + "\r\n";
            }

            textBoxPlanes.Text = text;

            // Refresh
            panelOutput.UpdateBitmap();
            panelHistogram.UpdateBitmap();
        }
예제 #8
0
파일: Form1.cs 프로젝트: vr3d/GodComplex
        // Build a random polygonal room
        void    BuildRoom()
        {
            const float MAX_DISTANCE = 20.0f;

            Random RNG = new Random(integerTrackbarControlRandomSeed.Value);

//			int			planesCount = (int) (4 + 2 * RNG.NextDouble());
            int planesCount = integerTrackbarControlRoomPlanesCount.Value;

            float2[] planePositions = new float2[planesCount];
            float2[] planeNormals   = new float2[planesCount];

            m_boxCenter = float2.Zero;            //new float2( (float) (-10.0 + 20.0 * RNG.NextDouble()), (float) (-10.0 + 20.0 * RNG.NextDouble()) );
            float baseAngle    = (float)(RNG.NextDouble() * 2.0 * Math.PI);
            float averageAngle = (float)(2.0 * Math.PI / planesCount);

            for (int planeIndex = 0; planeIndex < planesCount; planeIndex++)
            {
                float2 normal = new float2((float)Math.Cos(baseAngle), (float)Math.Sin(baseAngle));
                planeNormals[planeIndex] = normal;

                float2 toCenter        = m_boxCenter;
                float  distance2Center = toCenter.Dot(normal);
                float  planeDistance   = distance2Center > 0.0f ? distance2Center + 0.1f + (float)(Math.Max(0.0f, MAX_DISTANCE - distance2Center) * RNG.NextDouble()) : (float)(MAX_DISTANCE * RNG.NextDouble());

                float2 position = m_boxCenter - planeDistance * normal;
                planePositions[planeIndex] = position;

                baseAngle += (float)(averageAngle * (0.9 + 0.2 * RNG.NextDouble()));
            }

            // Build the original room pixels
            for (int i = 0; i < PIXELS_COUNT; i++)
            {
                float2 C     = m_boxCenter;
                float  angle = (float)(2.0 * Math.PI * i / PIXELS_COUNT);
                float2 V     = new float2((float)Math.Cos(angle), (float)Math.Sin(angle));

                // Compute intersection with the planes
                float minHitDistance = float.MaxValue;
                int   hitPlaneIndex  = -1;
                for (int planeIndex = 0; planeIndex < planesCount; planeIndex++)
                {
                    float2 D           = C - planePositions[planeIndex];
                    float  hitDistance = -D.Dot(planeNormals[planeIndex]) / V.Dot(planeNormals[planeIndex]);
                    if (hitDistance > 0.0f && hitDistance < minHitDistance)
                    {
                        minHitDistance = hitDistance;
                        hitPlaneIndex  = planeIndex;
                    }
                }
                if (hitPlaneIndex == -1)
                {
                    m_Pixels[i].Distance = 40.0f;
                    continue;
                }
                minHitDistance = Math.Min(40.0f, minHitDistance);

                float noiseDistance = 0.2f * (2.0f * (float)RNG.NextDouble() - 1.0f);
                m_Pixels[i].Distance = minHitDistance + noiseDistance;
                m_Pixels[i].Position = m_boxCenter + m_Pixels[i].Distance * V;

                float2 normal      = planeNormals[hitPlaneIndex];
                float  normalAngle = (float)Math.Atan2(normal.y, normal.x);
                float  noiseAngle  = 0.1f * (2.0f * (float)RNG.NextDouble() - 1.0f);
                normal = new float2((float)Math.Cos(normalAngle + noiseAngle), (float)Math.Sin(normalAngle + noiseAngle));

                m_Pixels[i].Normal = normal;
            }

            // Add some obstacles
            int         OBSTACLES_COUNT       = integerTrackbarControlObstacles.Value;
            const float MAX_OBSTACLE_DISTANCE = 15.0f;

            m_ObstaclesRound.Clear();
            m_ObstaclesSquare.Clear();
            for (int i = 0; i < OBSTACLES_COUNT; i++)
            {
//				float2	pos = m_boxCenter + MAX_OBSTACLE_DISTANCE * new float2( (float) (2.0 * RNG.NextDouble() - 1.0), (float) (2.0 * RNG.NextDouble() - 1.0) );

                float  d      = MAX_OBSTACLE_DISTANCE * (float)(0.3 + 0.7 * RNG.NextDouble());
                float  a      = (float)(2.0 * Math.PI * RNG.NextDouble());
                float2 pos    = m_boxCenter + d * new float2((float)Math.Cos(a), (float)Math.Sin(a));
                float2 dir    = new float2((float)(2.0 * RNG.NextDouble() - 1.0), (float)(2.0 * RNG.NextDouble() - 1.0)).Normalized;
                float2 radius = 1.0f * new float2((float)(0.1 + 0.9 * RNG.NextDouble()), (float)(0.1 + 0.9 * RNG.NextDouble()));

                Obstacle O = new Obstacle()
                {
                    m_Position    = pos,
                    m_Orientation = dir,
                    m_Scale       = radius
                };

                double k = RNG.NextDouble();
                if (k < 0.7)
                {
                    AddObstacleRound(pos, dir, radius); m_ObstaclesRound.Add(O);
                }
                else
                {
                    AddObstacleSquare(pos, dir, radius); m_ObstaclesSquare.Add(O);
                }
            }

            SolveRoom();
        }
예제 #9
0
        /// <summary>
        /// This function performs a simple integration test by slicing a bent plane into N slice and using the integrals
        /// to compute the resulting average bent normal for each slice, then finalizing the resulting normal which should
        /// equal the initial test normal
        /// </summary>
        void    PerformIntegrationTest()
        {
            float3 csNormal = new float3(2, 4, 1).Normalized;                   // Simple 45° bent normal

            uint SLICES_COUNT = 128;

            float3 csAverageBentNormal = float3.Zero;

            for (uint sliceIndex = 0; sliceIndex < SLICES_COUNT; sliceIndex++)
            {
                float  phi         = sliceIndex * Mathf.PI / SLICES_COUNT;
                float2 csDirection = new float2(Mathf.Cos(phi), Mathf.Sin(phi));

                // Compute initial horizon angles
                float t = -csDirection.Dot(csNormal.xy) / csNormal.z;
                float maxCosTheta_Front = t / Mathf.Sqrt(t * t + 1.0f);
                float maxCosTheta_Back  = -maxCosTheta_Front;                   // Back cosine is simply the mirror value

// =======================
// Here, the runtime algorithm is normally updating the horizon angles but we keep them flat: our goal is to obtain the original csNormal!
// =======================

                // Accumulate bent normal direction by rebuilding and averaging the front & back horizon vectors
                float2 ssNormal = new float2(csNormal.xy.Dot(csDirection), csNormal.z);                         // Slice-space normal

/*				// Numerical integration
 *                              // Half brute force where we perform the integration numerically as a sum...
 *                              //
 *                              const uint	STEPS_COUNT = 256;
 *
 *                              float	theta_Front = Mathf.Acos( maxCosTheta_Front );
 *                              float	theta_Back = -Mathf.Acos( maxCosTheta_Back );	// Technically, this is theta0 and it should be in [-PI,0] but we took its absolute value to ease our computation
 *
 *                              float2	ssBentNormal = float2.Zero;// 0.001f * float2.UnitY;
 *                              for ( uint i=0; i < STEPS_COUNT; i++ ) {
 *                                      float	theta = Mathf.Lerp( theta_Back, theta_Front, (i+0.5f) / STEPS_COUNT );
 *                                      float	sinTheta = Mathf.Sin( theta ), cosTheta = Mathf.Cos( theta );
 *                                      float2	ssOmega = new float2( sinTheta, cosTheta );
 *
 *                                      float	cosAlpha = Mathf.Saturate( ssOmega.Dot( ssNormal ) );
 *
 *                                      float	weight = cosAlpha * Mathf.Abs( sinTheta );		// cos(alpha) * sin(theta).dTheta  (be very careful to take abs(sin(theta)) because our theta crosses the pole and becomes negative here!)
 *
 *                                      ssBentNormal += weight * ssOmega;
 *                              }
 *
 *                              float	dTheta = (theta_Front - theta_Back) / STEPS_COUNT;
 *                              ssBentNormal *= dTheta;
 *
 *                              float3	csBentNormal = new float3( ssBentNormal.x * csDirection, ssBentNormal.y );
 * //*/
//*				// Analytical integration
                float cosTheta0   = maxCosTheta_Front;
                float cosTheta1   = maxCosTheta_Back;
                float sinTheta0   = Mathf.Sqrt(1.0f - cosTheta0 * cosTheta0);
                float sinTheta1   = Mathf.Sqrt(1.0f - cosTheta1 * cosTheta1);
                float cosTheta0_3 = cosTheta0 * cosTheta0 * cosTheta0;
                float cosTheta1_3 = cosTheta1 * cosTheta1 * cosTheta1;
                float sinTheta0_3 = sinTheta0 * sinTheta0 * sinTheta0;
                float sinTheta1_3 = sinTheta1 * sinTheta1 * sinTheta1;

                float averageX = ssNormal.x * (cosTheta0_3 + cosTheta1_3 - 3.0f * (cosTheta0 + cosTheta1) + 4.0f)
                                 + ssNormal.y * (sinTheta0_3 - sinTheta1_3);

                float averageY = ssNormal.x * (sinTheta0_3 - sinTheta1_3)
                                 + ssNormal.y * (2.0f - cosTheta0_3 - cosTheta1_3);

                float3 csBentNormal = new float3(averageX * csDirection, averageY);
//*/

                // DON'T NORMALIZE RESULT!!
                //csBentNormal.Normalize();

                csAverageBentNormal += csBentNormal;
            }

            float3 csFinalNormal = csAverageBentNormal.Normalized;
        }
예제 #10
0
        float3  GatherIrradiance(float2 _csDirection, float4x4 _localCamera2World, float3 _csNormal, float _stepSize_meters, uint _stepsCount, float _Z0, float3 _centralRadiance, out float3 _csBentNormal, out float2 _coneAngles, out float _AO, ref float4 _DEBUG)
        {
            // Pre-compute factors for the integrals
            float2 integralFactors_Front = ComputeIntegralFactors(_csDirection, _csNormal);
            float2 integralFactors_Back  = ComputeIntegralFactors(-_csDirection, _csNormal);

            // Compute initial cos(angle) for front & back horizons
            // We do that by projecting the screen-space direction ssDirection onto the tangent plane given by the normal
            //	then the cosine of the angle from the Z axis is simply given by the Pythagorean theorem:
            //                             P
            //			   N\  |Z		  -*-
            //				 \ |	  ---  ^
            //				  \|  ---      |
            //             --- *..........>+ ssDirection
            //        ---
            //
            float hitDistance_Front = -_csDirection.Dot(_csNormal.xy) / _csNormal.z;
            float maxCosTheta_Front = hitDistance_Front / Mathf.Sqrt(hitDistance_Front * hitDistance_Front + 1.0f);
            float maxCosTheta_Back  = -maxCosTheta_Front;               // Back cosine is simply the mirror value

            // Gather irradiance from front & back directions while updating the horizon angles at the same time
            float3 sumRadiance            = float3.Zero;
            float3 previousRadiance_Front = _centralRadiance;
            float3 previousRadianceBack   = _centralRadiance;
//*
//			float2	radius = float2.Zero;
            float2 csStep           = _stepSize_meters * _csDirection;
            float2 csPosition_Front = float2.Zero;
            float2 csPosition_Back  = float2.Zero;

            for (uint stepIndex = 0; stepIndex < _stepsCount; stepIndex++)
            {
//				radius += _stepSize_meters;
                csPosition_Front += csStep;
                csPosition_Back  -= csStep;

//				float2	mipLevel = ComputeMipLevel( radius, _radialStepSizes );
                float2 mipLevel = float2.Zero;

                sumRadiance += SampleIrradiance(csPosition_Front, _localCamera2World, _Z0, mipLevel, integralFactors_Front, ref previousRadiance_Front, ref maxCosTheta_Front);
                sumRadiance += SampleIrradiance(csPosition_Back, _localCamera2World, _Z0, mipLevel, integralFactors_Back, ref previousRadianceBack, ref maxCosTheta_Back);
            }
//*/
            // Accumulate bent normal direction by rebuilding and averaging the front & back horizon vectors
            float2 ssNormal = new float2(_csNormal.xy.Dot(_csDirection), _csNormal.z);

                        #if USE_NUMERICAL_INTEGRATION
            // Half brute force where we perform the integration numerically as a sum...
            //
            const uint STEPS = 256;

            float thetaFront = Mathf.Acos(maxCosTheta_Front);
            float thetaBack  = -Mathf.Acos(maxCosTheta_Back);

            float2 ssBentNormal = float2.Zero;
            for (uint i = 0; i < STEPS; i++)
            {
                float  theta = Mathf.Lerp(thetaBack, thetaFront, (i + 0.5f) / STEPS);
                float  sinTheta = Mathf.Sin(theta), cosTheta = Mathf.Cos(theta);
                float2 ssOmega = new float2(sinTheta, cosTheta);

                float cosAlpha = Mathf.Saturate(ssOmega.Dot(ssNormal));

                cosAlpha = 1.0f;

                float weight = cosAlpha * Mathf.Abs(sinTheta);                                          // cos(alpha) * sin(theta).dTheta  (be very careful to take abs(sin(theta)) because our theta crosses the pole and becomes negative here!)

                ssBentNormal += weight * ssOmega;
            }

            float dTheta = (thetaFront - thetaBack) / STEPS;
            ssBentNormal *= dTheta;

            _csBentNormal = new float3(ssBentNormal.x * _csDirection, ssBentNormal.y);
                        #else
            // Analytical solution
// Accounts for dot product with normal
//              float	cosTheta0 = maxCosTheta_Front;
//              float	cosTheta1 = maxCosTheta_Back;
//              float	sinTheta0 = Mathf.Sqrt( 1.0f - cosTheta0*cosTheta0 );
//              float	sinTheta1 = Mathf.Sqrt( 1.0f - cosTheta1*cosTheta1 );
//
//              float	cosTheta0_3 = cosTheta0*cosTheta0*cosTheta0;
//              float	cosTheta1_3 = cosTheta1*cosTheta1*cosTheta1;
//              float	sinTheta0_3 = sinTheta0*sinTheta0*sinTheta0;
//              float	sinTheta1_3 = sinTheta1*sinTheta1*sinTheta1;
//
//              float	averageX = ssNormal.x * (cosTheta0_3 + cosTheta1_3 - 3.0f * (cosTheta0 + cosTheta1) + 4.0f)
//                               + ssNormal.y * (sinTheta0_3 - sinTheta1_3);
//
//              float	averageY = ssNormal.x * (sinTheta0_3 - sinTheta1_3)
//                               + ssNormal.y * (2.0f - cosTheta0_3 - cosTheta1_3);
//

            // Raw integration, without dot product with normal
            float theta0 = -Mathf.Acos(maxCosTheta_Back);
            float theta1 = Mathf.Acos(maxCosTheta_Front);

            float averageX = theta1 + theta0 - Mathf.Sin(theta0) * Mathf.Cos(theta0) - Mathf.Sin(theta1) * Mathf.Cos(theta1);
            float averageY = 2.0f - Mathf.Cos(theta0) * Mathf.Cos(theta0) - Mathf.Cos(theta1) * Mathf.Cos(theta1);

            _csBentNormal = new float3(averageX * _csDirection, averageY);
                        #endif

            // DON'T NORMALIZE RESULT!!
//			_csBentNormal = _csBentNormal.Normalized;

            // Compute cone angles
            float3 csNormalizedBentNormal = _csBentNormal.Normalized;
            float3 csHorizon_Front        = new float3(Mathf.Sqrt(1.0f - maxCosTheta_Front * maxCosTheta_Front) * _csDirection, maxCosTheta_Front);
            float3 csHorizon_Back         = new float3(-Mathf.Sqrt(1.0f - maxCosTheta_Back * maxCosTheta_Back) * _csDirection, maxCosTheta_Back);

                        #if USE_FAST_ACOS
            _coneAngles.x = FastPosAcos(saturate(dot(csNormalizedBentNormal, csHorizon_Front)));
            _coneAngles.y = FastPosAcos(saturate(dot(csNormalizedBentNormal, csHorizon_Back)));
                        #else
            _coneAngles.x = Mathf.Acos(Mathf.Saturate(csNormalizedBentNormal.Dot(csHorizon_Front)));
            _coneAngles.y = Mathf.Acos(Mathf.Saturate(csNormalizedBentNormal.Dot(csHorizon_Back)));
                        #endif

            // Compute AO using equation 11 of the paper
            _AO = 2.0f - maxCosTheta_Back - maxCosTheta_Front;
//          _AO = 0.0f;
// //           float	theta0 = -Mathf.Acos( maxCosTheta_Back );
// //           float	theta1 = Mathf.Acos( maxCosTheta_Front );
//          for ( uint i=0; i < 256; i++ ) {
//              float	theta = Mathf.Lerp( theta0, theta1, (i+0.5f) / 256 );
//              _AO += Math.Abs( Mathf.Sin( theta ) );
//          }
//          _AO *= (theta1 - theta0) / 256.0f;

            return(sumRadiance);
        }