Exemple #1
0
        void UpdateSweepHullGeometry(Vector3[] shapeLocalVertices)
        {
            var target = ConvexSweepTarget.Value;

            var tr   = Transform.Value;
            var from = tr.ToMatrix4(true, true, false);
            var to   = target.Transform.Value.ToMatrix4(true, false, false);

            var hullPositions = new Vector3[shapeLocalVertices.Length * 2];

            for (int i = 0; i < shapeLocalVertices.Length; i++)
            {
                Matrix4.Multiply(ref from, ref shapeLocalVertices[i], out hullPositions[i]);
                Matrix4.Multiply(ref to, ref shapeLocalVertices[i], out hullPositions[i + shapeLocalVertices.Length]);
            }

            ConvexHullAlgorithm.Create(hullPositions, out hullVertices, out hullIndices, out hullPlanes);

            //ConvexHullAlgorithm.Create( hullPositions, out hullVertices, out hullIndices );
            ////Bullet's implementation makes additional margin
            ////BulletUtils.GetHullVertices( hullPositions, out hullVertices, out hullIndices );

            //hullPlanes = new Plane[ hullIndices.Length / 3 ];

            //for( int i = 0; i < hullIndices.Length; i += 3 )
            //{
            //	var v0 = hullVertices[ hullIndices[ i ] ];
            //	var v1 = hullVertices[ hullIndices[ i + 1 ] ];
            //	var v2 = hullVertices[ hullIndices[ i + 2 ] ];

            //	hullPlanes[ i / 3 ] = Plane.FromPoints( v0, v1, v2 );
            //}
        }
    private void Start()
    {
        Vector3[]  vertices = new Vector3[pointsParent.childCount];
        List <int> indices  = new List <int>();

        for (int i = 0; i < vertices.Length; i++)
        {
            vertices[i] = pointsParent.GetChild(i).position;
            indices.Add(i);
        }

        Plane plane = new Plane(Vector3.back, 0);

        ConvexHullAlgorithm.Execute(ref indices, vertices, plane.normal);

        indices.Reverse();//反转列表,逆时针变顺时针

        /*Vector3[] vertices2=new Vector3[indices.Count];
         *      for(int i=0;i<indices.Count;i++){
         *              Vector3 vertex=vertices[indices[i]];
         *              vertex.z=0;
         *              vertices2[i]=vertex;
         *      }
         *      indices=TriangulationAlgorithm.WidelyTriangleIndex(vertices2);*/

        TriangulationAlgorithm.WidelyTriangleIndex(vertices, ref indices, plane);

        for (int i = 0; i < indices.Count; i++)
        {
            int index = indices[i];
            s_points.Add(vertices[index]);
        }
    }
        /// <summary>
        /// Constructor to create the initial instance of the controller singleton
        /// </summary>
        /// <param name="parent">Handle to a view window</param>
        /// <param name="radius">Radius to draw nodes and lines at</param>
        private Controller(ExampleWindow parent, int radius)
        {
            algorithm = null;
            view = parent;

            maxX = parent.ModelOutput.Width;
            maxY = parent.ModelOutput.Height;

            this.nodeRadius = radius;

            model = new MasterModel(parent, nodeRadius);
        }
    private void Start()
    {
        Vector3[]  vertices = new Vector3[pointsParent.childCount];
        List <int> indices  = new List <int>();

        for (int i = 0; i < vertices.Length; i++)
        {
            vertices[i] = pointsParent.GetChild(i).position;
            indices.Add(i);
        }

        Plane plane = new Plane(Vector3.back, 0);

        ConvexHullAlgorithm.Execute(ref indices, vertices, plane.normal);

        for (int i = 0; i < indices.Count; i++)
        {
            s_points.Add(vertices[indices[i]]);
        }
    }
        /// <summary>
        /// Sets which algorithm to use and sets up model if nodes exist
        /// </summary>
        /// <param name="selection">The algorithm to use</param>
        public void SetAlgorithm(AlgorithmEnum selection)
        {
            switch (selection)
            {
                case AlgorithmEnum.BruteForce:
                    algorithm = new BruteForce();
                    break;
                case AlgorithmEnum.GrahamScan:
                    algorithm = new GrahamScan();
                    break;
                default:
                    throw new NotImplementedException("There is no algorithm that matches that selection");
            }

            if (model.GetNodeList().Count > 0)
            {
                ScaleStepTrackBar();
            }
        }
        protected internal override CollisionShape CreateShape()
        {
            var epsilon = 0.0001f;

            //clear data
            processedVertices = null;
            processedIndices  = null;
            processedTrianglesToSourceIndex = null;

            //get source geometry
            if (!GetSourceData(out var sourceVertices, out var sourceIndices))
            {
                return(null);
            }

            //check valid data
            if (CheckValidData)
            {
                if (!MathAlgorithms.CheckValidVertexIndexBuffer(sourceVertices.Length, sourceIndices, false))
                {
                    Log.Info("Component_CollisionShape_Mesh: CreateShape: Invalid source data.");
                    return(null);
                }
            }

            //process geometry
            if (MergeEqualVerticesRemoveInvalidTriangles)
            {
                //!!!!slowly. later use cached precalculated bullet shape.
                MathAlgorithms.MergeEqualVerticesRemoveInvalidTriangles(sourceVertices, sourceIndices, epsilon, out processedVertices, out processedIndices, out processedTrianglesToSourceIndex);
            }
            else
            {
                processedVertices = sourceVertices;
                processedIndices  = sourceIndices;
            }

            //create bullet shape

            if (ShapeType.Value == ShapeTypeEnum.Auto && ParentRigidBody.MotionType.Value == Component_RigidBody.MotionTypeEnum.Dynamic && MathAlgorithms.IsMeshConvex(processedVertices, processedIndices, epsilon) || ShapeType.Value == ShapeTypeEnum.Convex)
            {
                if (MathAlgorithms.IsPlaneMesh(processedVertices, processedIndices, epsilon))
                {
                    Log.Info("Component_CollisionShape_Mesh: CreateShape: Unable to create shape as convex hull. All vertices on the one plane.");
                    return(null);
                }

                //!!!!тут иначе? возможно лучше получить результирующие processed данные из буллета. как получить processedTrianglesToSourceIndex - это вопрос. возможно ли?
                //если нельзя то processedTrianglesToSourceIndex = new int[ 0 ]; - что означает нельзя сконвертировать.
                //если processedTrianglesToSourceIndex == null, то конвертация 1:1.

                try
                {
                    ConvexHullAlgorithm.Create(processedVertices.ToVector3Array(), processedIndices, out var processedVertices2, out processedIndices);
                    processedVertices = processedVertices2.ToVector3FArray();

                    //var convex = ConvexHullAlgorithm.Create( processedVertices, processedIndices );

                    //var vlist = new List<Vec3F>( convex.Faces.Length * 3 );
                    //foreach( var f in convex.Faces )
                    //	for( int v = 0; v < f.Vertices.Length; v++ )
                    //		vlist.Add( f.Vertices[ v ].ToVec3F() );

                    //processedVertices = vlist.ToArray();
                    //processedIndices = null;

                    //BulletUtils.GetHullVertices( processedVertices.ToVec3Array(), processedIndices, out var processedVertices2, out processedIndices );
                    //processedVertices = processedVertices2.ToVec3FArray();
                    //BulletUtils.GetHullVertices( processedVertices, processedIndices, out processedVertices, out processedIndices );

                    //если нельзя то processedTrianglesToSourceIndex = new int[ 0 ]; - что означает нельзя сконвертировать.
                    processedTrianglesToSourceIndex = Array.Empty <int>();
                }
                catch (Exception e)
                {
                    Log.Info("Component_CollisionShape_Mesh: CreateShape: Unable to create shape as convex hull. " + e.Message);
                    return(null);
                }

                //!!!!
                var processedVerticesBullet = BulletPhysicsUtility.Convert(processedVertices);

                return(new ConvexHullShape(processedVerticesBullet));
            }
            else
            {
                //!!!проверки на ошибки данных

                //!!!!can create without making of Vector3[] array. IntPtr constructor? internally the memory will copied?
                indexVertexArrays = new TriangleIndexVertexArray(processedIndices, BulletPhysicsUtility.Convert(processedVertices));

                //indexVertexArrays = new TriangleIndexVertexArray();
                //var indexedMesh = new IndexedMesh();
                //indexedMesh.Allocate( totalTriangles, totalVerts, triangleIndexStride, vertexStride );
                //indexedMesh SetData( ICollection<int> triangles, ICollection<Vector3> vertices );
                //indexVertexArrays.AddIndexedMesh( indexedMesh );


                //!!!!расшаривать данные которые тут. одинаковые в разных объектах

                //!!!!определять когда не считать кеш

                //It is better to use "useQuantizedAabbCompression=true", because it makes the tree data structure 4 times smaller: sizeof( btOptimizedBvhNode ) = 64 and sizeof( btQuantizedBvhNode ) = 16 bytes.Note that the number of AABB tree nodes is twice the number of triangles.

                //Instead of creating the tree on the XBox 360 console, it is better to deserialize it directly from disk to memory. See btOptimizedBvh::deSerializeInPlace in Demos/ConcaveDemo/ConcavePhysicsDemo.cpp

                //без useQuantizedAabbCompression в три раза быстрее создается

                //!!!!enable when cache support
                bool useQuantizedAabbCompression = false;
                //bool useQuantizedAabbCompression = true;
                bool buildBvh = true;

                //!!!!в другом конструкторе можно еще указать какие-то bound min max
                //public BvhTriangleMeshShape( StridingMeshInterface meshInterface, bool useQuantizedAabbCompression, Vector3 bvhAabbMin, Vector3 bvhAabbMax, bool buildBvh = true );

                return(new BvhTriangleMeshShape(indexVertexArrays, useQuantizedAabbCompression, buildBvh));
            }
        }
        //!!!!подобное для Brush режима
        //public delegate void CalculateCreateObjectPositionUnderCursorEventDelegate( Component_ObjectInSpace objectInSpace, ref bool found, ref Vector3 position );
        //public static event CalculateCreateObjectPositionUnderCursorEventDelegate CalculateCreateObjectPositionUnderCursorEvent;

        //public class CalculateCreateObjectPositionByRayResult
        //{
        //	public bool Found;
        //	public Vector3 Position;
        //	public Component_ObjectInSpace CollidedWith;
        //	public Vector3F Normal;
        //}

        public static (bool found, Vector3 position, Component_ObjectInSpace collidedWith) CalculateCreateObjectPositionByRay(Component_Scene scene, Component_ObjectInSpace objectInSpace, Ray ray, bool allowSnap)
        {
            //var viewport = ViewportControl.Viewport;

            //Vector2 mouse;
            //if( overrideMouse.HasValue )
            //	mouse = overrideMouse.Value;
            //else
            //{
            //	mouse = viewport.MousePosition;
            //	if( !new Rectangle( 0, 0, 1, 1 ).Contains( mouse ) )
            //		mouse = new Vector2( 0.5, 0.5 );
            //}

            //Ray ray;
            //if( overrideRay.HasValue )
            //	ray = overrideRay.Value;
            //else
            //	ray = viewport.CameraSettings.GetRayByScreenCoordinates( mouse );
            //!!!!? clamp max distance
            //ray.Direction = ray.Direction.GetNormalize() * 100;

            //!!!!можно конвекс форму делать вместо бокса
            Bounds localBounds = new Bounds();

            if (objectInSpace != null)
            {
                //particle system specific
                if (!(objectInSpace is Component_ParticleSystemInSpace))
                {
                    localBounds = objectInSpace.SpaceBounds.CalculatedBoundingBox - objectInSpace.Transform.Value.Position;
                }
            }
            if (localBounds.GetSize().X < 0.001)
            {
                localBounds.Expand(new Vector3(0.001, 0, 0));
            }
            if (localBounds.GetSize().Y < 0.001)
            {
                localBounds.Expand(new Vector3(0, 0.001, 0));
            }
            if (localBounds.GetSize().Z < 0.001)
            {
                localBounds.Expand(new Vector3(0, 0, 0.001));
            }

            double resultMinScale = 1.01;
            Component_ObjectInSpace resultMinScaleCollidedWith = null;

            if (objectInSpace != null)
            {
                //when objectInSpace != null

                Plane[] planes;
                {
                    var b1     = localBounds + ray.Origin;
                    var b2     = b1 + ray.Direction;
                    var points = CollectionUtility.Merge(b1.ToPoints(), b2.ToPoints());
                    ConvexHullAlgorithm.Create(points, out planes);
                }

                var item = new Component_Scene.GetObjectsInSpaceItem(Component_Scene.GetObjectsInSpaceItem.CastTypeEnum.All, null, true, planes);
                scene.GetObjectsInSpace(item);

                foreach (var resultItem in item.Result)
                {
                    if (objectInSpace != resultItem.Object && !resultItem.Object.GetAllParents(false).Contains(objectInSpace))
                    {
                        //mesh in space
                        if (resultItem.Object is Component_MeshInSpace meshInSpace)
                        {
                            Vector3[] verticesFull;
                            int[]     indices;
                            {
                                var b1     = localBounds + ray.Origin;
                                var b2     = b1 + ray.Direction;
                                var points = CollectionUtility.Merge(b1.ToPoints(), b2.ToPoints());
                                ConvexHullAlgorithm.Create(points, out verticesFull, out indices);
                            }

                            if (meshInSpace._Intersects(verticesFull, indices))
                            {
                                double minScale = 1.01;

                                double currentScale = 0.5;
                                //!!!!?
                                const double threshold = 0.00001;

                                double step = 0.25;
                                while (step > threshold)
                                {
                                    Vector3[] vertices = new Vector3[verticesFull.Length];
                                    for (int n = 0; n < vertices.Length; n++)
                                    {
                                        vertices[n] = verticesFull[n] - ray.Direction + ray.Direction * currentScale;
                                    }
                                    //Vector3[] vertices;
                                    //int[] indices;
                                    //{
                                    //	var b1 = localBounds + ray.Origin;
                                    //	var b2 = b1 + ray.Direction * currentScale;
                                    //	var points = CollectionUtility.Merge( b1.ToPoints(), b2.ToPoints() );
                                    //	ConvexHullAlgorithm.Create( points, out vertices, out indices );
                                    //}

                                    bool intersects = meshInSpace._Intersects(vertices, indices);

                                    if (!intersects)
                                    {
                                        minScale = currentScale;
                                    }

                                    if (intersects)
                                    {
                                        currentScale -= step;
                                    }
                                    else
                                    {
                                        currentScale += step;
                                    }
                                    step /= 2;
                                }

                                if (minScale <= 1 && minScale < resultMinScale)
                                {
                                    resultMinScale             = minScale;
                                    resultMinScaleCollidedWith = meshInSpace;
                                }
                            }
                        }

                        //!!!!какие еще
                    }
                }
            }
            else
            {
                //when objectInSpace == null

                var item = new Component_Scene.GetObjectsInSpaceItem(Component_Scene.GetObjectsInSpaceItem.CastTypeEnum.All, null, true, ray);
                scene.GetObjectsInSpace(item);

                foreach (var resultItem in item.Result)
                {
                    //mesh in space
                    if (resultItem.Object is Component_MeshInSpace meshInSpace)
                    {
                        if (meshInSpace.RayCast(ray, Component_Mesh.CompiledData.RayCastMode.Auto, out var scale, out var triangleIndex))
                        {
                            if (scale <= 1 && scale < resultMinScale)
                            {
                                resultMinScale             = scale;
                                resultMinScaleCollidedWith = meshInSpace;
                                //if( triangleIndex != -1 )
                                //{
                                //}
                            }
                        }
                    }

                    //!!!!какие еще
                }
            }

            bool    found;
            Vector3 pos;

            if (resultMinScale <= 1)
            {
                found = true;
                pos   = ray.GetPointOnRay(resultMinScale);
            }
            else
            {
                found = false;
                pos   = ray.Origin + ray.Direction.GetNormalize() * Math.Max(localBounds.GetBoundingSphere().Radius, 1) * 20;
            }

            //snap for 2D mode
            if (scene.Mode.Value == Component_Scene.ModeEnum._2D)
            {
                pos.Z = Math.Ceiling(pos.Z);
            }

            //snap
            if (allowSnap)
            {
                double snap;

                //if( Form.ModifierKeys.HasFlag( Keys.Control ) )
                snap = ProjectSettings.Get.SceneEditorStepMovement;
                //else
                //	snap = 0;
                if (snap != 0)
                {
                    Vector3 snapVec = new Vector3(snap, snap, snap);
                    pos += snapVec / 2;
                    pos /= snapVec;
                    pos  = new Vector3I((int)pos.X, (int)pos.Y, (int)pos.Z).ToVector3();
                    pos *= snapVec;
                }
            }

            //CalculateCreateObjectPositionUnderCursorEvent?.Invoke( objectInSpace, ref found, ref pos );

            return(found, pos, resultMinScaleCollidedWith);
            //objectToTransform.Transform = new Transform( pos, objectToTransform.Transform.Value.Rotation, objectToTransform.Transform.Value.Scale );
            //}
            //else
            //{
            //	var localBounds = objectInSpace.SpaceBounds.CalculatedBoundingBox - objectInSpace.Transform.Value.Position;

            //	//disable object to disable collisions
            //	var disable = ContainsPhysicsBodies( objectInSpace );
            //	if( disable )
            //		objectInSpace.Enabled = false;

            //	//!!!!contact group
            //	PhysicsConvexSweepTestItem castItem = new PhysicsConvexSweepTestItem( Matrix4.FromTranslate( ray.Origin ),
            //		Matrix4.FromTranslate( ray.Origin + ray.Direction ), 1, -1, PhysicsConvexSweepTestItem.ModeEnum.OneClosest, localBounds );
            //	Scene.PhysicsConvexSweepTest( new PhysicsConvexSweepTestItem[] { castItem } );

            //	//restore disabled object
            //	if( disable )
            //		objectInSpace.Enabled = true;

            //	Vector3 pos;
            //	if( castItem.Result.Length != 0 )
            //		pos = castItem.Result[ 0 ].Position;
            //	else
            //	{
            //		pos = ray.Origin + ray.Direction.GetNormalize() * Math.Max( localBounds.GetBoundingSphere().Radius, 1 ) * 20;
            //	}

            //	objectInSpace.Transform = new Transform( pos, objectInSpace.Transform.Value.Rotation, objectInSpace.Transform.Value.Scale );
            //}
        }