/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public ConvexHullTestDemo(DemosGame game) : base(game) { var random = new Random(5); for (int i = 0; i < 500000; ++i) { List<Vector3> points = new List<Vector3>(); for (int k = 0; k < random.Next(8, 60); k++) { points.Add(new Vector3(-100 + 30 * (float)random.NextDouble(), 100 + 500 * (float)random.NextDouble(), 100 + 30 * (float)random.NextDouble())); } var convexHull = new ConvexHull(new Vector3(0, 7, 0), points, 10); Console.WriteLine(convexHull.CollisionInformation.Shape.Vertices.Count); } var vertices = new[] { new Vector3(0, -1.750886E-9f, -1.5f), new Vector3(1, 1, 0.5f), new Vector3(1, -1, 0.5f), new Vector3(-1, 1, 0.5f), new Vector3(-1, -1, 0.5f), }; var hullVertices = new RawList<Vector3>(); ConvexHullHelper.GetConvexHull(vertices, hullVertices); ConvexHull hull = new ConvexHull(vertices, 5); Space.Add(hull); Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public RayCastTestDemo(DemosGame game) : base(game) { Space.Add(new Box(new Vector3(0, -0.5f, 0), 50, 1, 50)); //Put whatever you'd like to ray cast here. var capsule = new Capsule(new Vector3(0, 1.2f, 0), 1, 0.6f); capsule.AngularVelocity = new Vector3(1, 1, 1); Space.Add(capsule); var cylinder = new Cylinder(new Vector3(0, 5, 0), 2, .5f); cylinder.AngularVelocity = new Vector3(1, -1, 1); Space.Add(cylinder); var points = new List<Vector3>(); var random = new Random(0); for (int k = 0; k < 40; k++) { points.Add(new Vector3(1 * (float)random.NextDouble(), 3 * (float)random.NextDouble(), 2 * (float)random.NextDouble())); } var convexHull = new ConvexHull(new Vector3(0, 10, 0), points); convexHull.AngularVelocity = new Vector3(-1, 1, 1); Space.Add(convexHull); game.Camera.Position = new Vector3(-10, 5, 10); game.Camera.Yaw((float)Math.PI / -4f); game.Camera.Pitch(-(float)Math.PI / 9f); //Starter ray. origin = new Vector3(10, 5, 0); direction = new Vector3(-3, -1, 0); }
public void TestAllIdenticalPoints() { Coordinate[] pts = new Coordinate[100]; for (int i = 0; i < 100; i++) pts[i] = new Coordinate(0, 0); ConvexHull ch = new ConvexHull(pts, _geometryFactory); IGeometry actualGeometry = ch.GetConvexHull(); IGeometry expectedGeometry = _reader.Read("POINT (0 0)"); Assert.IsTrue(expectedGeometry.EqualsExact(actualGeometry)); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public GraphicMatchingDemo(DemosGame game) : base(game) { //When creating a collision shape based on a model, the graphic will generally be offset at first. //This is because the collision shape computes the center of mass and offsets itself to align with the local origin. //That offset must be applied to the graphic to make it match the collision shape. //Check out the documentation page for more information: //http://bepuphysics.codeplex.com/wikipage?title=Shape%20Recentering var model = game.Content.Load<Model>("guy"); BEPUutilities.Vector3[] vertices; int[] indices; ModelDataExtractor.GetVerticesAndIndicesFromModel(model, out vertices, out indices); //Create an entity based on the model. ConvexHull hull = new ConvexHull(vertices, 10); Space.Add(hull); //Create a graphic for the hull. The BEPUphysicsDrawer will also automatically receive a visualization of the convex hull which we can compare our graphic against. //The graphic will be offset from the collision shape because we have not attempted to offset it to match the collision shape's origin. var graphic = new DisplayEntityModel(hull, model, game.ModelDrawer); game.ModelDrawer.Add(graphic); //Now let's create another entity from the same vertices. hull = new ConvexHull(vertices, 10); Space.Add(hull); //Note that the prefab entity type ConvexHull uses the ConvexHullShape constructor internally, which outputs the computed center of the shape //prior to offset. The ConvexHull constructor sets the entity's Position to that position so that the initial world space location of the vertices //matches what was passed into the constructor. //The same process could be performed using this code: //Vector3 computedCenter; //var shape = new ConvexHullShape(vertices, out computedCenter); //<-- It spits out the computed center here; this is what is used to offset the graphic! //var entity = new Entity(shape, 10); //entity.Position = computedCenter; //Space.Add(entity); //For more information about constructing entities, check out the EntityConstructionDemo. //But for now, let's just use the prefab entity type. As mentioned earlier, the constructor set the entity's Position using the computed center. //Since we didn't overwrite it with some other position yet, we can still use it. graphic = new DisplayEntityModel(hull, model, game.ModelDrawer); graphic.LocalTransform = Matrix.CreateTranslation(-hull.Position); game.ModelDrawer.Add(graphic); //This graphic is perfectly aligned with the collision shape! Hooray! Box ground = new Box(new Vector3(0, -1.5f, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
public void TestManyIdenticalPoints() { Coordinate[] pts = new Coordinate[100]; for (int i = 0; i < 99; i++) pts[i] = new Coordinate(0, 0); pts[99] = new Coordinate(1, 1); ConvexHull ch = new ConvexHull(pts, _geometryFactory); IGeometry actualGeometry = ch.GetConvexHull(); IGeometry expectedGeometry = _reader.Read("LINESTRING (0 0, 1 1)"); Assert.IsTrue(actualGeometry.EqualsExact(expectedGeometry)); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public ConvexHullTestDemo(DemosGame game) : base(game) { var vertices = new[] { new Vector3(0, -1.750886E-9f, -1.5f), new Vector3(1, 1, 0.5f), new Vector3(1, -1, 0.5f), new Vector3(-1, 1, 0.5f), new Vector3(-1, -1, 0.5f), }; RawList<Vector3> hullVertices = new RawList<Vector3>(); ConvexHullHelper.GetConvexHull(vertices, hullVertices); ConvexHull hull = new ConvexHull(vertices, 5); ShapeDistributionInformation shapeInfo; hull.CollisionInformation.Shape.ComputeDistributionInformation(out shapeInfo); Space.Add(hull); Box ground = new Box(new Vector3(0, -.5f, 0), 50, 1, 50); Space.Add(ground); game.Camera.Position = new Vector3(0, 6, 15); }
// Use this for initialization void Start() { const int NumberOfVertices = 10; const float size = 20; const int dimension = 3; List <List <Vector3> > vc = new List <List <Vector3> > (); // vc.Add(new List<Vector3>(){ // new Vector3(-1,-1,-1) , // new Vector3(1,-1,-1), // new Vector3(-1,1,-1), // new Vector3(0,1,1), // new Vector3(-1,-1,1), // new Vector3(1,-1,1), // new Vector3(-1,1,1), // new Vector3(1,0,1), // new Vector3(1,0,-1), // new Vector3(0,1,-1) // }); //ALL VC POINTS: // //BAD BLOCK // //SHOULD BE BAD // vc.Add(new List<Vector3>(){ // new Vector3(-0.16764f,-0.0700706f,-0.5f), // new Vector3(-0.0464072f,-0.0647357f,-0.5f), // new Vector3(-0.144536f,0.237344f,-0.5f), // new Vector3(-0.149231f,0.240476f,-0.5f), // // new Vector3(-0.16764f,-0.0700706f,0.5f), // new Vector3(-0.0464072f,-0.0647357f,0.5f), // new Vector3(-0.144536f,0.237344f,0.5f), // new Vector3(-0.149231f,0.240476f,0.5f), // // }); // // //Fails on completely parallel triangles // vc.Add(new List<Vector3>(){ // new Vector3(-0.348162f,-0.0982212f,-0.5f), // new Vector3(-0.0326806f,-0.398012f,0.5f), // new Vector3(-0.348162f,-0.0982212f,0.5f), // //new Vector3(-0.0326806f,-0.398012f,-0.2f),//Introduced a way point // new Vector3(-0.0326806f,-0.398012f,-0.5f), // new Vector3(-0.232884f,-0.0832066f,-0.5f), // new Vector3(-0.232884f,-0.0832066f,0.5f), // // }); // //TEST #2 // vc.Add(new List<Vector3>(){ // new Vector3(-1f,-1f,-0.5f), // new Vector3(0.536051f,-1f,-0.5f), // new Vector3(-0.191468f,-0.375987f,-0.5f), // new Vector3(0.0555073f,-0.372317f,-0.5f), // new Vector3(-1f,-1f,0.5f), // new Vector3(0.536051f,-1f,0.5f), // new Vector3(0.0173284f,-0.361066f,0.5f), // new Vector3(0.0555073f,-0.372317f,0.5f), // new Vector3(0.0173284f,-0.361066f,-0.5f), // new Vector3(-1f,-0.795192f,-0.5f), // new Vector3(-1f,-0.795192f,0.5f), // new Vector3(-0.191468f,-0.375987f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.102548f,-0.119624f,-0.5f), // new Vector3(-0.0611588f,-0.0380439f,-0.5f), // new Vector3(0.00741258f,-0.118741f,0.5f), // new Vector3(0.00741258f,-0.118741f,-0.5f), // new Vector3(-0.102548f,-0.119624f,0.5f), // new Vector3(-0.006146f,-0.0269761f,-0.5f), // new Vector3(-0.0611588f,-0.0380439f,0.5f), // new Vector3(-0.006146f,-0.0269761f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.191468f,-0.375987f,0.5f), // new Vector3(-0.191468f,-0.375987f,-0.5f), // new Vector3(-0.0793624f,-0.200597f,-0.5f), // new Vector3(-0.0340186f,-0.214759f,0.5f), // new Vector3(0.0173284f,-0.361066f,0.5f), // new Vector3(-0.0340186f,-0.214759f,-0.5f), // new Vector3(-0.0793624f,-0.200597f,0.5f), // new Vector3(0.0173284f,-0.361066f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-1f,-0.795192f,-0.5f), // new Vector3(-0.0793624f,-0.200597f,-0.5f), // new Vector3(-0.107104f,-0.12395f,-0.5f), // new Vector3(-0.0793624f,-0.200597f,0.5f), // new Vector3(-1f,-0.795192f,0.5f), // new Vector3(-0.191468f,-0.375987f,0.5f), // new Vector3(-1f,-0.781501f,0.5f), // new Vector3(-1f,-0.781501f,-0.5f), // new Vector3(-0.191468f,-0.375987f,-0.5f), // new Vector3(-0.107104f,-0.12395f,0.5f), // new Vector3(-0.257323f,-0.0957589f,0.5f), // new Vector3(-0.257323f,-0.0957589f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.00741258f,-0.118741f,0.5f), // new Vector3(-0.0793624f,-0.200597f,-0.5f), // new Vector3(-0.107104f,-0.12395f,0.5f), // new Vector3(0.123349f,-0.160472f,0.5f), // new Vector3(-0.0340186f,-0.214759f,0.5f), // new Vector3(-0.0340186f,-0.214759f,-0.5f), // new Vector3(-0.0793624f,-0.200597f,0.5f), // new Vector3(-0.102548f,-0.119624f,0.5f), // new Vector3(-0.102548f,-0.119624f,-0.5f), // new Vector3(-0.107104f,-0.12395f,-0.5f), // new Vector3(0.12004f,-0.17124f,0.5f), // new Vector3(0.12004f,-0.17124f,-0.5f), // new Vector3(0.123349f,-0.160472f,-0.5f), // new Vector3(0.00741258f,-0.118741f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.257323f,-0.0957589f,0.5f), // new Vector3(-0.102548f,-0.119624f,0.5f), // new Vector3(-0.171954f,0.0668147f,0.5f), // new Vector3(-0.117652f,0.0686361f,-0.5f), // new Vector3(-0.257323f,-0.0957589f,-0.5f), // new Vector3(-0.107104f,-0.12395f,0.5f), // new Vector3(-0.124183f,0.0732046f,0.5f), // new Vector3(-0.0611588f,-0.0380439f,-0.5f), // new Vector3(-0.107104f,-0.12395f,-0.5f), // new Vector3(-0.102548f,-0.119624f,-0.5f), // new Vector3(-0.117652f,0.0686361f,0.5f), // new Vector3(-0.0611588f,-0.0380439f,0.5f), // new Vector3(-0.124183f,0.0732046f,-0.5f), // new Vector3(-0.171954f,0.0668147f,-0.5f), // new Vector3(-0.254036f,-0.0717289f,0.5f), // new Vector3(-0.254036f,-0.0717289f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.536051f,-1f,0.5f), // new Vector3(0.855617f,-1f,-0.5f), // new Vector3(0.121255f,-0.180823f,-0.5f), // new Vector3(0.121255f,-0.180823f,0.5f), // new Vector3(0.0555073f,-0.372317f,0.5f), // new Vector3(0.855617f,-1f,0.5f), // new Vector3(0.0555073f,-0.372317f,-0.5f), // new Vector3(0.536051f,-1f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.267402f,0.130015f,-0.5f), // new Vector3(1f,-0.194706f,0.5f), // new Vector3(0.165052f,-0.118485f,0.5f), // new Vector3(0.846305f,0.532869f,-0.5f), // new Vector3(1f,-0.194706f,-0.5f), // new Vector3(0.165052f,-0.118485f,-0.5f), // new Vector3(0.267402f,0.130015f,0.5f), // new Vector3(1f,0.59539f,-0.5f), // new Vector3(0.846305f,0.532869f,0.5f), // new Vector3(1f,0.59539f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.855617f,-1f,-0.5f), // new Vector3(1f,-1f,-0.5f), // new Vector3(0.121255f,-0.180823f,0.5f), // new Vector3(1f,-0.194706f,-0.5f), // new Vector3(0.855617f,-1f,0.5f), // new Vector3(1f,-1f,0.5f), // new Vector3(0.147274f,-0.12381f,-0.5f), // new Vector3(1f,-0.194706f,0.5f), // new Vector3(0.12004f,-0.17124f,0.5f), // new Vector3(0.121255f,-0.180823f,-0.5f), // new Vector3(0.123349f,-0.160472f,0.5f), // new Vector3(0.165052f,-0.118485f,-0.5f), // new Vector3(0.123349f,-0.160472f,-0.5f), // new Vector3(0.12004f,-0.17124f,-0.5f), // new Vector3(0.147274f,-0.12381f,0.5f), // new Vector3(0.165052f,-0.118485f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.12004f,-0.17124f,-0.5f), // new Vector3(-0.0340186f,-0.214759f,-0.5f), // new Vector3(0.12004f,-0.17124f,0.5f), // new Vector3(0.121255f,-0.180823f,0.5f), // new Vector3(0.0555073f,-0.372317f,-0.5f), // new Vector3(0.0555073f,-0.372317f,0.5f), // new Vector3(-0.0340186f,-0.214759f,0.5f), // new Vector3(0.121255f,-0.180823f,-0.5f), // new Vector3(0.0173284f,-0.361066f,0.5f), // new Vector3(0.0173284f,-0.361066f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.00741258f,-0.118741f,-0.5f), // new Vector3(0.123349f,-0.160472f,0.5f), // new Vector3(0.0657027f,0.00496402f,-0.5f), // new Vector3(0.0657027f,0.00496402f,0.5f), // new Vector3(0.00741258f,-0.118741f,0.5f), // new Vector3(0.123349f,-0.160472f,-0.5f), // new Vector3(-0.006146f,-0.0269761f,-0.5f), // new Vector3(-0.006146f,-0.0269761f,0.5f), // new Vector3(0.147274f,-0.12381f,-0.5f), // new Vector3(0.147274f,-0.12381f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-1f,-0.781501f,0.5f), // new Vector3(-0.660971f,0.601722f,-0.5f), // new Vector3(-1f,0.909721f,-0.5f), // new Vector3(-0.752045f,0.71827f,0.5f), // new Vector3(-0.257323f,-0.0957589f,-0.5f), // new Vector3(-0.254036f,-0.0717289f,-0.5f), // new Vector3(-1f,0.909721f,0.5f), // new Vector3(-0.752045f,0.71827f,-0.5f), // new Vector3(-1f,-0.781501f,-0.5f), // new Vector3(-0.660971f,0.601722f,0.5f), // new Vector3(-0.254036f,-0.0717289f,0.5f), // new Vector3(-0.257323f,-0.0957589f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.124183f,0.0732046f,0.5f), // new Vector3(0.0399654f,0.0694558f,0.5f), // new Vector3(-0.0225365f,0.3006f,-0.5f), // new Vector3(0.0399654f,0.0694558f,-0.5f), // new Vector3(-0.124183f,0.0732046f,-0.5f), // new Vector3(-0.0225365f,0.3006f,0.5f), // new Vector3(-0.117652f,0.0686361f,-0.5f), // new Vector3(-0.117652f,0.0686361f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.0680041f,0.0421237f,-0.5f), // new Vector3(-0.006146f,-0.0269761f,0.5f), // new Vector3(-0.117652f,0.0686361f,-0.5f), // new Vector3(0.0399654f,0.0694558f,0.5f), // new Vector3(0.0399654f,0.0694558f,-0.5f), // new Vector3(0.0680041f,0.0421237f,0.5f), // new Vector3(-0.0611588f,-0.0380439f,-0.5f), // new Vector3(0.0657027f,0.00496402f,0.5f), // new Vector3(-0.0611588f,-0.0380439f,0.5f), // new Vector3(-0.117652f,0.0686361f,0.5f), // new Vector3(-0.006146f,-0.0269761f,-0.5f), // new Vector3(0.0657027f,0.00496402f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.660971f,0.601722f,-0.5f), // new Vector3(-0.660971f,0.601722f,0.5f), // new Vector3(-0.254036f,-0.0717289f,-0.5f), // new Vector3(-0.171954f,0.0668147f,-0.5f), // new Vector3(-0.171954f,0.0668147f,0.5f), // new Vector3(-0.254036f,-0.0717289f,0.5f), // new Vector3(-0.254036f,-0.0717289f,0f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.171954f,0.0668147f,0.5f), // new Vector3(-0.124183f,0.0732046f,-0.5f), // new Vector3(-0.752045f,0.71827f,-0.5f), // new Vector3(-0.0219509f,0.323106f,0.5f), // new Vector3(-0.660971f,0.601722f,0.5f), // new Vector3(-0.124183f,0.0732046f,0.5f), // new Vector3(-0.752045f,0.71827f,0.5f), // new Vector3(-0.0219509f,0.323106f,-0.5f), // new Vector3(-0.660971f,0.601722f,-0.5f), // new Vector3(-0.171954f,0.0668147f,-0.5f), // new Vector3(-0.0225365f,0.3006f,-0.5f), // new Vector3(-0.0225365f,0.3006f,0.5f), // new Vector3(-0.0216151f,0.309922f,-0.5f), // new Vector3(-0.0216151f,0.309922f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.0219509f,0.323106f,0.5f), // new Vector3(0.151151f,0.0961385f,-0.5f), // new Vector3(-0.0219509f,0.323106f,-0.5f), // new Vector3(0.846305f,0.532869f,-0.5f), // new Vector3(0.267402f,0.130015f,-0.5f), // new Vector3(0.846305f,0.532869f,0.5f), // new Vector3(0.267402f,0.130015f,0.5f), // new Vector3(0.151151f,0.0961385f,0.5f), // new Vector3(-0.0216151f,0.309922f,-0.5f), // new Vector3(-0.0216151f,0.309922f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.151151f,0.0961385f,-0.5f), // new Vector3(0.0680041f,0.0421237f,0.5f), // new Vector3(-0.0225365f,0.3006f,-0.5f), // new Vector3(0.0399654f,0.0694558f,0.5f), // new Vector3(0.151151f,0.0961385f,0.5f), // new Vector3(-0.0216151f,0.309922f,-0.5f), // new Vector3(0.0399654f,0.0694558f,-0.5f), // new Vector3(0.0680041f,0.0421237f,-0.5f), // new Vector3(-0.0225365f,0.3006f,0.5f), // new Vector3(-0.0216151f,0.309922f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.0680041f,0.0421237f,-0.5f), // new Vector3(0.0657027f,0.00496402f,-0.5f), // new Vector3(0.151151f,0.0961385f,-0.5f), // new Vector3(0.267402f,0.130015f,-0.5f), // new Vector3(0.147274f,-0.12381f,-0.5f), // new Vector3(0.147274f,-0.12381f,0.5f), // new Vector3(0.151151f,0.0961385f,0.5f), // new Vector3(0.267402f,0.130015f,0.5f), // new Vector3(0.165052f,-0.118485f,-0.5f), // new Vector3(0.165052f,-0.118485f,0.5f), // new Vector3(0.0657027f,0.00496402f,0.5f), // new Vector3(0.0680041f,0.0421237f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-1f,0.909721f,0.5f), // new Vector3(1f,0.59539f,0.5f), // new Vector3(-1f,1f,-0.5f), // new Vector3(1f,1f,-0.5f), // new Vector3(-1f,0.909721f,-0.5f), // new Vector3(0.846305f,0.532869f,0.5f), // new Vector3(-1f,1f,0.5f), // new Vector3(1f,1f,0.5f), // new Vector3(-0.0219509f,0.323106f,0.5f), // new Vector3(-0.0219509f,0.323106f,-0.5f), // new Vector3(-0.752045f,0.71827f,0.5f), // new Vector3(-0.752045f,0.71827f,-0.5f), // new Vector3(0.846305f,0.532869f,-0.5f), // new Vector3(1f,0.59539f,-0.5f), // // }); // //TEST#3 // // vc.Add(new List<Vector3>(){ // new Vector3(-1f,-0.960555f,0.5f), // new Vector3(-1f,-0.960555f,-0.5f), // new Vector3(-1f,0.55324f,-0.5f), // new Vector3(-0.426258f,0.124114f,0.5f), // new Vector3(-0.304973f,-0.213889f,0.5f), // new Vector3(-0.479205f,0.176951f,0.5f), // new Vector3(-1f,0.55324f,0.5f), // new Vector3(-0.304973f,-0.213889f,-0.5f), // new Vector3(-0.426258f,0.124114f,-0.5f), // new Vector3(-0.479205f,0.176951f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.186329f,-0.243634f,0.5f), // new Vector3(-0.186329f,-0.243634f,-0.5f), // new Vector3(0.0540037f,-0.225309f,-0.5f), // new Vector3(0.0540037f,-0.225309f,0.5f), // new Vector3(-0.217051f,-0.197398f,0.5f), // new Vector3(-0.217051f,-0.197398f,-0.5f), // new Vector3(-0.151959f,-0.0789192f,0.5f), // new Vector3(-0.104137f,-0.077778f,0.5f), // new Vector3(-0.104137f,-0.077778f,-0.5f), // new Vector3(-0.151959f,-0.0789192f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.304973f,-0.213889f,-0.5f), // new Vector3(-0.217051f,-0.197398f,-0.5f), // new Vector3(-0.426258f,0.124114f,-0.5f), // new Vector3(-0.151959f,-0.0789192f,0.5f), // new Vector3(-0.304973f,-0.213889f,0.5f), // new Vector3(-0.217051f,-0.197398f,0.5f), // new Vector3(-0.426258f,0.124114f,0.5f), // new Vector3(-0.151959f,-0.0789192f,-0.5f), // new Vector3(-0.254596f,0.0110088f,-0.5f), // new Vector3(-0.254596f,0.0110088f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-1f,-1f,-0.5f), // new Vector3(-0.304973f,-0.213889f,-0.5f), // new Vector3(-0.186329f,-0.243634f,-0.5f), // new Vector3(-0.217051f,-0.197398f,0.5f), // new Vector3(-1f,-1f,0.5f), // new Vector3(-0.0660014f,-1f,-0.5f), // new Vector3(-0.217051f,-0.197398f,-0.5f), // new Vector3(-0.304973f,-0.213889f,0.5f), // new Vector3(-0.186329f,-0.243634f,0.5f), // new Vector3(-0.0660014f,-1f,0.5f), // new Vector3(-1f,-0.960555f,-0.5f), // new Vector3(-1f,-0.960555f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.0660014f,-1f,-0.5f), // new Vector3(0.298754f,-0.441025f,-0.5f), // new Vector3(-0.186329f,-0.243634f,-0.5f), // new Vector3(0.0854744f,-0.245537f,0.5f), // new Vector3(-0.0660014f,-1f,0.5f), // new Vector3(0.607584f,-1f,-0.5f), // new Vector3(-0.186329f,-0.243634f,0.5f), // new Vector3(0.0854744f,-0.245537f,-0.5f), // new Vector3(0.0540037f,-0.225309f,-0.5f), // new Vector3(0.0540037f,-0.225309f,0.5f), // new Vector3(0.298754f,-0.441025f,0.5f), // new Vector3(0.607584f,-1f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.00424733f,0.0677186f,-0.5f), // new Vector3(0.0854744f,-0.245537f,0.5f), // new Vector3(-0.104137f,-0.077778f,-0.5f), // new Vector3(0.0421851f,0.0652789f,-0.5f), // new Vector3(-0.104137f,-0.077778f,0.5f), // new Vector3(0.0540037f,-0.225309f,0.5f), // new Vector3(-0.00424733f,0.0677186f,0.5f), // new Vector3(0.0421851f,0.0652789f,0.5f), // new Vector3(0.0540037f,-0.225309f,-0.5f), // new Vector3(0.0854744f,-0.245537f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.22418f,0.03625f,0.5f), // new Vector3(0.298754f,-0.441025f,-0.5f), // new Vector3(0.0421851f,0.0652789f,-0.5f), // new Vector3(0.0854744f,-0.245537f,-0.5f), // new Vector3(0.298754f,-0.441025f,0.5f), // new Vector3(0.22418f,0.03625f,-0.5f), // new Vector3(0.0421851f,0.0652789f,0.5f), // new Vector3(0.0854744f,-0.245537f,0.5f), // new Vector3(0.174432f,0.0976613f,-0.5f), // new Vector3(0.174432f,0.0976613f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.0692106f,0.1823f,-0.5f), // new Vector3(-0.0473917f,0.169589f,-0.5f), // new Vector3(-0.150062f,0.303337f,-0.5f), // new Vector3(0.0137812f,0.261091f,0.5f), // new Vector3(-0.0692106f,0.1823f,0.5f), // new Vector3(-0.00990032f,0.297795f,-0.5f), // new Vector3(-0.150062f,0.303337f,0.5f), // new Vector3(-0.0296384f,0.314197f,-0.5f), // new Vector3(-0.0473917f,0.169589f,0.5f), // new Vector3(0.0137812f,0.261091f,-0.5f), // new Vector3(-0.0296384f,0.314197f,0.5f), // new Vector3(-0.00990032f,0.297795f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.0828026f,0.091434f,0.5f), // new Vector3(-0.426258f,0.124114f,0.5f), // new Vector3(-0.254596f,0.0110088f,0.5f), // new Vector3(-0.254596f,0.0110088f,-0.5f), // new Vector3(-0.0828026f,0.091434f,-0.5f), // new Vector3(-0.201087f,0.146032f,0.5f), // new Vector3(-0.201087f,0.146032f,-0.5f), // new Vector3(-0.426258f,0.124114f,-0.5f), // new Vector3(-0.479205f,0.176951f,0.5f), // new Vector3(-0.479205f,0.176951f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.479205f,0.176951f,-0.5f), // new Vector3(-0.0692106f,0.1823f,0.5f), // new Vector3(-1f,0.582126f,-0.5f), // new Vector3(-0.150062f,0.303337f,-0.5f), // new Vector3(-1f,0.55324f,-0.5f), // new Vector3(-0.201087f,0.146032f,0.5f), // new Vector3(-1f,0.582126f,0.5f), // new Vector3(-0.150062f,0.303337f,0.5f), // new Vector3(-0.201087f,0.146032f,-0.5f), // new Vector3(-0.0692106f,0.1823f,-0.5f), // new Vector3(-0.479205f,0.176951f,0.5f), // new Vector3(-1f,0.55324f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.201087f,0.146032f,0.5f), // new Vector3(-0.0692106f,0.1823f,0.5f), // new Vector3(-0.0473917f,0.169589f,0.5f), // new Vector3(-0.0179331f,0.0835178f,0.5f), // new Vector3(-0.0828026f,0.091434f,0.5f), // new Vector3(-0.0828026f,0.091434f,0f), // new Vector3(-0.201087f,0.146032f,-0.5f), // new Vector3(-0.0692106f,0.1823f,-0.5f), // new Vector3(-0.0828026f,0.091434f,-0.5f), // new Vector3(-0.0179331f,0.0835178f,-0.5f), // new Vector3(-0.0473917f,0.169589f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.254596f,0.0110088f,0.5f), // new Vector3(-0.151959f,-0.0789192f,0.5f), // new Vector3(-0.104137f,-0.077778f,0.5f), // new Vector3(-0.0828026f,0.091434f,-0.5f), // new Vector3(-0.0179331f,0.0835178f,-0.5f), // new Vector3(-0.0828026f,0.091434f,0.5f), // new Vector3(-0.0179331f,0.0835178f,0.5f), // new Vector3(-0.104137f,-0.077778f,-0.5f), // new Vector3(-0.254596f,0.0110088f,-0.5f), // new Vector3(-0.151959f,-0.0789192f,-0.5f), // new Vector3(-0.011291f,0.0763045f,0.5f), // new Vector3(-0.011291f,0.0763045f,-0.5f), // new Vector3(-0.00424733f,0.0677186f,-0.5f), // new Vector3(-0.00424733f,0.0677186f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.011291f,0.0763045f,0.5f), // new Vector3(-0.011291f,0.0763045f,-0.5f), // new Vector3(0.189929f,0.226259f,0.5f), // new Vector3(0.189929f,0.226259f,-0.5f), // new Vector3(0.174432f,0.0976613f,0.5f), // new Vector3(0.0421851f,0.0652789f,0.5f), // new Vector3(0.0536377f,0.249979f,-0.5f), // new Vector3(0.0536377f,0.249979f,0.5f), // new Vector3(-0.00424733f,0.0677186f,0.5f), // new Vector3(-0.00424733f,0.0677186f,-0.5f), // new Vector3(0.0421851f,0.0652789f,-0.5f), // new Vector3(0.174432f,0.0976613f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.22418f,0.03625f,-0.5f), // new Vector3(1f,0.27234f,-0.5f), // new Vector3(1f,0.792096f,-0.5f), // new Vector3(1f,0.792096f,0.5f), // new Vector3(0.174432f,0.0976613f,-0.5f), // new Vector3(1f,0.27234f,0.5f), // new Vector3(0.271967f,0.357577f,-0.5f), // new Vector3(0.271967f,0.357577f,0.5f), // new Vector3(0.189929f,0.226259f,-0.5f), // new Vector3(0.189929f,0.226259f,0.5f), // new Vector3(0.22418f,0.03625f,0.5f), // new Vector3(0.174432f,0.0976613f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.0473917f,0.169589f,0.5f), // new Vector3(0.0536377f,0.249979f,0.5f), // new Vector3(0.0137812f,0.261091f,0.5f), // new Vector3(-0.0179331f,0.0835178f,0.5f), // new Vector3(-0.011291f,0.0763045f,0.5f), // //new Vector3(-0.011291f,0.0763045f,0f), // new Vector3(-0.0473917f,0.169589f,-0.5f), // new Vector3(0.0536377f,0.249979f,-0.5f), // new Vector3(0.0137812f,0.261091f,-0.5f), // new Vector3(-0.0179331f,0.0835178f,-0.5f), // new Vector3(-0.011291f,0.0763045f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.0536377f,0.249979f,-0.5f), // new Vector3(0.189929f,0.226259f,-0.5f), // new Vector3(0.140247f,0.396627f,0.5f), // new Vector3(0.271967f,0.357577f,0.5f), // new Vector3(0.0137812f,0.261091f,0.5f), // new Vector3(0.189929f,0.226259f,0.5f), // new Vector3(0.0536377f,0.249979f,0.5f), // new Vector3(0.0137812f,0.261091f,-0.5f), // new Vector3(0.271967f,0.357577f,-0.5f), // new Vector3(0.140247f,0.396627f,-0.5f), // new Vector3(-0.00990032f,0.297795f,0.5f), // new Vector3(-0.00990032f,0.297795f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.607584f,-1f,0.5f), // new Vector3(1f,-1f,-0.5f), // new Vector3(0.22418f,0.03625f,-0.5f), // new Vector3(1f,0.27234f,-0.5f), // new Vector3(0.298754f,-0.441025f,0.5f), // new Vector3(1f,-1f,0.5f), // new Vector3(0.22418f,0.03625f,0.5f), // new Vector3(1f,0.27234f,0.5f), // new Vector3(0.298754f,-0.441025f,-0.5f), // new Vector3(0.607584f,-1f,-0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(-0.150062f,0.303337f,-0.5f), // new Vector3(-0.0296384f,0.314197f,-0.5f), // new Vector3(-1f,1f,-0.5f), // new Vector3(-0.360437f,1f,0.5f), // new Vector3(-1f,0.582126f,-0.5f), // new Vector3(-0.0296384f,0.314197f,0.5f), // new Vector3(-1f,1f,0.5f), // new Vector3(0.00799953f,0.465615f,0.5f), // new Vector3(0.00799953f,0.465615f,-0.5f), // new Vector3(-0.360437f,1f,-0.5f), // new Vector3(-0.150062f,0.303337f,0.5f), // new Vector3(-1f,0.582126f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.140247f,0.396627f,0.5f), // new Vector3(0.140247f,0.396627f,-0.5f), // new Vector3(0.00799953f,0.465615f,-0.5f), // new Vector3(0.00799953f,0.465615f,0.5f), // new Vector3(-0.0296384f,0.314197f,-0.5f), // new Vector3(-0.0296384f,0.314197f,0.5f), // new Vector3(-0.00990032f,0.297795f,-0.5f), // new Vector3(-0.00990032f,0.297795f,0.5f), // // }); // // vc.Add(new List<Vector3>(){ // new Vector3(0.00799953f,0.465615f,-0.5f), // new Vector3(1f,0.792096f,0.5f), // new Vector3(-0.360437f,1f,-0.5f), // new Vector3(1f,1f,-0.5f), // new Vector3(0.00799953f,0.465615f,0.5f), // new Vector3(0.140247f,0.396627f,-0.5f), // new Vector3(-0.360437f,1f,0.5f), // new Vector3(1f,1f,0.5f), // new Vector3(0.271967f,0.357577f,-0.5f), // new Vector3(1f,0.792096f,-0.5f), // new Vector3(0.271967f,0.357577f,0.5f), // new Vector3(0.140247f,0.396627f,0.5f), // // }); // vc.Add(new List<Vector3>(){ // new Vector3(-0.806506f,0.343989f,-0.5f), // new Vector3(0.0101658f,0.420679f,0.5f), // new Vector3(0.0101658f,0.420679f,-0.5f), // new Vector3(-0.14343f,0.205019f,0.5f), // new Vector3(-0.14343f,0.205019f,-0.5f), // //new Vector3(-0.806506f,0.343989f,0f), // new Vector3(-0.806506f,0.343989f,0.5f), // // }); vc.Add(new List <Vector3>() { new Vector3(-1f, -1f, -0.5f), new Vector3(-0.0448597f, -0.598239f, -0.5f), new Vector3(-1f, -0.362044f, -0.5f), new Vector3(-0.385575f, -0.221627f, -0.5f), new Vector3(-1f, -1f, 0.5f), new Vector3(-0.385575f, -0.221627f, 0.5f), new Vector3(-1f, -0.362044f, 0.5f), new Vector3(-0.103467f, -1f, -0.5f), new Vector3(-0.18347f, -0.420897f, -0.5f), new Vector3(-0.18347f, -0.420897f, 0.5f), new Vector3(-0.0448597f, -0.598239f, 0.5f), new Vector3(-0.103467f, -1f, 0.5f), }); vc.Add(new List <Vector3>() { new Vector3(-0.0448597f, -0.598239f, -0.5f), new Vector3(1f, -1f, -0.5f), new Vector3(-0.103467f, -1f, 0.5f), new Vector3(0.518295f, -0.459347f, -0.5f), new Vector3(-0.103467f, -1f, -0.5f), new Vector3(1f, -1f, 0.5f), new Vector3(0.0743321f, -0.34692f, -0.5f), new Vector3(1f, -0.709246f, -0.5f), new Vector3(0.518295f, -0.459347f, 0.5f), new Vector3(1f, -0.709246f, 0.5f), new Vector3(-0.0448597f, -0.598239f, 0.5f), new Vector3(0.0743321f, -0.34692f, 0.5f), }); vc.Add(new List <Vector3>() { new Vector3(0.0743321f, -0.34692f, 0.5f), new Vector3(0.518295f, -0.459347f, -0.5f), new Vector3(0.222638f, -0.250217f, -0.5f), new Vector3(0.356161f, -0.286853f, -0.5f), new Vector3(0.079184f, -0.323635f, 0.5f), new Vector3(0.518295f, -0.459347f, 0.5f), new Vector3(0.222638f, -0.250217f, 0.5f), new Vector3(0.356161f, -0.286853f, 0.5f), new Vector3(0.079184f, -0.323635f, -0.5f), new Vector3(0.0743321f, -0.34692f, -0.5f), }); vc.Add(new List <Vector3>() { new Vector3(-0.385575f, -0.221627f, -0.5f), new Vector3(-1f, 0.144961f, 0.5f), new Vector3(-0.312959f, -0.137179f, -0.5f), new Vector3(-0.684528f, 0.136085f, 0.5f), new Vector3(-1f, -0.362044f, -0.5f), new Vector3(-0.312959f, -0.137179f, 0.5f), new Vector3(-0.684528f, 0.136085f, -0.5f), new Vector3(-1f, 0.144961f, -0.5f), new Vector3(-0.385575f, -0.221627f, 0.5f), new Vector3(-1f, -0.362044f, 0.5f), }); vc.Add(new List <Vector3>() { new Vector3(-0.684528f, 0.136085f, -0.5f), new Vector3(-0.312959f, -0.137179f, 0.5f), new Vector3(-0.283868f, 0.0376008f, 0.5f), new Vector3(-0.312959f, -0.137179f, -0.5f), new Vector3(-0.343069f, 0.143474f, 0.5f), new Vector3(-0.312229f, -0.136512f, 0.5f), new Vector3(-0.684528f, 0.136085f, 0.5f), new Vector3(-0.312229f, -0.136512f, -0.5f), new Vector3(-0.283868f, 0.0376008f, -0.5f), new Vector3(-0.343069f, 0.143474f, -0.5f), }); vc.Add(new List <Vector3>() { new Vector3(-0.312229f, -0.136512f, 0.5f), new Vector3(-0.385575f, -0.221627f, -0.5f), new Vector3(-0.312229f, -0.136512f, -0.5f), new Vector3(-0.216008f, -0.160551f, -0.5f), new Vector3(-0.18347f, -0.420897f, 0.5f), new Vector3(-0.18347f, -0.420897f, -0.5f), new Vector3(-0.312959f, -0.137179f, -0.5f), new Vector3(-0.216008f, -0.160551f, 0.5f), new Vector3(-0.312959f, -0.137179f, 0.5f), new Vector3(-0.385575f, -0.221627f, 0.5f), }); vc.Add(new List <Vector3>() { new Vector3(-0.312229f, -0.136512f, -0.5f), new Vector3(-0.216008f, -0.160551f, -0.5f), new Vector3(0.0139972f, -0.15204f, -0.5f), new Vector3(0.0153618f, -0.0473141f, -0.5f), new Vector3(-0.312229f, -0.136512f, 0.5f), new Vector3(-0.216008f, -0.160551f, 0.5f), new Vector3(-0.283868f, 0.0376008f, -0.5f), new Vector3(-0.283868f, 0.0376008f, 0.5f), new Vector3(-0.0237972f, -0.020674f, -0.5f), new Vector3(-0.0237972f, -0.020674f, 0.5f), new Vector3(0.0153618f, -0.0473141f, 0.5f), new Vector3(0.0139972f, -0.15204f, 0.5f), }); vc.Add(new List <Vector3>() { new Vector3(-0.0448597f, -0.598239f, 0.5f), new Vector3(0.079184f, -0.323635f, -0.5f), new Vector3(-0.216008f, -0.160551f, -0.5f), new Vector3(0.0139972f, -0.15204f, -0.5f), new Vector3(-0.18347f, -0.420897f, 0.5f), new Vector3(0.0743321f, -0.34692f, -0.5f), new Vector3(-0.216008f, -0.160551f, 0.5f), new Vector3(0.0139972f, -0.15204f, 0.5f), new Vector3(-0.18347f, -0.420897f, -0.5f), new Vector3(-0.0448597f, -0.598239f, -0.5f), new Vector3(0.079184f, -0.323635f, 0.5f), new Vector3(0.0743321f, -0.34692f, 0.5f), }); vc.Add(new List <Vector3>() { new Vector3(0.335603f, -0.119844f, -0.5f), new Vector3(0.0139972f, -0.15204f, -0.5f), new Vector3(0.079184f, -0.323635f, 0.5f), new Vector3(0.307884f, 0.0428469f, -0.5f), new Vector3(0.222638f, -0.250217f, 0.5f), new Vector3(0.0139972f, -0.15204f, 0.5f), new Vector3(0.335603f, -0.119844f, 0.5f), new Vector3(0.307884f, 0.0428469f, 0.5f), new Vector3(0.0277375f, -0.0346146f, -0.5f), new Vector3(0.0153618f, -0.0473141f, -0.5f), new Vector3(0.079184f, -0.323635f, -0.5f), new Vector3(0.222638f, -0.250217f, -0.5f), new Vector3(0.0153618f, -0.0473141f, 0.5f), new Vector3(0.0277375f, -0.0346146f, 0.5f), }); vc.Add(new List <Vector3>() { new Vector3(0.335603f, -0.119844f, 0.5f), new Vector3(1f, -0.206532f, -0.5f), new Vector3(0.307884f, 0.0428469f, -0.5f), new Vector3(1f, 1f, -0.5f), new Vector3(0.335603f, -0.119844f, -0.5f), new Vector3(1f, -0.206532f, 0.5f), new Vector3(0.683389f, 0.692466f, 0.5f), new Vector3(1f, 1f, 0.5f), new Vector3(0.544173f, -0.176223f, -0.5f), new Vector3(0.544173f, -0.176223f, 0.5f), new Vector3(0.307884f, 0.0428469f, 0.5f), new Vector3(0.906816f, 1f, 0.5f), new Vector3(0.906816f, 1f, -0.5f), new Vector3(0.683389f, 0.692466f, -0.5f), }); vc.Add(new List <Vector3>() { new Vector3(0.356161f, -0.286853f, -0.5f), new Vector3(1f, -0.709246f, 0.5f), new Vector3(0.544173f, -0.176223f, -0.5f), new Vector3(1f, -0.206532f, -0.5f), new Vector3(0.356161f, -0.286853f, 0.5f), new Vector3(0.518295f, -0.459347f, 0.5f), new Vector3(0.544173f, -0.176223f, 0.5f), new Vector3(1f, -0.206532f, 0.5f), new Vector3(0.518295f, -0.459347f, -0.5f), new Vector3(1f, -0.709246f, -0.5f), }); vc.Add(new List <Vector3>() { new Vector3(0.335603f, -0.119844f, -0.5f), new Vector3(0.222638f, -0.250217f, -0.5f), new Vector3(0.335603f, -0.119844f, 0.5f), new Vector3(0.544173f, -0.176223f, -0.5f), new Vector3(0.356161f, -0.286853f, -0.5f), new Vector3(0.544173f, -0.176223f, 0.5f), new Vector3(0.356161f, -0.286853f, 0.5f), new Vector3(0.222638f, -0.250217f, 0.5f), }); vc.Add(new List <Vector3>() { new Vector3(-1f, 0.144961f, 0.5f), new Vector3(-0.300478f, 0.206166f, 0.5f), new Vector3(-1f, 1f, -0.5f), new Vector3(-0.738741f, 1f, -0.5f), new Vector3(-1f, 0.144961f, -0.5f), new Vector3(-0.332252f, 0.156636f, -0.5f), new Vector3(-1f, 1f, 0.5f), new Vector3(-0.738741f, 1f, 0.5f), new Vector3(-0.302425f, 0.202496f, -0.5f), new Vector3(-0.300478f, 0.206166f, -0.5f), new Vector3(-0.302425f, 0.202496f, 0.5f), new Vector3(-0.332252f, 0.156636f, 0.5f), new Vector3(-0.343069f, 0.143474f, 0.5f), new Vector3(-0.343069f, 0.143474f, -0.5f), new Vector3(-0.684528f, 0.136085f, 0.5f), new Vector3(-0.684528f, 0.136085f, -0.5f), }); vc.Add(new List <Vector3>() { new Vector3(-0.283868f, 0.0376008f, 0.5f), new Vector3(-0.0237972f, -0.020674f, -0.5f), new Vector3(-0.332252f, 0.156636f, -0.5f), new Vector3(-0.0815209f, 0.114455f, -0.5f), new Vector3(-0.343069f, 0.143474f, 0.5f), new Vector3(-0.0237972f, -0.020674f, 0.5f), new Vector3(-0.332252f, 0.156636f, 0.5f), new Vector3(-0.0815209f, 0.114455f, 0.5f), new Vector3(-0.343069f, 0.143474f, -0.5f), new Vector3(-0.283868f, 0.0376008f, -0.5f), }); vc.Add(new List <Vector3>() { new Vector3(-0.0986741f, 0.419068f, 0.5f), new Vector3(-0.0840575f, 0.147685f, -0.5f), new Vector3(-0.0986741f, 0.419068f, -0.5f), new Vector3(-0.0585627f, 0.273246f, -0.5f), new Vector3(-0.302425f, 0.202496f, -0.5f), new Vector3(-0.0840575f, 0.147685f, 0.5f), new Vector3(-0.302425f, 0.202496f, 0.5f), new Vector3(-0.0585627f, 0.273246f, 0.5f), new Vector3(-0.300478f, 0.206166f, -0.5f), new Vector3(-0.300478f, 0.206166f, 0.5f), }); vc.Add(new List <Vector3>() { new Vector3(-0.0840575f, 0.147685f, 0.5f), new Vector3(-0.0840575f, 0.147685f, -0.5f), new Vector3(-0.0585627f, 0.273246f, 0.5f), new Vector3(0.0277375f, -0.0346146f, 0.5f), new Vector3(-0.0237972f, -0.020674f, -0.5f), new Vector3(0.0675767f, 0.128497f, 0.5f), new Vector3(-0.0585627f, 0.273246f, -0.5f), new Vector3(0.0675767f, 0.128497f, -0.5f), new Vector3(-0.0815209f, 0.114455f, 0.5f), new Vector3(-0.0815209f, 0.114455f, -0.5f), new Vector3(0.0153618f, -0.0473141f, 0.5f), new Vector3(-0.0237972f, -0.020674f, 0.5f), new Vector3(0.0153618f, -0.0473141f, -0.5f), new Vector3(0.0277375f, -0.0346146f, -0.5f), }); vc.Add(new List <Vector3>() { new Vector3(-0.332252f, 0.156636f, -0.5f), new Vector3(-0.302425f, 0.202496f, -0.5f), new Vector3(-0.0815209f, 0.114455f, 0.5f), new Vector3(-0.302425f, 0.202496f, 0.5f), new Vector3(-0.332252f, 0.156636f, 0.5f), new Vector3(-0.0815209f, 0.114455f, -0.5f), new Vector3(-0.0840575f, 0.147685f, -0.5f), new Vector3(-0.0840575f, 0.147685f, 0.5f), }); vc.Add(new List <Vector3>() { new Vector3(0.683389f, 0.692466f, 0.5f), new Vector3(0.0277375f, -0.0346146f, -0.5f), new Vector3(0.0675767f, 0.128497f, -0.5f), new Vector3(0.683389f, 0.692466f, -0.5f), new Vector3(0.307884f, 0.0428469f, 0.5f), new Vector3(0.307884f, 0.0428469f, -0.5f), new Vector3(0.0277375f, -0.0346146f, 0.5f), new Vector3(0.0675767f, 0.128497f, 0.5f), }); vc.Add(new List <Vector3>() { new Vector3(0.0675767f, 0.128497f, -0.5f), new Vector3(0.683389f, 0.692466f, -0.5f), new Vector3(-0.0585627f, 0.273246f, 0.5f), new Vector3(0.906816f, 1f, -0.5f), new Vector3(0.0675767f, 0.128497f, 0.5f), new Vector3(0.683389f, 0.692466f, 0.5f), new Vector3(0.114596f, 1f, -0.5f), new Vector3(0.906816f, 1f, 0.5f), new Vector3(-0.0986741f, 0.419068f, -0.5f), new Vector3(-0.0585627f, 0.273246f, -0.5f), new Vector3(-0.0986741f, 0.419068f, 0.5f), new Vector3(0.114596f, 1f, 0.5f), }); vc.Add(new List <Vector3>() { new Vector3(-0.738741f, 1f, 0.5f), new Vector3(0.114596f, 1f, -0.5f), new Vector3(-0.738741f, 1f, -0.5f), new Vector3(-0.300478f, 0.206166f, -0.5f), new Vector3(-0.300478f, 0.206166f, 0.5f), new Vector3(-0.0986741f, 0.419068f, -0.5f), new Vector3(0.114596f, 1f, 0.5f), new Vector3(-0.0986741f, 0.419068f, 0.5f), }); var cc = 0; foreach (var vv in vc) { cc++; randomVerts = vv; var vertices = new List <Vertex> (); var color = new Color(139.0f / 255f, 244f / 255f, 23f / 255f, 1); if (cc % 2 == 0) { color = new Color(255f / 255f, 0, 240f / 255f); } if (cc % 3 == 0) { color = new Color(0f / 255f, 255f / 255f, 252f / 255f); } //new Color (UnityEngine.Random.Range (0.0f, 1.0f), // UnityEngine.Random.Range (0.0f, 1.0f), // UnityEngine.Random.Range (0.0f, 1.0f)); //add a random control point in the center? // // vv.Add( Vector3.Scale( Vector3.Normalize (new Vector3 (randomVerts [1].x, randomVerts [1].y, randomVerts [1].z) // - new Vector3 (randomVerts [0].x, randomVerts [0].y, randomVerts [0].z)), new Vector3(0.1f,0.1f,0.1f)) // + new Vector3 (randomVerts [0].x, randomVerts [0].y, randomVerts [0].z)); //control point seems to have to be in z-depth? //vv.Add(new Vector3(randomVerts[1].x, randomVerts[1].y, 0f); Debug.Log(String.Format("{0} - {1} - {2}", cc, vv.Count(), randomVerts.Count)); foreach (var v in vv) { var location = new double[dimension]; location [0] = v.x; location [1] = v.y; location [2] = v.z; vertices.Add(new Vertex(location)); } // for (var i = 0; i < NumberOfVertices; i++) // { // var location = new double[dimension]; // for (var j = 0; j < dimension; j++) // location[j] = UnityEngine.Random.Range(0,size); // // var v = new Vertex (location); // vertices.Add(v); // randomVerts.Add (new Vector3((float)location[0], (float)location[1], 0f)); // } voronoi = VoronoiMesh.Create(vertices); //var delaunay = Triangulation.CreateDelaunay<Vertex> (vertices); //var c = Triangulation.CreateDelaunay<Vertex, Tetrahedron>(vertices).Cells; //verticesList = new List<Vector3> (); //lines = new List<Vector3[]> (); var convexHull = ConvexHull.Create <Vertex>(vertices); foreach (var f in convexHull.Faces) { _CreateTriangle(f.ToString(), new Vector3[] { _CreateVector3FromPosition(f.Vertices[0]), _CreateVector3FromPosition(f.Vertices[1]), _CreateVector3FromPosition(f.Vertices[2]) }); } // foreach (var e in voronoi.Vertices) { // //CreateTriangles (e); // CreateTetrahedron (cc, e,color); // } } // foreach (var e in voronoi.Edges) { // var l = e; // // lines.Add (new Vector3[]{ // new Vector3((float)e.Source.Vertices[0].Position[0], // (float)e.Source.Vertices[0].Position[1], // 0.0f), // new Vector3((float)e.Target.Vertices[0].Position[0], // (float)e.Target.Vertices[0].Position[1], // 0.0f) // // }); // // } // var component = GetComponent<MeshFilter> ().mesh; }
public static List <Point3D> GetFootPrintNonBREP(IIfcProduct ifcElement, Xbim3DModelContext context) { var resultList = new List <Point3D>(); foreach (XbimShapeInstance instance in context.ShapeInstancesOf(ifcElement)) { // Get the IFC Representation of the Footprint of the instance XbimShapeGeometry geometry = context.ShapeGeometry(instance); var data = ((IXbimShapeGeometryData)geometry).ShapeData; using (var stream = new MemoryStream(data)) { using (var reader = new BinaryReader(stream)) { XbimShapeTriangulation mesh = reader.ReadShapeTriangulation(); mesh = mesh.Transform(instance.Transformation); // find the minimal z coordinate double minZ = 10000; foreach (var vertex in mesh.Vertices) { if (vertex.Z <= minZ) { minZ = vertex.Z; } } List <IVertex> points = new List <IVertex>(); foreach (var vertex in mesh.Vertices) { if (vertex.Z != minZ) { continue; } points.Add(new DefaultVertex { Position = new[] { vertex.X, vertex.Y } }); } if (points.Count <= 2) { return(null); } // Compute ConvexHull var cH = ConvexHull.Create(points); foreach (var item in cH.Points) { var point = new Point3D() { X = item.Position[0], Y = item.Position[1], Z = minZ }; bool duplicate = false; foreach (var result in resultList) { if (result == point) { duplicate = true; break; } } if (!duplicate) { resultList.Add(point); } } } } } return(resultList); }
public void Start() { gameManager = GameObject.Find("GameManager").GetComponent <GameManager>(); if (transform.childCount == 0) { vertices = new GameObject[verticesList.Count]; int k = 0; foreach (KeyValuePair <string, Vector3> entry in verticesList) { vertices[k] = GameObject.Instantiate(gameManager.vertexPrefab, (Vector3)entry.Value, Quaternion.identity) as GameObject; vertices[k].name = (string)entry.Key; vertices[k].tag = "Vertex"; vertices[k].transform.parent = transform; k++; } k = 0; } else { vertices = GameObject.FindGameObjectsWithTag("Vertex").ToList().OrderBy(go => go.name).ToList().ToArray(); } if (debugRawData == true) { string s = ""; s += "vertices: \n" + vertices.Select(i => i.name + " -> " + i.transform.position.ToString() + "\n").Aggregate((i, j) => i + "" + j); if (adjacencyList.Length != 0) { s += "adjacency: \n" + adjacencyList.Select(i => i.ToString() + "\n").Aggregate((i, j) => i + "" + j); } Debug.Log(s); } originalPositionVertices = new Vector3[vertices.Length]; centroid = GameObject.CreatePrimitive(PrimitiveType.Sphere); centroid.name = "centroid"; centroid.GetComponent <Renderer>().enabled = false; centroid.GetComponent <SphereCollider>().enabled = false; Vector2 radius = new Vector2(15, 15); Vector3 centroid_position = Vector3.zero; Vector3[] points = new Vector3[vertices.Length]; for (int i = 0; i < vertices.Length; i++) { int flag = isVertexinAdjacencyList(vertices[i].name); if (flag >= 0) { foreach (string vertex in RHS(adjacencyList)[flag].Split(","[0])) { vertices[i].GetComponent <Vertex>().AddNeighbour(FindVertexByName(vertex)); } } } for (int i = 0; i < vertices.Length; i++) { originalPositionVertices[i] = vertices[i].transform.position; float _i = (i * 1.0f) / vertices.Length; float angle = _i * Mathf.PI * 2; points[i] = originalPositionVertices[i]; vertices[i].transform.position = new Vector3(Mathf.Sin(angle) * radius.x, Mathf.Cos(angle) * radius.y, 0.0f); if (vertices[i].GetComponent <Vertex>() != null) { if (vertices[i].GetComponent <Vertex>().getNeighbours() != null) { foreach (GameObject neighbour in vertices[i].GetComponent <Vertex>().getNeighbours()) { if (neighbour != null && neighbour.GetComponent <Vertex>().getNeighbours() != null) { if (!neighbour.GetComponent <Vertex>().getNeighbours().Contains(vertices[i])) { neighbour.GetComponent <Vertex>().AddNeighbour(vertices[i]); if (!vertices[i].GetComponent <Vertex>().getNeighbours().Contains(neighbour)) { vertices[i].GetComponent <Vertex>().AddNeighbour(neighbour); } } } } } } //Debug.Log(originalPositionVertices[i]); centroid_position += originalPositionVertices[i]; } centroid_position /= vertices.Length; centroid.transform.position = centroid_position; List <Vector3> convexHull = ConvexHull.ComputeConvexHull(points); area = ConvexHull.PolygonArea(convexHull); }
private static bool GetHull( List <Autodesk.Revit.DB.XYZ> pts, List <Autodesk.Revit.DB.UV> uvs, double tolerance, out List <Autodesk.Revit.DB.XYZ> hullPts, out List <Autodesk.Revit.DB.UV> hullUvs) { hullPts = new List <Autodesk.Revit.DB.XYZ>(); hullUvs = new List <Autodesk.Revit.DB.UV>(); if (!pts.Any() || !uvs.Any()) { return(false); } try { var hullPoints = uvs.Select(x => new HullPoint(x.U, x.V)).ToList(); var hull = ConvexHull.MakeHull(hullPoints); var hUvs = hull.Select(x => new Autodesk.Revit.DB.UV(x.x, x.y)).ToList(); var hPts = hUvs.Select(x => pts[uvs.FindIndex(y => y.IsAlmostEqualTo(x))]).ToList(); var indexToRemove = -1; Restart: if (indexToRemove != -1) { hPts.RemoveAt(indexToRemove); hUvs.RemoveAt(indexToRemove); // ReSharper disable once RedundantAssignment indexToRemove = -1; } for (var i = 0; i < hPts.Count; i++) { var start = hPts[i]; Autodesk.Revit.DB.XYZ middle; Autodesk.Revit.DB.XYZ end; int middleIndex; if (i + 2 == hPts.Count) { middle = hPts[i + 1]; middleIndex = i + 1; end = hPts[0]; } else if (i + 1 == hPts.Count) { middle = hPts[0]; middleIndex = 0; end = hPts[1]; } else { middle = hPts[i + 1]; middleIndex = i + 1; end = hPts[i + 2]; } if (start.DistanceTo(end) < tolerance) { continue; } var line = Autodesk.Revit.DB.Line.CreateBound(start, end); var intResult = line.Project(middle); if (intResult.Distance > 0.01) { continue; } indexToRemove = middleIndex; goto Restart; } hullPts = hPts; hullUvs = hUvs; return(true); } catch (Exception) { return(false); } }
/// <summary> /// The SpacePlanningZones function. /// </summary> /// <param name="model">The input model.</param> /// <param name="input">The arguments to the execution.</param> /// <returns>A SpacePlanningZonesOutputs instance containing computed results and the model with any new elements.</returns> public static SpacePlanningZonesOutputs Execute(Dictionary <string, Model> inputModels, SpacePlanningZonesInputs input) { var corridorWidth = input.CorridorWidth; var corridorMat = SpaceBoundary.MaterialDict["Circulation"]; var output = new SpacePlanningZonesOutputs(); var levelsModel = inputModels["Levels"]; var levelVolumes = levelsModel.AllElementsOfType <LevelVolume>(); inputModels.TryGetValue("Floors", out var floorsModel); var coresModel = inputModels["Core"]; var cores = coresModel.AllElementsOfType <ServiceCore>(); var random = new Random(5); var levels = new List <LevelElements>(); var levelMappings = new Dictionary <Guid, (SpaceBoundary boundary, LevelElements level)>(); if (levelVolumes.Count() == 0) { throw new Exception("This function requires LevelVolumes, produced by functions like \"Simple Levels by Envelope\". Try using a different levels function."); } if (cores.Count() == 0) { throw new Exception("No ServiceCore elements were found in the model."); } foreach (var lvl in levelVolumes) { var spaceBoundaries = new List <Element>(); if (floorsModel != null) { var floorAtLevel = floorsModel.AllElementsOfType <Floor>().FirstOrDefault(f => Math.Abs(lvl.Transform.Origin.Z - f.Transform.Origin.Z) < (f.Thickness * 1.1)); if (floorAtLevel != null) { lvl.Height -= floorAtLevel.Thickness; var floorFaceOffset = (floorAtLevel.Transform.Origin.Z + floorAtLevel.Thickness) - lvl.Transform.Origin.Z; if (floorFaceOffset > 0.001) { lvl.Transform.Concatenate(new Transform(0, 0, floorFaceOffset)); lvl.Height -= floorFaceOffset; } } } List <Profile> corridorProfiles = new List <Profile>(); var TOO_SHORT = 9; var levelBoundary = new Profile(lvl.Profile.Perimeter, lvl.Profile.Voids, Guid.NewGuid(), null); var coresInBoundary = cores.Where(c => levelBoundary.Contains(c.Centroid)).ToList(); foreach (var core in coresInBoundary) { levelBoundary.Voids.Add(new Polygon(core.Profile.Perimeter.Vertices).Reversed()); levelBoundary.OrientVoids(); } var perimeter = levelBoundary.Perimeter; var perimeterSegments = perimeter.Segments(); var perimeterAngles = new List <double>(); for (int i = 0; i < perimeter.Vertices.Count; i++) { var nextIndex = (i + 1) % perimeter.Vertices.Count; var prevIndex = (i + perimeter.Vertices.Count - 1) % perimeter.Vertices.Count; var prevVec = perimeter.Vertices[i] - perimeter.Vertices[prevIndex]; var nextVec = perimeter.Vertices[nextIndex] - perimeter.Vertices[i]; var angle = prevVec.PlaneAngleTo(nextVec); perimeterAngles.Add(angle); } var allLengths = perimeterSegments.Select(s => s.Length()); var validLengths = allLengths.Where(l => l > TOO_SHORT)?.OrderBy(l => l); var shortLength = (validLengths?.FirstOrDefault() ?? 35 / 1.2) * 1.2; var longLength = Math.Min(validLengths.SkipLast(1).Last(), 50); var shortEdges = new List <Line>(); var shortEdgeIndices = new List <int>(); for (int i = 0; i < perimeterSegments.Count(); i++) { var start = perimeterAngles[i]; var end = perimeterAngles[(i + 1) % perimeterAngles.Count]; if (start > 80 && start < 100 && end > 80 && end < 100 && perimeterSegments[i].Length() < longLength) { shortEdges.Add(perimeterSegments[i]); shortEdgeIndices.Add(i); } } // Single Loaded Zones var singleLoadedZones = new List <(Polygon hull, Line centerLine)>(); var singleLoadedLengthThreshold = input.OuterBandDepth * 2 + corridorWidth * 2 + 5; // (two offsets, two corridors, and a usable space width) foreach (var sei in shortEdgeIndices) { var ps = perimeterSegments; if (ps[sei].Length() < singleLoadedLengthThreshold) { var legSegments = new[] { ps[(sei + ps.Length - 1) % ps.Length], ps[sei], ps[(sei + 1) % ps.Length] }; var legLength = Math.Min(legSegments[0].Length(), legSegments[2].Length()); legSegments[0] = new Line(ps[sei].Start, ps[sei].Start + legLength * (legSegments[0].Direction() * -1)); legSegments[2] = new Line(ps[sei].End, ps[sei].End + legLength * (legSegments[2].Direction())); var hull = ConvexHull.FromPolylines(legSegments.Select(l => l.ToPolyline(1))); var centerLine = new Line((legSegments[0].Start + legSegments[2].Start) / 2, (legSegments[0].End + legSegments[2].End) / 2); singleLoadedZones.Add((hull, centerLine)); } } var shortEdgesExtended = shortEdges.Select(l => new Line(l.Start - l.Direction() * 0.2, l.End + l.Direction() * 0.2)); var longEdges = perimeterSegments.Except(shortEdges); var shortEdgeDepth = Math.Max(input.DepthAtEnds, input.OuterBandDepth); var longEdgeDepth = input.OuterBandDepth; var perimeterMinusSingleLoaded = new List <Profile>(); perimeterMinusSingleLoaded.AddRange(Profile.Difference(new[] { lvl.Profile }, singleLoadedZones.Select(p => new Profile(p.hull)))); var innerOffset = perimeterMinusSingleLoaded.SelectMany(p => p.Perimeter.Offset(-longEdgeDepth)); var thickerOffsets = shortEdgesExtended.SelectMany(s => s.ToPolyline(1).Offset(shortEdgeDepth, EndType.Butt)).ToList(); var thickerOffsetProfiles = thickerOffsets.Select(o => new Profile(o.Offset(0.01))).ToList(); var endOffsetSegments = thickerOffsets.SelectMany(o => o.Segments()).Where(l => innerOffset.Any(o => o.Contains(l.PointAt(0.5)))); var innerOffsetMinusThicker = innerOffset.SelectMany(i => Polygon.Difference(new[] { i }, thickerOffsets)); var outerband = new Profile(lvl.Profile.Perimeter, innerOffsetMinusThicker.ToList(), Guid.NewGuid(), null); var outerbandLongEdges = Profile.Difference(new List <Profile> { outerband }, thickerOffsetProfiles); var ends = Profile.Intersection(new List <Profile> { outerband }, thickerOffsets.Select(o => new Profile(o)).ToList()); var coreSegments = coresInBoundary.SelectMany(c => c.Profile.Perimeter.Offset((corridorWidth / 2) * 0.999).FirstOrDefault()?.Segments()); var corridorInset = innerOffsetMinusThicker.Select(p => new Profile(p, p.Offset(-corridorWidth), Guid.NewGuid(), "Corridor")); corridorProfiles.AddRange(corridorInset); // join single loaded zones to each other (useful in bent-bar case) var allCenterLines = singleLoadedZones.ToArray(); var distanceThreshold = 10.0; for (int i = 0; i < allCenterLines.Count(); i++) { var crvA = allCenterLines[i].centerLine; for (int j = 0; j < i; j++) { var crvB = allCenterLines[j].centerLine; var doesIntersect = crvA.Intersects(crvB, out var intersection, true, true); Console.WriteLine($"DOES INTERSECT: " + doesIntersect.ToString()); var nearPtA = intersection.ClosestPointOn(crvA); var nearPtB = intersection.ClosestPointOn(crvB); if (nearPtA.DistanceTo(intersection) + nearPtB.DistanceTo(intersection) < distanceThreshold) { if (nearPtA.DistanceTo(crvA.Start) < 0.01) { allCenterLines[i] = (allCenterLines[i].hull, new Line(intersection, crvA.End)); } else { allCenterLines[i] = (allCenterLines[i].hull, new Line(crvA.Start, intersection)); } if (nearPtB.DistanceTo(crvB.Start) < 0.01) { allCenterLines[j] = (allCenterLines[j].hull, new Line(intersection, crvB.End)); } else { allCenterLines[j] = (allCenterLines[j].hull, new Line(crvB.Start, intersection)); } } } } // thicken and extend single loaded foreach (var singleLoadedZone in allCenterLines) { var cl = singleLoadedZone.centerLine; List <Line> centerlines = new List <Line> { cl }; foreach (var core in coresInBoundary) { List <Line> linesRunning = new List <Line>(); foreach (var curve in centerlines) { curve.Trim(core.Profile.Perimeter, out var linesTrimmedByCore); linesRunning.AddRange(linesTrimmedByCore); } centerlines = linesRunning; } cl = centerlines.OrderBy(l => l.Length()).Last(); foreach (var clCandidate in centerlines) { var extended = clCandidate.ExtendTo(innerOffsetMinusThicker.SelectMany(p => p.Segments())).ToPolyline(1); if (extended.Length() == cl.Length() && innerOffsetMinusThicker.Count() > 0) { var end = extended.End; var dist = double.MaxValue; Vector3?runningPt = null; foreach (var boundary in innerOffsetMinusThicker) { var closestDist = end.DistanceTo(boundary, out var pt); if (closestDist < dist) { dist = closestDist; runningPt = pt; } } extended = new Polyline(new[] { extended.Start, extended.End, runningPt.Value }); } //TODO - verify that newly constructed line is contained within building perimeter var thickenedCorridor = extended.Offset(corridorWidth / 2.0, EndType.Square); corridorProfiles.AddRange(Profile.Difference(thickenedCorridor.Select(c => new Profile(c)), thickerOffsets.Select(c => new Profile(c)))); } } foreach (var core in coresInBoundary) { if (singleLoadedZones.Any(z => z.hull.Covers(core.Profile.Perimeter))) { continue; } var boundary = core.Profile.Perimeter.Offset(corridorWidth / 2.0).FirstOrDefault(); var outerOffset = boundary.Offset(corridorWidth).FirstOrDefault(); var coreWrap = new Profile(outerOffset, boundary); var coreWrapWithinFloor = Profile.Intersection(new[] { coreWrap }, new[] { levelBoundary }); } var extendedLines = new List <Line>(); var corridorRegions = new List <Polygon>(); var exclusionRegions = innerOffsetMinusThicker.SelectMany(r => r.Offset(2 * corridorWidth, EndType.Square)); foreach (var enclosedRegion in innerOffsetMinusThicker) { foreach (var segment in coreSegments) { enclosedRegion.Contains(segment.Start, out var startContainment); enclosedRegion.Contains(segment.End, out var endContainment); if (endContainment == Containment.Outside && startContainment == Containment.Outside) { continue; } var extendedSegment = segment.ExtendTo(new Profile(enclosedRegion)); if (extendedSegment.Length() - segment.Length() < 2 * 8) { continue; } extendedLines.Add(extendedSegment); var thickenedCorridor = extendedSegment.ToPolyline(1).Offset(corridorWidth / 2.0, EndType.Butt); var difference = new List <Profile>(); difference = Profile.Difference(corridorProfiles, exclusionRegions.Select(r => new Profile(r))); if (difference.Count > 0 && difference.Sum(d => d.Perimeter.Area()) > 10) { corridorProfiles.AddRange(Profile.Intersection(thickenedCorridor.Select(c => new Profile(c)), new[] { levelBoundary })); } } } var remainingSpaces = Profile.Difference(new[] { levelBoundary }, corridorProfiles); foreach (var remainingSpace in remainingSpaces) { try { if (remainingSpace.Perimeter.Vertices.Any(v => v.DistanceTo(levelBoundary.Perimeter) < 0.1)) { var endCapZones = Profile.Intersection(new[] { remainingSpace }, thickerOffsetProfiles); var linearZones = Profile.Difference(new[] { remainingSpace }, thickerOffsetProfiles); foreach (var linearZone in linearZones) { var segmentsExtended = new List <Polyline>(); foreach (var line in linearZone.Segments()) { if (line.Length() < 2) { continue; } var l = new Line(line.Start - line.Direction() * 0.1, line.End + line.Direction() * 0.1); var extended = l.ExtendTo(linearZone); var endDistance = extended.End.DistanceTo(l.End); var startDistance = extended.Start.DistanceTo(l.Start); var maxExtension = Math.Max(input.OuterBandDepth, input.DepthAtEnds) * 1.6; if (startDistance > 0.1 && startDistance < maxExtension) { var startLine = new Line(extended.Start, line.Start); segmentsExtended.Add(startLine.ToPolyline(1)); } if (endDistance > 0.1 && endDistance < maxExtension) { var endLine = new Line(extended.End, line.End); segmentsExtended.Add(endLine.ToPolyline(1)); } } Console.WriteLine(JsonConvert.SerializeObject(linearZone.Perimeter)); Console.WriteLine(JsonConvert.SerializeObject(linearZone.Voids)); Console.WriteLine(JsonConvert.SerializeObject(segmentsExtended)); var splits = Profile.Split(new[] { linearZone }, segmentsExtended, Vector3.EPSILON); spaceBoundaries.AddRange(splits.Select(s => SpaceBoundary.Make(s, input.DefaultProgramAssignment, lvl.Transform, lvl.Height))); } spaceBoundaries.AddRange(endCapZones.Select(s => SpaceBoundary.Make(s, input.DefaultProgramAssignment, lvl.Transform, lvl.Height))); } else { spaceBoundaries.Add(SpaceBoundary.Make(remainingSpace, input.DefaultProgramAssignment, lvl.Transform, lvl.Height)); } } catch (Exception e) { Console.WriteLine("🚨"); Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); spaceBoundaries.Add(SpaceBoundary.Make(remainingSpace, input.DefaultProgramAssignment, lvl.Transform, lvl.Height)); } } var level = new LevelElements(new List <Element>(), Guid.NewGuid(), lvl.Name); levels.Add(level); foreach (var pt in input.AdditionalCorridorLocations) { SplitZones(input, corridorWidth, lvl, spaceBoundaries, corridorProfiles, pt); } foreach (var pt in input.ManualSplitLocations) { SplitZones(input, corridorWidth, lvl, spaceBoundaries, corridorProfiles, pt, false); } foreach (SpaceBoundary b in spaceBoundaries) { levelMappings.Add(b.Id, (b, level)); output.Model.AddElements(b.Boundary.ToModelCurves(b.Transform.Concatenated(new Transform(0, 0, 0.03)))); } corridorProfiles.Select(p => new Floor(p, 0.1, lvl.Transform, corridorMat)).ToList().ForEach(f => level.Elements.Add(f)); } List <SpaceBoundary> SubdividedBoundaries = new List <SpaceBoundary>(); if (input.Overrides != null && input.Overrides.ProgramAssignments.Count > 0) { var spaceBoundaries = levelMappings.Select(kvp => kvp.Value); foreach (var overrideValue in input.Overrides.ProgramAssignments.Where(o => o.Identity.IndividualCentroid.IsAlmostEqualTo(o.Identity.ParentCentroid))) { var centroid = overrideValue.Identity.ParentCentroid; var matchingSB = spaceBoundaries .OrderBy(sb => sb.boundary.Transform.OfPoint(sb.boundary.Boundary.Perimeter.Centroid()).DistanceTo(centroid)) .FirstOrDefault(sb => sb.boundary.Transform.OfPoint(sb.boundary.Boundary.Perimeter.Centroid()).DistanceTo(centroid) < 2.0); var allMatchingSBs = spaceBoundaries .OrderBy(sb => sb.boundary.Transform.OfPoint(sb.boundary.Boundary.Perimeter.Centroid()).DistanceTo(centroid)) .Where(sb => sb.boundary.Transform.OfPoint(sb.boundary.Boundary.Perimeter.Centroid()).DistanceTo(centroid) < 2.0); if (matchingSB.boundary != null) { if (overrideValue.Value.Split <= 1) { matchingSB.boundary.SetProgram(overrideValue.Value.ProgramType ?? input.DefaultProgramAssignment); Identity.AddOverrideIdentity(matchingSB.boundary, "Program Assignments", overrideValue.Id, overrideValue.Identity); } else { levelMappings.Remove(matchingSB.boundary.Id); var boundaries = new List <Polygon>(matchingSB.boundary.Boundary.Voids) { matchingSB.boundary.Boundary.Perimeter }; var guideVector = GetDominantAxis(boundaries.SelectMany(b => b.Segments())); var alignmentXform = new Transform(boundaries[0].Start, guideVector, Vector3.ZAxis); var grid = new Grid2d(boundaries, alignmentXform); grid.U.DivideByCount(Math.Max(overrideValue.Value.Split, 1)); output.Model.AddElements(grid.GetCellSeparators(GridDirection.V, false).Select(c => new ModelCurve(c as Line, new Material("Grey", new Color(0.3, 0.3, 0.3, 1)), matchingSB.boundary.Transform.Concatenated(new Transform(0, 0, 0.02))))); foreach (var cell in grid.GetCells().SelectMany(c => c.GetTrimmedCellGeometry())) { var rep = matchingSB.boundary.Representation.SolidOperations.OfType <Extrude>().First(); var newCellSb = SpaceBoundary.Make(cell as Polygon, overrideValue.Value.ProgramType ?? input.DefaultProgramAssignment, matchingSB.boundary.Transform, rep.Height, matchingSB.boundary.AdditionalProperties["ParentCentroid"] as Vector3?); Identity.AddOverrideIdentity(newCellSb, "Program Assignments", overrideValue.Id, overrideValue.Identity); newCellSb.AdditionalProperties["Split"] = overrideValue.Value.Split; SubdividedBoundaries.Add(newCellSb); levelMappings.Add(newCellSb.Id, (newCellSb, matchingSB.level)); } } } } foreach (var overrideValue in input.Overrides.ProgramAssignments.Where(o => !o.Identity.IndividualCentroid.IsAlmostEqualTo(o.Identity.ParentCentroid))) { var matchingCell = SubdividedBoundaries.FirstOrDefault(b => (b.AdditionalProperties["IndividualCentroid"] as Vector3?)?.DistanceTo(overrideValue.Identity.IndividualCentroid) < 0.01); if (matchingCell != null) { Identity.AddOverrideIdentity(matchingCell, "Program Assignments", overrideValue.Id, overrideValue.Identity); matchingCell.SetProgram(overrideValue.Value.ProgramType); } } } foreach (var levelMapping in levelMappings) { levelMapping.Value.level.Elements.Add(levelMapping.Value.boundary); } Dictionary <string, AreaTally> areas = new Dictionary <string, AreaTally>(); foreach (var sb in levels.SelectMany(lev => lev.Elements.OfType <SpaceBoundary>())) { var area = sb.Boundary.Area(); if (sb.Name == null) { continue; } if (!areas.ContainsKey(sb.Name)) { areas[sb.Name] = new AreaTally(sb.Name, sb.Material.Color, area, area, 1, null, Guid.NewGuid(), sb.Name); } else { var existingTally = areas[sb.Name]; existingTally.AchievedArea += area; existingTally.AreaTarget += area; existingTally.DistinctAreaCount++; } } output.Model.AddElements(areas.Select(kvp => kvp.Value).OrderByDescending(a => a.AchievedArea)); output.Model.AddElements(levels); return(output); }
public void Create() { foreach (Transform child in transform) { Destroy(child.gameObject); } //InputField[] fields = FindObjectsOfType<InputField>(); //InputField numseed = fields[0]; //InputField numplates = fields[1]; //InputField numtiles = fields[2]; //numberOfVertices = Convert.ToInt32(numtiles.text); //plates = Convert.ToInt32(numplates.text); //seed = Convert.ToInt32(numseed.text); // INITIALIZATION Vertex3[] vertices = new Vertex3[numberOfVertices]; Vector3[] meshVerts = new Vector3[numberOfVertices]; allVerts = new List <Vector3>(); vertsForVoronoiHull = new List <Vector3>(); // VORONOI VERTICES NEED ONE EXTRA ONE IN CENTER Vertex3[] voronoiVertices = new Vertex3[numberOfVertices + 1]; // RANDOM SEED Random.seed = seed; // GENERATE UNIFORM POINTS allVerts = GeneratePointsUniformly(); allVerts.Sort((v1, v2) => v1.y.CompareTo(v2.y)); // SET INDICES FOR VORONOI int i = 0; while (i < numberOfVertices) { vertices[i] = new Vertex3(allVerts[i].x, allVerts[i].y, allVerts[i].z); voronoiVertices[i] = vertices[i]; meshVerts[i] = vertices[i].ToVector3();; i++; } // SET LAST EXTRA VERTEX voronoiVertices[numberOfVertices] = new Vertex3(0, 0, 0); // VORONOI voronoiMesh = VoronoiMesh.Create <Vertex3, Cell3>(voronoiVertices); // VORONOI HULL GENERATION int index = 0; foreach (var edge in voronoiMesh.Edges) { Vector3 source = new Vector3(edge.Source.Circumcenter.x, edge.Source.Circumcenter.y, edge.Source.Circumcenter.z); Vector3 target = new Vector3(edge.Target.Circumcenter.x, edge.Target.Circumcenter.y, edge.Target.Circumcenter.z); source *= ((float)size / 2.5f); target *= ((float)size / 2.5f); vertsForVoronoiHull.Add(source); vertsForVoronoiHull.Add(target); index++; } // REMOVE DUPLICATE POINTS vertsForVoronoiHull = vertsForVoronoiHull.Distinct().ToList(); // CONVERT FROM VECTOR3 LIST TO VERTEX3 LIST FOR FINAL HULL Vertex3[] verticesDelaunay = new Vertex3[vertsForVoronoiHull.Count]; int g = 0; while (g < vertsForVoronoiHull.Count) { verticesDelaunay[g] = new Vertex3(vertsForVoronoiHull[g].x, vertsForVoronoiHull[g].y, vertsForVoronoiHull[g].z); g++; } // GENERATE VORONOI HULL ConvexHull <Vertex3, Face3> convexHull = ConvexHull.Create <Vertex3, Face3>(verticesDelaunay); convexHullVertices = new List <Vertex3>(convexHull.Points); convexHullFaces = new List <Face3>(convexHull.Faces); convexHullIndices = new List <int>(); foreach (Face3 f in convexHullFaces) { convexHullIndices.Add(convexHullVertices.IndexOf(f.Vertices[0])); convexHullIndices.Add(convexHullVertices.IndexOf(f.Vertices[1])); convexHullIndices.Add(convexHullVertices.IndexOf(f.Vertices[2])); } Dictionary <Vector3, List <Vector3> > normals = new Dictionary <Vector3, List <Vector3> >(); // CREATE TRIANGLES FOR MESH for (int j = 0; j < convexHullIndices.Count; j += 3) { int v0 = convexHullIndices[j + 0]; int v1 = convexHullIndices[j + 1]; int v2 = convexHullIndices[j + 2]; Vector3 a = new Vector3((float)convexHullVertices[v0].x, (float)convexHullVertices[v0].y, (float)convexHullVertices[v0].z); Vector3 b = new Vector3((float)convexHullVertices[v1].x, (float)convexHullVertices[v1].y, (float)convexHullVertices[v1].z); Vector3 c = new Vector3((float)convexHullVertices[v2].x, (float)convexHullVertices[v2].y, (float)convexHullVertices[v2].z); Vector3 normal = Vector3.Cross(a - b, a - c); // DECLARE KEY AND ROUND IT TO AVOID FLOATING POINT ISSUES Vector3 key = normal.normalized; float roundX = Mathf.Round(key.x * 100) / 100; float roundY = Mathf.Round(key.y * 100) / 100; float roundZ = Mathf.Round(key.z * 100) / 100; Vector3 roundedKey = new Vector3(roundX, roundY, roundZ); // POPULATE DICTIONARY if (!normals.ContainsKey(roundedKey)) { normals.Add(roundedKey, new List <Vector3>()); } normals[roundedKey].Add(a); normals[roundedKey].Add(b); normals[roundedKey].Add(c); } // CREATE VORONOI TILES List <VoronoiTile> tiles = new List <VoronoiTile>(); foreach (var pair in normals) { List <Vector3> tileVerts = new List <Vector3>(); for (int p = 0; p < pair.Value.Count; ++p) { tileVerts.Add(pair.Value[p]); } GameObject tile = new GameObject("Tile", typeof(VoronoiTile), typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider)); var thisTile = tile.GetComponent <VoronoiTile>() as VoronoiTile; thisTile.Initialize(tileVerts, false); // OPTIMIZE HERE tile.GetComponent <MeshFilter>().mesh = thisTile.tileMesh; tile.GetComponent <MeshCollider>().sharedMesh = thisTile.tileMesh; thisTile.Normal = pair.Key; tiles.Add(thisTile); ++numberOfTiles; } foreach (var tile in tiles) { tile.FindNeighbors(tiles); } List <VoronoiTile> waterTiles = new List <VoronoiTile>(); Material oceanMat = (Material)Resources.Load("Ocean", typeof(Material)); foreach (var pair in normals) { List <Vector3> tileVerts = new List <Vector3>(); for (int p = 0; p < pair.Value.Count; ++p) { tileVerts.Add(pair.Value[p]); } GameObject tile = new GameObject("WaterTile", typeof(VoronoiTile), typeof(MeshFilter), typeof(MeshRenderer)); var thisTile = tile.GetComponent <VoronoiTile>() as VoronoiTile; thisTile.Initialize(tileVerts, true); tile.GetComponent <MeshFilter>().mesh = thisTile.tileMesh; tile.GetComponent <MeshRenderer>().material = oceanMat; waterTiles.Add(thisTile); } ocean = new GameObject("Ocean"); ocean.transform.parent = transform; foreach (var tile in waterTiles) { tile.transform.parent = ocean.transform; } // FLOOD FILLS // GENERATE PLATES List <VoronoiTile> plateStartNodes = GeneratePlateStartNodes(plates, ref tiles); // GENERATE PLATE MATERIALS List <Material> plateMaterials = GenerateMaterials(1); // changed here // GENERATE START LISTS List <List <VoronoiTile> > colors = new List <List <VoronoiTile> >(); for (int b = 0; b < plates; ++b) { colors.Add(new List <VoronoiTile>() { plateStartNodes[b] }); } // FILL FloodFillSimultaneous(ref colors, plateMaterials, ref tiles); // GROUP PLATES plateList = new List <TectonicPlate>(); for (int q = 0; q < plates; ++q) { GameObject plateTest = new GameObject("Plate" + q, typeof(TectonicPlate)); List <VoronoiTile> testPlateTiles = new List <VoronoiTile>(); foreach (var voronoiTile in tiles) { if (voronoiTile.plate == q) { testPlateTiles.Add(voronoiTile); } } var thisTecPlate = plateTest.GetComponent <TectonicPlate>(); thisTecPlate.Initialize(ref testPlateTiles); int land = Random.Range(0, 10); if (land < landAmount) { thisTecPlate.isLand = true; } plateTest.transform.parent = transform; plateList.Add(thisTecPlate); } LoadMaterials(); // CREATE WATER AND LAND AREAS FOR HEIGHT FindWaterAndLandPoints(); // DETERMINE BIOMES AssignPlateProperties(); AssignTileProperties(); DetermineBiomes(true); GenerateHeight(); DetermineHeightBiomes(); }
// ************************************************************************ public QuadrantSpecific4(ConvexHull convexHull, IReadOnlyList <Point> listOfPoint) : base(convexHull, listOfPoint, new Q4Comparer()) { Name = QuadrantName; }
/// <summary> /// Main segmentation loop. Loops through the entire set of pixels to /// detect skin-like pixels. Then Removes noise and enhances the skin /// pixels using skinblobs and gets the contourPointss of the skin. Finally /// calculating the convex hull. /// Also changes colors of pixels in the texture for debug / visualisation /// purposes. /// </summary> /// <param name="texture"> Contains all the pixels of the image. </param> /// <param name="threshold"> /// Contains the color threshold to be considered a skin candidate. /// </param> /// <returns> Edited texture. </returns> public Color[] SegmentColors(WebCamTexture texture, float threshold, DisplayOptions OPTIONS) { // Get an array of pixels from the texture. var pixels = texture.GetPixels(); // First Loop : Segment and identify skin blobs. skinObjects = new List <SkinBlob>(); largestSkinObject = new SkinBlob(new Vector2()); int close = 0; for (var i = 0; i < pixels.Length; i++) { // Identify skin coloured pixels and add them to an object. // Threshold for skin color lowers if the pixel is close to a definite skin pixel. if (PixelThreshold(pixels[i], threshold) || (close > 0 && PixelThreshold(pixels[i], threshold / 2))) { CheckSkinObjects(Utility.IndexToPoint(texture.width, i)); close = closeThreshold; // Display options - Sets initital segmentation pixels to white if (OPTIONS.SHOW_SEGMENTATION_FIRST) { pixels[i] = Color.white; } } else { close--; // Display options - Sets other pixels to black if (OPTIONS.SHOW_SEGMENTATION_FIRST) { pixels[i] = Color.black; } } } // Second Loop : focus on largest skin blob, removing noise. Get contour list. // Contour list creates candidates for the convex hull. var contourPoints = new List <Vector2>(); // Linewidth dictates the longest uninterrupted line of skin pixels. var lineWidth = 0; var thisPixel = 0; // 0 black / 1 white. var lastPixel = 0; // 0 black / 1 white. for (var i = 0; i < pixels.Length; i++) { var pixelCoords = Utility.IndexToPoint(texture.width, i); // If within the skin objects min max boundries. // Also within an even more lenient threshold. if (pixelCoords.y < largestSkinObject.GetMaxPoint().y&& pixelCoords.y > largestSkinObject.GetMinPoint().y&& pixelCoords.x < largestSkinObject.GetMaxPoint().x&& pixelCoords.x > largestSkinObject.GetMinPoint().x&& PixelThreshold(pixels[i], threshold / 3)) { lineWidth++; thisPixel = 1; // Skin pixel // Calculates 'center of mass'. largestSkinObject.AddToMean(pixelCoords); // Display Options - Show pixels after second segmentaiton. if (OPTIONS.SHOW_SEGMENTATION_SECOND) { pixels[i] = Color.grey; } } else { // Send linewidth to the skin object and reset linewidth as // black pixel has been reached. largestSkinObject.TestWidth(lineWidth); lineWidth = 0; thisPixel = 0; // Black pixel. // Display Options - Show pixels after second segmentaiton. if (OPTIONS.SHOW_SEGMENTATION_SECOND) { pixels[i] = Color.black; } } // Get a "good enough" contour point list for convex hull calculations. // Checks if the previous pixel was classed differently, then if true, // adds the current pixel to a list of contour points. if (thisPixel != lastPixel) { contourPoints.Add(pixelCoords); } lastPixel = thisPixel; } // Calculate convex hull using contour points. var hullPoints = ConvexHull.GetConvexHull(contourPoints); fingertipPoints = GetFingertips(hullPoints); // Display Options - Set contour pixels to green if (OPTIONS.SHOW_CONTOUR) { contourPoints.ForEach(point => { pixels[Utility.PointToIndex(texture.width, point)] = Color.green; }); } // Return array of edited pixels for display. return(pixels); }
/// <summary> /// Constructs a new demo. /// </summary> /// <param name="game">Game owning this demo.</param> public FancyShapesDemo(DemosGame game) : base(game) { var points = new List<Vector3>(); //Setup a random distribution in a cube and compute a convex hull. var random = new Random(0); for (int k = 0; k < 40; k++) { points.Add(new Vector3(3 * (float)random.NextDouble(), 5 * (float)random.NextDouble(), 3 * (float)random.NextDouble())); } var convexHull = new ConvexHull(new Vector3(0, 7, 0), points, 10); Space.Add(convexHull); points.Clear(); //Create another random distribution, but this time with more points. points.Clear(); for (int k = 0; k < 400; k++) { points.Add(new Vector3(1 * (float)random.NextDouble(), 3 * (float)random.NextDouble(), 1 * (float)random.NextDouble())); } convexHull = new ConvexHull(new Vector3(4, 7, 0), points, 10); Space.Add(convexHull); //Minkowski Sums are fancy 'combinations' of objects, where the result is the sum of the individual points making up shapes. //Think of it as sweeping one shape around and through another; a sphere and a box would produce a rounded-edge box. var minkowskiSum = new MinkowskiSum(new Vector3(4, -3, 0), new OrientedConvexShapeEntry(new BoxShape(2, 2, 2)), new OrientedConvexShapeEntry(new ConeShape(2, 2)), 10); Space.Add(minkowskiSum); minkowskiSum = new MinkowskiSum(new Vector3(0, 3, 0), new OrientedConvexShapeEntry(Quaternion.CreateFromYawPitchRoll(1, 2, 3), new ConeShape(1, 1)), new OrientedConvexShapeEntry(new TriangleShape(Vector3.Zero, Vector3.Right, Vector3.Forward)), 1); Space.Add(minkowskiSum); //Note how this minkowski sum is composed of a cylinder, and another minkowski sum shape. minkowskiSum = new MinkowskiSum(new Vector3(-4, 10, 0), new OrientedConvexShapeEntry(new CylinderShape(1, 2)), new OrientedConvexShapeEntry(new MinkowskiSumShape( new OrientedConvexShapeEntry(new TriangleShape(new Vector3(1, 1, 1), new Vector3(-2, 0, 0), new Vector3(0, -1, 0))), new OrientedConvexShapeEntry(new BoxShape(.3f, 1, .3f)))), 10); Space.Add(minkowskiSum); //Minkowski sums can also be used on more than two shapes at once. The two-shape constructor is just a convenience wrapper. //Wrapped objects use an implicit convex hull around a set of shapes. //Oblique cone: var cone = new List<ConvexShapeEntry> { new ConvexShapeEntry(new CylinderShape(0, 1)), new ConvexShapeEntry(new RigidTransform(new Vector3(1f, 2, 0)), new SphereShape(0)) }; Space.Add(new WrappedBody(new Vector3(-5, 0, 0), cone, 10)); //Rather odd shape: var oddShape = new List<ConvexShapeEntry>(); var bottom = new ConvexShapeEntry(new Vector3(-2, 2, 0), new SphereShape(2)); var middle = new ConvexShapeEntry( new RigidTransform( new Vector3(-2, 3, 0), Quaternion.CreateFromAxisAngle(Vector3.Right, (float)Math.PI / 6)), new CylinderShape(0, 3)); var top = new ConvexShapeEntry(new Vector3(-2, 4, 0), new SphereShape(1f)); oddShape.Add(bottom); oddShape.Add(middle); oddShape.Add(top); Space.Add(new WrappedBody(new Vector3(-3, 4, 0), oddShape, 10)); //Transformable shapes can be any other kind of convex primitive transformed by any affine transformation. Matrix3x3 transform; transform = Matrix3x3.Identity; transform.M23 = .5f; transform.M13 = .5f; var transformable = new TransformableEntity(new Vector3(0, 0, 4), new BoxShape(1, 1, 1), transform, 10); Space.Add(transformable); Space.Add(new Box(new Vector3(0, -10, 0), 70, 5, 70)); game.Camera.Position = new Vector3(0, 0, 30); }
void OnChanged_MakeGeometry(bool isEnd = false) { // We'd like to be able to record which control points will never be on the // hull, to avoid the extra work of hulling them. However, we don't know if // the most-recent knot is a keeper. If it's not a keeper, we can't say for // sure that any verts not on the hull won't reappear on the hull when the // most-recent knot changes to some other location. // // Thus, only trust the "not on hull" result if all the input knots are // keepers. But there's no exposed way of determining if all the knots are // keepers. One conservative thing we can do is: check whether the last two // knots are identical; if so, don't hull the last knot. This is safe because // identical knots are fungible (for purposes of hulling). It's an invariant // that every knot's a keeper except (maybe) the last knot; thus, we're only // hulling keepers and the not-in-hull result can be trusted. // // This then raises the question: are the last 2 knots ever identical? If not, // we'll lose out on our optimization. It turns out that when GeometryBrush // decides to keep a knot, it duplicates it before going to geometry generation. // So currently it's an okay assumption, but maybe a little more fragile than // we'd like. Worth revisiting once we do the work to give brushes more control // over which control points are kept. bool recordInterior = false; UnityEngine.Profiling.Profiler.BeginSample("Track Interior"); if (m_TrackInterior && m_knots.Count >= 2) { int last = m_knots.Count - 1; if (m_knots[last].point.m_Pos == m_knots[last - 1].point.m_Pos) { recordInterior = true; // Only hull vertices which are guaranteed not to change or disappear. // // This removal is _required_ (in order to recordInterior), because otherwise // we might generate incorrect values for DefinitelyInterior. False negatives // are benign; false positives can cause vertices to be permanently omitted // from the hull. // // This removal is _safe_ because removal of the last N vertices does not // change the hull. Each of those vertices has a duplicate that is kept. // Proof: the last knot is identical to the last-1 knot; identical knots // generate identical Vertices. // // This temporarily breaks the invariant that # vertices = # knots * vertsPerKnot, // but the alternative is linq shenanigans (ie, m_AllVertices.Take(Count-N)). // We don't really rely on that invariant, and the invariant is re-established // periodically by ResizeVertices(). int toRemove = GetNumVerticesPerKnot(); m_AllVertices.RemoveRange(m_AllVertices.Count - toRemove, toRemove); } } UnityEngine.Profiling.Profiler.EndSample(); // Don't bother hulling the ones that we've proven will never be on the hull UnityEngine.Profiling.Profiler.BeginSample("Remove Interior"); var input = m_AllVertices.Where(v => !v.DefinitelyInterior).ToList(); UnityEngine.Profiling.Profiler.EndSample(); Knot knot = m_knots[1]; // Clear geometry because we recreate from scratch knot.iVert = 0; knot.nVert = 0; knot.iTri = 0; knot.nTri = 0; m_geometry.m_Vertices.SetCount(0); m_geometry.m_Normals.SetCount(0); m_geometry.m_Colors.SetCount(0); m_geometry.m_Texcoord0.v3.SetCount(0); m_geometry.m_Tris.SetCount(0); // Straightedge is very WYSIWYG, so don't simplify if it's enabled. bool simplify = !PointerManager.m_Instance.StraightEdgeModeEnabled && ((isEnd && m_SimplifyMode == SimplifyMode.SimplifyAtEnd) || (!isEnd && m_SimplifyMode == SimplifyMode.SimplifyInteractively && recordInterior)); // Attempt to create hull. It can fail if the dimensionality is too low // because of too few points; and maybe also if the points are collinear/coplanar. // Only simplify after keeping a knot, to try to keep things feeling a bit more // like what a production implementation would do -- if simplification happens // every frame we get very jittery behavior that feels uncontrollable. UnityEngine.Profiling.Profiler.BeginSample("Create Hull"); ConvexHull <Vertex, Face> hull = CreateHull(input, enableSimplify: simplify); UnityEngine.Profiling.Profiler.EndSample(); if (hull != null) { if (recordInterior) { foreach (var v in input) { v.DefinitelyInterior = true; } foreach (var v in hull.Points) { v.DefinitelyInterior = false; } } UnityEngine.Profiling.Profiler.BeginSample("Create Geometry"); if (m_Faceted) { CreateFacetedGeometry(ref knot, hull); } else { CreateSmoothGeometry(ref knot, hull); } UnityEngine.Profiling.Profiler.EndSample(); } m_knots[1] = knot; }
private static void GrowGroupAroundLoosePolyline(Obstacle group, Polyline loosePolyline) { var points = group.VisibilityPolyline.Select(p => p).Concat(loosePolyline.Select(p => p)); group.SetConvexHull(new OverlapConvexHull(ConvexHull.CreateConvexHullAsClosedPolyline(points), new[] { group })); }
private void InitalizeConvexHull(List <ModelData.Vertex> points) { ConvexHullIndicies = new HashSet <int>(collection: ConvexHull.Create(points.ConvertAll(x => (IVertex)x)).Points.ToList().ConvertAll(x => ((Vertex)x).Index)); }
// // Reference implementations of queries using simple brute-force methods // static unsafe float RefConvexConvexDistance(ref ConvexHull a, ref ConvexHull b, MTransform aFromB) { bool success = false; if (a.NumVertices + b.NumVertices < 64) // too slow without burst { // Build the minkowski difference in a-space int maxNumVertices = a.NumVertices * b.NumVertices; Aabb aabb = Aabb.Empty; for (int iB = 0; iB < b.NumVertices; iB++) { float3 vertexB = Math.Mul(aFromB, b.Vertices[iB]); for (int iA = 0; iA < a.NumVertices; iA++) { float3 vertexA = a.Vertices[iA]; aabb.Include(vertexA - vertexB); } } ConvexHullBuilderStorage diffStorage = new ConvexHullBuilderStorage(maxNumVertices, Allocator.Temp, aabb, 0.0f, ConvexHullBuilder.IntResolution.Low); ref ConvexHullBuilder diff = ref diffStorage.Builder; success = true; for (int iB = 0; iB < b.NumVertices; iB++) { float3 vertexB = Math.Mul(aFromB, b.Vertices[iB]); for (int iA = 0; iA < a.NumVertices; iA++) { float3 vertexA = a.Vertices[iA]; diff.AddPoint(vertexA - vertexB, (uint)(iA | iB << 16)); } } float distance = 0.0f; if (success && diff.Dimension == 3) { // Find the closest triangle to the origin distance = float.MaxValue; bool penetrating = true; foreach (int t in diff.Triangles.Indices) { ConvexHullBuilder.Triangle triangle = diff.Triangles[t]; float3 v0 = diff.Vertices[triangle.GetVertex(0)].Position; float3 v1 = diff.Vertices[triangle.GetVertex(1)].Position; float3 v2 = diff.Vertices[triangle.GetVertex(2)].Position; float3 n = diff.ComputePlane(t).Normal; DistanceQueries.Result result = DistanceQueries.TriangleSphere(v0, v1, v2, n, float3.zero, 0.0f, MTransform.Identity); if (result.Distance < distance) { distance = result.Distance; } penetrating = penetrating & (math.dot(n, -result.NormalInA) < 0.0f); // only penetrating if inside of all planes } if (penetrating) { distance = -distance; } distance -= a.ConvexRadius + b.ConvexRadius; } else { success = false; } diffStorage.Dispose(); if (success) { return(distance); } }
//given list of badges which comprise cluster, we build convex hull and then smooth border public void PlayBuildSmoothCurve() { var BadgesCorners = ShapeUtils.buildBadgeCorners(_endpoint.GetClusterables()); if (BadgesCorners.Count <= 2) { //rebuilding cluster after unclustering last badge. //the cluster will soon be removed (by server event) return; } convexHull.Points = ConvexHull.FindConvexPolygon(BadgesCorners); var convexPoints = convexHull.Points; _topLeft = new Point(convexPoints.Min(pt => pt.X), convexPoints.Min(pt => pt.Y)); //build bezier curve var pathFigure = new PathFigure(); Point[] firstControlPoints = null; Point[] secondControlPoints = null; ovp.BezierSpline.GetCurveControlPoints(convexPoints.ToArray(), out firstControlPoints, out secondControlPoints); pathFigure.StartPoint = convexPoints.ElementAt(0); for (int i = 0; i < convexPoints.Count - 1; i++) { pathFigure.Segments.Add(new BezierSegment(firstControlPoints[i], secondControlPoints[i], convexPoints.ElementAt(i + 1), true)); } //closing segment if (convexPoints.Count == 3) { Point[] firstLast = new Point[] { convexPoints[2], convexPoints[0], convexPoints[1] }; ovp.BezierSpline.GetCurveControlPoints(firstLast, out firstControlPoints, out secondControlPoints); pathFigure.Segments.Add(new BezierSegment(firstControlPoints.First(), secondControlPoints.First(), convexPoints.First(), true)); } else { Point[] firstLast = new Point[] { convexPoints[convexPoints.Count - 2], convexPoints[convexPoints.Count - 1], convexPoints[0], convexPoints[1] }; ovp.BezierSpline.GetCurveControlPoints(firstLast, out firstControlPoints, out secondControlPoints); pathFigure.Segments.Add(new BezierSegment(firstControlPoints[1], secondControlPoints[1], convexPoints[0], true)); } var pathGeom = new PathGeometry(); pathGeom.Figures.Add(pathFigure); bezierBorder.Data = pathGeom; _offset = new Point(0, 0); if (_endpoint.GetClusterables().Count() > 0) { clusterCreated = true; if (cleanerTimer != null) { cleanerTimer.Stop(); cleanerTimer = null; } } SetBounds(); }
static void ValidateDistanceResult(DistanceQueries.Result result, ref ConvexHull a, ref ConvexHull b, MTransform aFromB, float referenceDistance, string failureMessage) { // Calculate the support distance along the separating normal float3 tempA = getSupport(ref a, -result.NormalInA); float3 supportQuery = tempA - result.NormalInA * a.ConvexRadius; float3 tempB = Math.Mul(aFromB, getSupport(ref b, math.mul(aFromB.InverseRotation, result.NormalInA))); float3 supportTarget = tempB + result.NormalInA * b.ConvexRadius; float supportQueryDot = math.dot(supportQuery, result.NormalInA); float supportTargetDot = math.dot(supportTarget, result.NormalInA); float supportDistance = supportQueryDot - supportTargetDot; // Increase the tolerance in case of core penetration float adjustedTolerance = tolerance; float zeroCoreDistance = -a.ConvexRadius - b.ConvexRadius; // Distance of shapes including radius at which core shapes are penetrating if (result.Distance < zeroCoreDistance || referenceDistance < zeroCoreDistance || supportDistance < zeroCoreDistance) { // Core shape penetration distances are less accurate, and error scales with the number of vertices (as well as shape size). See stopThreshold in ConvexConvexDistanceQueries. // This is not usually noticeable in rigid body simulation because accuracy improves as the penetration resolves. // The tolerance is tuned for these tests, it might require further tuning as the tests change. adjustedTolerance = 1e-2f + 1e-3f * (a.NumVertices + b.NumVertices); } // Check that the distance is consistent with the reference distance Assert.AreEqual(result.Distance, referenceDistance, adjustedTolerance, failureMessage + ": incorrect distance"); // Check that the separating normal and closest point are consistent with the distance Assert.AreEqual(result.Distance, supportDistance, adjustedTolerance, failureMessage + ": incorrect normal"); float positionDot = math.dot(result.PositionOnAinA, result.NormalInA); Assert.AreEqual(supportQueryDot, positionDot, adjustedTolerance, failureMessage + ": incorrect position"); }
// // Reference implementations of queries using simple brute-force methods // static unsafe float RefConvexConvexDistance(ref ConvexHull a, ref ConvexHull b, MTransform aFromB) { bool success = false; if (a.NumVertices + b.NumVertices < 64) // TODO - work around hull builder asserts { // Build the minkowski difference in a-space int maxNumVertices = a.NumVertices * b.NumVertices; ConvexHullBuilder diff = new ConvexHullBuilder(maxNumVertices, 2 * maxNumVertices, Allocator.Temp); Aabb aabb = Aabb.Empty; for (int iB = 0; iB < b.NumVertices; iB++) { float3 vertexB = Math.Mul(aFromB, b.Vertices[iB]); for (int iA = 0; iA < a.NumVertices; iA++) { float3 vertexA = a.Vertices[iA]; aabb.Include(vertexA - vertexB); } } diff.IntegerSpaceAabb = aabb; success = true; for (int iB = 0; iB < b.NumVertices; iB++) { float3 vertexB = Math.Mul(aFromB, b.Vertices[iB]); for (int iA = 0; iA < a.NumVertices; iA++) { float3 vertexA = a.Vertices[iA]; if (!diff.AddPoint(vertexA - vertexB, (uint)(iA | iB << 16))) { // TODO - coplanar vertices are tripping up ConvexHullBuilder, we should fix it but for now fall back to DistanceQueries.ConvexConvex() success = false; } } } float distance = 0.0f; if (success && diff.Triangles.GetFirstIndex() != -1) { // Find the closest triangle to the origin distance = float.MaxValue; bool penetrating = true; for (int t = diff.Triangles.GetFirstIndex(); t != -1; t = diff.Triangles.GetNextIndex(t)) { ConvexHullBuilder.Triangle triangle = diff.Triangles[t]; float3 v0 = diff.Vertices[triangle.GetVertex(0)].Position; float3 v1 = diff.Vertices[triangle.GetVertex(1)].Position; float3 v2 = diff.Vertices[triangle.GetVertex(2)].Position; float3 n = diff.ComputePlane(t).Normal; DistanceQueries.Result result = DistanceQueries.TriangleSphere(v0, v1, v2, n, float3.zero, 0.0f, MTransform.Identity); if (result.Distance < distance) { distance = result.Distance; } penetrating = penetrating & (math.dot(n, -result.NormalInA) < 0.0f); // only penetrating if inside of all planes } if (penetrating) { distance = -distance; } distance -= a.ConvexRadius + b.ConvexRadius; } else { success = false; } diff.Dispose(); if (success) { return(distance); } } // Fall back in case hull isn't 3D or hull builder fails // Most of the time this happens for cases like sphere-sphere, capsule-capsule, etc. which have special implementations, // so comparing those to GJK still validates the results of different API queries against each other. return(DistanceQueries.ConvexConvex(ref a, ref b, aFromB).Distance); }
// ****************************************************************** public ConvexHullEnumerator(ConvexHull convexHull) { _convexHull = convexHull; }
public void Parse(GameBitBuffer buffer) { Field0 = buffer.ReadInt(32); Field1 = buffer.ReadInt(32); Field2 = buffer.ReadInt(32); Field3 = buffer.ReadInt(32); Field4 = buffer.ReadFloat32(); Field5 = buffer.ReadFloat32(); Field6 = buffer.ReadFloat32(); Field7 = new ConvexHull(); Field7.Parse(buffer); Field8 = new OBB(); Field8.Parse(buffer); Field9 = new Sphere(); Field9.Parse(buffer); Field10 = new Cylinder(); Field10.Parse(buffer); Field11 = new Capsule(); Field11.Parse(buffer); }
private static Mesh CreateHullMesh(Mesh mesh) { var bounds = AxisAlignedBoundingBox.Empty(); // Get the convex hull for the mesh var cHVertexList = new List <CHVertex>(); foreach (var position in mesh.Vertices.Distinct().ToArray()) { cHVertexList.Add(new CHVertex(position)); bounds.ExpandToInclude(position); } var tollerance = .01; if (cHVertexList.Count == 0 || bounds.XSize <= tollerance || bounds.YSize <= tollerance || bounds.ZSize <= tollerance || double.IsNaN(cHVertexList.First().Position[0])) { return(mesh); } var convexHull = ConvexHull <CHVertex, CHFace> .Create(cHVertexList, tollerance); if (convexHull != null) { // create the mesh from the hull data Mesh hullMesh = new Mesh(); foreach (var face in convexHull.Faces) { int vertexCount = hullMesh.Vertices.Count; foreach (var vertex in face.Vertices) { hullMesh.Vertices.Add(new Vector3(vertex.Position[0], vertex.Position[1], vertex.Position[2])); } hullMesh.Faces.Add(vertexCount, vertexCount + 1, vertexCount + 2, hullMesh.Vertices); } try { // make sure there is not currently a convex hull on this object if (mesh.PropertyBag.ContainsKey(ConvexHullMesh)) { mesh.PropertyBag.Remove(ConvexHullMesh); } // add the new hull mesh.PropertyBag.Add(ConvexHullMesh, hullMesh); // make sure we remove this hull if the mesh changes mesh.Changed += MeshChanged_RemoveConvexHull; // remove the marker that says we are building the hull if (mesh.PropertyBag.ContainsKey(CreatingConvexHullMesh)) { mesh.PropertyBag.Remove(CreatingConvexHullMesh); } return(hullMesh); } catch { } } return(null); }
/// <summary> /// Constructs a new entity for use by the constructor. /// </summary> /// <param name="modelName">The name of the Prop's model.</param> /// <param name="translation">The position.</param> /// <param name="orientation">The orientation.</param> /// <param name="scale">The amount to scale the prop by.</param> /// <param name="mass">The mass of the prop.</param> /// <returns>The entity to be passed into the PhysicsObject constructor.</returns> private static Entity CreateEntity(String modelName, Vector3 translation, Quaternion orientation, Vector3 scale, float mass) { Vector3[] vertices; int[] indices; CollisionMeshManager.LookupMesh(modelName, out vertices, out indices); Vector3[] modVertices = new Vector3[vertices.Length]; for (int i = 0; i < vertices.Length; i++) { modVertices[i] = scale * vertices[i]; } Entity entity = new ConvexHull(modVertices, mass); return entity; //return new MobileMesh(vertices, indices, new AffineTransform(scale, orientation, translation), MobileMeshSolidity.Solid, mass); }
public Dictionary <int, List <Mesh> > GenerateJointMeshes(bool label = true) { JointMeshes.Clear(); JointArmLabel.Clear(); var separateJointMeshes = new Dictionary <int, List <Mesh> >(); var jointArmCounter = new Dictionary <int, int>(); var jointCorePoints = new Dictionary <int, List <double[]> >(); for (int v = 0; v < Vertices.Count; v++) { separateJointMeshes[v] = new List <Mesh>(); jointCorePoints[v] = new List <double[]>(); jointArmCounter[v] = 1; } foreach (Tuple <int, int> e in Edges) { if (!RodMeshes.ContainsKey(e)) { continue; } Curve c = new LineCurve(Vertices[e.Item1], Vertices[e.Item2]); double len = c.GetLength(); if (len == 0) { throw new Exception("Joint not created. Joint lengths greater than rod length. Try reducing joint lengths or radius."); } Curve startCurve; Curve endCurve; try { startCurve = c.Trim(CurveEnd.End, len - (Offsets[e] + JointLength)); endCurve = c.Trim(CurveEnd.Start, len - (Offsets[Tuple.Create(e.Item2, e.Item1)] + JointLength)); if (startCurve == null || endCurve == null) { throw new Exception(); } } catch { throw new Exception("Joint not created. Joint lengths greater than rod length. Try reducing joint lengths or radius."); } // Convex hull points var vector = Point3d.Subtract(Vertices[e.Item2], Vertices[e.Item1]); vector.Unitize(); Polyline outerPoly; var outerProfile = GetProfile(OuterWallRadius, vector); outerProfile.TryGetPolyline(out outerPoly); foreach (var l in outerPoly.Skip(1)) { jointCorePoints[e.Item1].Add(new double[] { l.X + Vertices[e.Item1].X, l.Y + Vertices[e.Item1].Y, l.Z + Vertices[e.Item1].Z }); jointCorePoints[e.Item2].Add(new double[] { l.X + Vertices[e.Item2].X, l.Y + Vertices[e.Item2].Y, l.Z + Vertices[e.Item2].Z }); } // Create hollow joint arms var startMesh = GenerateJointArm(Vertices[e.Item1], vector, startCurve.GetLength(), Offsets[e]); var endMesh = GenerateJointArm(Vertices[e.Item2], vector, -endCurve.GetLength(), -Offsets[Tuple.Create(e.Item2, e.Item1)]); separateJointMeshes[e.Item1].Add(startMesh); separateJointMeshes[e.Item2].Add(endMesh); if (label) { // Create joint label var startLabel = GenerateJointArmLabel(Vertices[e.Item1], vector, e.Item1.ToString() + ((char)(jointArmCounter[e.Item1] + 64)).ToString(), startCurve.GetLength()); var endLabel = GenerateJointArmLabel(Vertices[e.Item2], vector, e.Item2.ToString() + ((char)(jointArmCounter[e.Item2] + 64)).ToString(), -endCurve.GetLength()); jointArmCounter[e.Item1]++; jointArmCounter[e.Item2]++; if (startLabel != null) { separateJointMeshes[e.Item1].Add(startLabel); } if (endLabel != null) { separateJointMeshes[e.Item2].Add(endLabel); } } } foreach (KeyValuePair <int, List <double[]> > kvp in jointCorePoints) { try { var scaling = Math.Floor(1000 / kvp.Value.SelectMany(p => p).Max()); var convHullRes = ConvexHull.Create(kvp.Value.Select(p => p.Select(pi => pi * scaling).ToArray()).ToList()); var hullPoints = convHullRes.Result.Points.ToList(); var hullFaces = convHullRes.Result.Faces.ToList(); var newMesh = new Mesh(); newMesh.Vertices.AddVertices(hullPoints.Select(p => new Point3d(p.Position[0] / scaling, p.Position[1] / scaling, p.Position[2] / scaling))); newMesh.Faces.AddFaces(hullFaces.Select(f => new MeshFace(hullPoints.IndexOf(f.Vertices[0]), hullPoints.IndexOf(f.Vertices[1]), hullPoints.IndexOf(f.Vertices[2])))); newMesh.Normals.ComputeNormals(); newMesh.UnifyNormals(); newMesh.Normals.ComputeNormals(); newMesh.Compact(); separateJointMeshes[kvp.Key].Insert(0, newMesh); // Add conv hull to beginning } catch { } } foreach (KeyValuePair <int, List <Mesh> > kvp in separateJointMeshes) { if (kvp.Value.Count > 0) { var mesh = kvp.Value.First(); foreach (var m in kvp.Value.Skip(1)) { mesh.Append(m); } mesh.Weld(Tolerance); JointMeshes[kvp.Key] = new List <Mesh>() { mesh }; } } return(JointMeshes); }
static TimeSpan TestNDConvexHull(int dim, int numVert, double size) { var vertices = CreateRandomVertices(dim, numVert, size); return(RunComputation(() => ConvexHull.Create(vertices))); }
public void InitLevel() { if (m_levelCounter >= m_levels.Count) { SceneManager.LoadScene(m_victoryScene); return; } // clear old level Clear(); //affine transformation // initialize settlements for (var i = 0; i < m_levels[m_levelCounter].Points.Count; i++) { m_levels[m_levelCounter].Points[i] += new Vector2(epsilon * (Random.Range(0f, 1f) - 0.5f), epsilon * (Random.Range(0f, 0.1f))); var point = m_levels[m_levelCounter].Points[i]; var obj = Instantiate(m_pointPrefab, point, Quaternion.identity) as GameObject; obj.transform.parent = this.transform; instantObjects.Add(obj); } foreach (var point in m_levels[m_levelCounter].Points) { } m_pointSelection = false; //Make vertex list m_points = FindObjectsOfType <P1HullPoint>().ToList(); // set maximum number of selected m_points var convexhulltemp = ConvexHull.ComputeConvexHull(m_points.Select(v => v.Pos)); m_pointNumberLimit = Random.Range(3, convexhulltemp.VertexCount + 1); if (m_pointNumberLimit < 3) { m_pointNumberLimit = 3; } // set selected number panel GameObject.Find("MaximumNumber").GetComponent <Text>().text = m_pointNumberLimit.ToString(); GameObject.Find("SelectedNumber").GetComponent <Text>().text = "0"; // compute maximum k-gon (Area) if (m_pointNumberLimit >= convexhulltemp.VertexCount) { m_solutionHull = convexhulltemp; } else { m_solutionHull = MaximumKgon.ComputeMaximumAreaKgon(m_points.Select(v => v.Pos), m_pointNumberLimit); } // set hint button Debug.Log(m_hint); foreach (var seg in m_solutionHull.Segments) { //Add a line renderer // instantiate new road mesh var hintmesh = Instantiate(m_hintLineMeshPrefab, Vector3.forward, Quaternion.identity) as GameObject; hintmesh.transform.parent = m_hint.transform; instantObjects.Add(hintmesh); hintMeshes.Add(hintmesh); hintmesh.GetComponent <P1HullSegment>().Segment = seg; var hintmeshScript = hintmesh.GetComponent <ReshapingMesh>(); hintmeshScript.CreateNewMesh(seg.Point1, seg.Point2); } m_hint.SetActive(false); //set stars information GameObject.Find("Area").GetComponent <Text>().text = "0"; m_rateList = new List <float>() { 0.6f, 0.8f, 0.95f, 1.0f }; Debug.Log(m_rateList.Count); for (int i = 1; i < m_rateList.Count; i++) { var objName = "Star" + i; Debug.Log(objName); var starArea = m_rateList[i - 1] * m_solutionHull.Area; GameObject.Find(objName).GetComponent <Text>().text = starArea.ToString(); } m_advanceButton.Disable(); }
private void ComputeConvexHull() { GeometryFactory fact = new GeometryFactory(); Coordinate[] coords = GetPointArray(); ConvexHull hull = new ConvexHull(coords, fact); _convexHull = hull.GetConvexHull(); }
public unsafe override void Initialize(ContentArchive content, Camera camera) { camera.Position = new Vector3(-30, 10, -30); //camera.Yaw = MathHelper.Pi ; camera.Yaw = MathHelper.Pi * 3f / 4; //camera.Pitch = MathHelper.PiOver2 * 0.999f; Simulation = Simulation.Create(BufferPool, new DemoNarrowPhaseCallbacks(), new DemoPoseIntegratorCallbacks(new Vector3(0, -10, 0))); var sphere = new Sphere(1.5f); var capsule = new Capsule(1f, 1f); var box = new Box(1f, 3f, 2f); var cylinder = new Cylinder(1.5f, 0.3f); const int pointCount = 32; var points = new QuickList <Vector3>(pointCount, BufferPool); //points.Allocate(BufferPool) = new Vector3(0, 0, 0); //points.Allocate(BufferPool) = new Vector3(0, 0, 1); //points.Allocate(BufferPool) = new Vector3(0, 1, 0); //points.Allocate(BufferPool) = new Vector3(0, 1, 1); //points.Allocate(BufferPool) = new Vector3(1, 0, 0); //points.Allocate(BufferPool) = new Vector3(1, 0, 1); //points.Allocate(BufferPool) = new Vector3(1, 1, 0); //points.Allocate(BufferPool) = new Vector3(1, 1, 1); var random = new Random(5); for (int i = 0; i < pointCount; ++i) { points.AllocateUnsafely() = new Vector3(3 * (float)random.NextDouble(), 1 * (float)random.NextDouble(), 3 * (float)random.NextDouble()); //points.AllocateUnsafely() = new Vector3(0, 1, 0) + Vector3.Normalize(new Vector3((float)random.NextDouble() * 2 - 1, (float)random.NextDouble() * 2 - 1, (float)random.NextDouble() * 2 - 1)) * (float)random.NextDouble(); } var convexHull = new ConvexHull(points.Span.Slice(0, points.Count), BufferPool, out _); box.ComputeInertia(1, out var boxInertia); capsule.ComputeInertia(1, out var capsuleInertia); sphere.ComputeInertia(1, out var sphereInertia); cylinder.ComputeInertia(1, out var cylinderInertia); convexHull.ComputeInertia(1, out var hullInertia); var boxIndex = Simulation.Shapes.Add(box); var capsuleIndex = Simulation.Shapes.Add(capsule); var sphereIndex = Simulation.Shapes.Add(sphere); var cylinderIndex = Simulation.Shapes.Add(cylinder); var hullIndex = Simulation.Shapes.Add(convexHull); const int width = 8; const int height = 16; const int length = 8; var shapeCount = 0; for (int i = 0; i < width; ++i) { for (int j = 0; j < height; ++j) { for (int k = 0; k < length; ++k) { var location = new Vector3(3, 3, 3) * new Vector3(i, j, k) + new Vector3(-width * 1.5f, 2.5f, -length * 1.5f); var bodyDescription = new BodyDescription { Activity = new BodyActivityDescription(0.01f), Pose = new RigidPose { Orientation = BepuUtilities.Quaternion.Identity, Position = location }, Collidable = new CollidableDescription { Continuity = new ContinuousDetectionSettings { Mode = ContinuousDetectionMode.Discrete }, SpeculativeMargin = 0.1f } }; var index = shapeCount++; switch ((index) % 5) { case 0: bodyDescription.Collidable.Shape = sphereIndex; bodyDescription.LocalInertia = sphereInertia; break; case 1: bodyDescription.Collidable.Shape = capsuleIndex; bodyDescription.LocalInertia = capsuleInertia; break; case 2: bodyDescription.Collidable.Shape = boxIndex; bodyDescription.LocalInertia = boxInertia; break; case 3: bodyDescription.Collidable.Shape = cylinderIndex; bodyDescription.LocalInertia = cylinderInertia; break; case 4: bodyDescription.Collidable.Shape = hullIndex; bodyDescription.LocalInertia = hullInertia; break; } Simulation.Bodies.Add(bodyDescription); } } } DemoMeshHelper.CreateDeformedPlane(128, 128, (x, y) => new Vector3(x - 64, 2f * (float)(Math.Sin(x * 0.5f) * Math.Sin(y * 0.5f)), y - 64), new Vector3(4, 1, 4), BufferPool, out var mesh); Simulation.Statics.Add(new StaticDescription(new Vector3(), new CollidableDescription(Simulation.Shapes.Add(mesh), 0.1f))); }