Example #1
0
 void PointGroup_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
 {
     if (e.PropertyName == "IsVisible")
     {
         Viewport.Redraw();
     }
 }
Example #2
0
        private void PerformPlanarizationStep(Vector3 center)
        {
            float EdgeFactor = (float)ShapePreservation;

            Vector3[] Forces = new Vector3[SurfaceMesh.Vertices.Count];

            for (int r = 0; r < 10; r++)
            {
                float MeanZ = SurfaceMesh.GetCentroid().Z;

                Parallel.For(0, SurfaceMesh.Vertices.Count,
                             i => SurfaceMesh.Vertices[i].Position.Z += (MeanZ - SurfaceMesh.Vertices[i].Position.Z) / EdgeFactor * 0.4f);

                for (int s = 0; s < 30; s++)
                {
                    Parallel.For(0, Forces.Length, i =>
                    {
                        Vector3 Force       = new Vector3(0);
                        Vector3 OwnPosition = SurfaceMesh.Vertices[i].Position;
                        foreach (var t in PlanarizationAccel[i])
                        {
                            Vector3 Direction = t.Item1.Position - OwnPosition;
                            float Distance    = Direction.Length;
                            Direction        /= Math.Max(1e-4f, Distance);
                            float Difference  = Distance - t.Item2;
                            Force            += Direction * Difference;
                        }

                        Forces[i] = Force * 0.5f;
                    });

                    Parallel.For(0, Forces.Length, i => SurfaceMesh.Vertices[i].Position += Forces[i] * 0.4f);
                }
            }

            Vector3 NewCenter        = SurfaceMesh.GetCentroid();
            Vector3 CenterAdjustment = center - NewCenter;

            Parallel.ForEach(SurfaceMesh.Vertices, v => v.Position += CenterAdjustment);

            Parallel.ForEach(SurfaceMesh.Triangles, face => face.UpdateNormal());

            ParentWindow?.Dispatcher.Invoke(() =>
            {
                SurfaceMesh.UpdateBuffers();
                Viewport?.Redraw();
            });

            UpdatePlanarizationStats();
        }
Example #3
0
        private void MatchPosition()
        {
            if (LockTarget == null || !IsLocked || !IsLockedPosition)
            {
                TurnUpsideUp();
                SurfaceMesh.UpdateBuffers();
                Viewport.Redraw();
                return;
            }

            Vector3[] IdealPositions = new Vector3[VertexLocks.Count];
            Vector4[] StartPositions = new Vector4[VertexLocks.Count];
            {
                int i = 0;
                foreach (var pair in VertexLocks)
                {
                    Vector3 OwnPosition = pair.Key.VolumePosition;
                    Vector3 Mean        = new Vector3(0);
                    foreach (var target in pair.Value)
                    {
                        Vector3 Relative           = OwnPosition - target.GetVolumeCenter();
                        Matrix4 Volume2Transformed = target.GetPlaneMatrix() * Matrix4.Transpose(target.GetVolumePlaneMatrix());
                        Relative  = Vector3.Transform(Relative, Matrix4.Transpose(Volume2Transformed));
                        Relative += target.GetCenter();
                        Mean     += Relative;
                    }

                    Mean *= 1f / pair.Value.Length;
                    IdealPositions[i] = Mean;
                    StartPositions[i] = new Vector4(pair.Key.Position, 1);
                    i++;
                }
            }

            Vector3 BestRotation = new Vector3(), BestTranslation = new Vector3();
            float   BestScore = float.MaxValue;

            Vector3 Extent            = SurfaceMesh.GetMax() - SurfaceMesh.GetMin();
            float   MaxExtent         = Math.Max(Math.Max(Extent.X, Extent.Y), Extent.Z) / 2f;
            float   AngleConditioning = (float)Math.Asin(Math.Min(1f / MaxExtent, Math.Sin(30 * Helper.ToRad)));

            AngleConditioning = Math.Max(1, Helper.ToDeg * AngleConditioning);

            List <Vector3> AnglesToTry = new List <Vector3> {
                new Vector3(5, 3, -4), new Vector3(5, 3, 184), new Vector3(185, 3, -4), new Vector3(5, 182, -4)
            };
            Random Rand = new Random(123);

            for (int i = 0; i < 5; i++)
            {
                AnglesToTry.Add(new Vector3(Rand.Next(360), Rand.Next(360), Rand.Next(360)));
            }
            for (int i = 0; i < AnglesToTry.Count; i++)
            {
                AnglesToTry[i] /= AngleConditioning;
            }

            Func <double[], double> F = vars =>
            {
                Vector3 Angles = new Vector3(Helper.ToRad * (float)vars[0], Helper.ToRad * (float)vars[1], Helper.ToRad * (float)vars[2]) * AngleConditioning;
                Vector3 Shifts = new Vector3((float)vars[3], (float)vars[4], (float)vars[5]);

                Matrix4 Transform = Matrix4.CreateTranslation(Shifts) *
                                    Matrix4.CreateRotationX(Angles.X) *
                                    Matrix4.CreateRotationY(Angles.Y) *
                                    Matrix4.CreateRotationZ(Angles.Z);

                float MeanDistance = 0;
                for (int i = 0; i < StartPositions.Length; i++)
                {
                    MeanDistance += (Vector4.Transform(StartPositions[i], Transform).Xyz - IdealPositions[i]).LengthSquared;
                }
                MeanDistance /= StartPositions.Length;

                return(Math.Sqrt(MeanDistance));
            };

            Func <double[], double[]> G = vars =>
            {
                double[] Gradients = new double[vars.Length];

                for (int i = 0; i < vars.Length; i++)
                {
                    double[] Plus = new double[vars.Length];
                    vars.CopyTo(Plus, 0);
                    Plus[i] += 0.1;

                    double[] Minus = new double[vars.Length];
                    vars.CopyTo(Minus, 0);
                    Minus[i] -= 0.1;

                    Gradients[i] = (F(Plus) - F(Minus)) / 0.2;
                }

                return(Gradients);
            };

            foreach (var startAngle in AnglesToTry)
            {
                double[] Start = { startAngle.X, startAngle.Y, startAngle.Z, 0, 0, 0 };

                Cobyla Optimizer = new Cobyla(6, F);
                Optimizer.Minimize(Start);

                if (Optimizer.Value < BestScore)
                {
                    BestScore       = (float)Optimizer.Value;
                    BestRotation    = new Vector3((float)Optimizer.Solution[0], (float)Optimizer.Solution[1], (float)Optimizer.Solution[2]) * AngleConditioning;
                    BestTranslation = new Vector3((float)Optimizer.Solution[3], (float)Optimizer.Solution[4], (float)Optimizer.Solution[5]);
                }
            }

            Matrix4 ToTarget = Matrix4.CreateTranslation(BestTranslation) *
                               Matrix4.CreateRotationX(Helper.ToRad * BestRotation.X) *
                               Matrix4.CreateRotationY(Helper.ToRad * BestRotation.Y) *
                               Matrix4.CreateRotationZ(Helper.ToRad * BestRotation.Z);

            foreach (var v in SurfaceMesh.Vertices)
            {
                v.Position = Vector4.Transform(new Vector4(v.Position, 1), ToTarget).Xyz;
            }
            foreach (var t in SurfaceMesh.Triangles)
            {
                t.UpdateNormal();
            }

            SurfaceMesh.UpdateBuffers();
            Viewport.Redraw();
        }