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 ); //} }