private void runTest(int samples, double radius) { double[] times = new double[samples]; Stopwatch watch = new Stopwatch(); Random rand = new Random(); Console.WriteLine("Cores: " + Environment.ProcessorCount); Console.WriteLine("64bit:" + Environment.Is64BitProcess + Environment.NewLine); for (int s = 0; s < samples; s++) { List <Vector3D> points = new List <Vector3D>(); List <PoissonDisc> tPoints = PoissonDiscSampling.Sample3D(84357, radius, new Vector3D(5, 5, 5), 4, false); foreach (PoissonDisc disc in tPoints) { points.Add(new Vector3D(disc.position.X, disc.position.Y, disc.position.Z)); } ConvexHull3D hull = new ConvexHull3D(); Console.WriteLine(points.Count); watch.Restart(); points = hull.ConstructHull(points); watch.Stop(); Console.WriteLine(points.Count); times[s] = watch.Elapsed.TotalMilliseconds; } Console.WriteLine(samples + ": avg => " + times.Average() + " | best => " + times.Min() + " | worst => " + times.Max()); }
//metric form edges public Metric(Vector3[] edges, float m = 0f, int crew_capacity = 0, bool compute_hull=false) : this() { if(compute_hull) hull = new ConvexHull3D(edges); bounds = initBounds(edges); volume = boundsVolume(bounds); area = boundsArea(bounds); mass = m; CrewCapacity = crew_capacity; }
public void Cube_ConvexHull() { pointCloudSource = PointCloud.CreateCube_Corners_CenteredAt0(0.1f); PointCloud.SetColorOfListTo(pointCloudSource, Color.Red); List <Vector3> myListVectors = pointCloudSource.ListVectors; ConvexHull3D convHull = new ConvexHull3D(myListVectors); ShowPointCloud(pointCloudSource); System.Diagnostics.Debug.WriteLine("Number of faces: " + convHull.Faces.ListFaces.Count.ToString()); }
public void Bunny_Hull() { string fileNameLong = pathUnitTests + "\\bunny.xyz"; pointCloudSource = IOUtils.ReadXYZFile_ToVertices(fileNameLong, false); PointCloud.SetColorOfListTo(pointCloudSource, System.Drawing.Color.Red); List <Vector3> myListVectors = pointCloudSource.ListVectors; ConvexHull3D cHull = new ConvexHull3D(myListVectors); ShowPointCloud(pointCloudSource); }
public override ModelContent Process(NodeContent input, ContentProcessorContext context) { var attributes = input.Children.ToDictionary(n => n.Name, n => n.OpaqueData); var nodesToRemove = (from node in input.Children where node.OpaqueData.GetAttribute(TYPE_ATTR_NAME, MeshType.Both) == MeshType.Physical select node).ToArray(); ModelContent model = base.Process(input, context); var parts = new List <CompiledPart>(); var materials = new List <Material>(); var mass = new MassProperties(); var centerOfMass = Vector3.Zero; foreach (var mesh in model.Meshes) { MeshType type = MeshType.Both; PhysicalShape shape = PhysicalShape.Mesh; float elasticity = _defaultElasticity, roughness = _defaultRoughness, density = _defaultDensity; if (attributes.ContainsKey(mesh.Name)) { type = attributes[mesh.Name].GetAttribute(TYPE_ATTR_NAME, MeshType.Both); if (type == MeshType.Visual) { continue; } elasticity = attributes[mesh.Name].GetAttribute(ELASTICITY_ATTR_NAME, _defaultElasticity); roughness = attributes[mesh.Name].GetAttribute(ROUGHNESS_ATTR_NAME, _defaultRoughness); density = attributes[mesh.Name].GetAttribute(DENSITY_ATTR_NAME, _defaultDensity); shape = attributes[mesh.Name].GetAttribute(SHAPE_ATTR_NAME, _defaultShape); } var meshCenterOfMass = Vector3.Zero; var meshMass = MassProperties.Immovable; CompiledPart meshPart = null; if (mesh.MeshParts.Count < 1) { continue; } int[] indices = mesh.MeshParts[0].IndexBuffer.Skip(mesh.MeshParts[0].StartIndex).Take(mesh.MeshParts[0].PrimitiveCount * 3).ToArray(); Vector3[] vertices = MeshToVertexArray(context.TargetPlatform, mesh); if (_windingOrder == WindingOrder.Clockwise) { ReverseWindingOrder(indices); } switch (shape) { case PhysicalShape.Mesh: { meshPart = new CompiledMesh(vertices, indices); meshMass = MassProperties.Immovable; meshCenterOfMass = GetMeshTranslation(mesh); } break; case PhysicalShape.Polyhedron: { var hull = new ConvexHull3D(vertices); meshPart = hull.ToPolyhedron(); meshMass = MassProperties.FromTriMesh(density, vertices, indices, out meshCenterOfMass); } break; case PhysicalShape.Sphere: { Sphere s; Sphere.Fit(vertices, out s); meshPart = new CompiledSphere(s.Center, s.Radius); meshMass = MassProperties.FromSphere(density, s.Center, s.Radius); meshCenterOfMass = s.Center; } break; case PhysicalShape.Capsule: { Capsule c; Capsule.Fit(vertices, out c); meshPart = new CompiledCapsule(c.P1, c.P2, c.Radius); meshMass = MassProperties.FromCapsule(density, c.P1, c.P2, c.Radius, out meshCenterOfMass); } break; } parts.Add(meshPart); materials.Add(new Material(elasticity, roughness)); Vector3.Multiply(ref meshCenterOfMass, meshMass.Mass, out meshCenterOfMass); Vector3.Add(ref centerOfMass, ref meshCenterOfMass, out centerOfMass); mass.Mass += meshMass.Mass; meshMass.Inertia.M44 = 0f; Matrix.Add(ref mass.Inertia, ref meshMass.Inertia, out mass.Inertia); } // compute mass properties Vector3.Divide(ref centerOfMass, mass.Mass, out centerOfMass); mass.Inertia.M44 = 1f; MassProperties.TranslateInertiaTensor(ref mass.Inertia, -mass.Mass, centerOfMass, out mass.Inertia); if (centerOfMass.Length() >= Constants.Epsilon) { var transform = Matrix.CreateTranslation(-centerOfMass.X, -centerOfMass.Y, -centerOfMass.Z); foreach (var p in parts) { p.Transform(ref transform); } transform = model.Root.Transform; transform.M41 -= centerOfMass.X; transform.M42 -= centerOfMass.Y; transform.M43 -= centerOfMass.Z; model.Root.Transform = transform; } mass = new MassProperties(mass.Mass, mass.Inertia); var rbm = new RigidBodyModel(mass, parts.ToArray(), materials.ToArray()); // remove non-visual nodes if (nodesToRemove.Length > 0) { foreach (var node in nodesToRemove) { input.Children.Remove(node); } model = base.Process(input, context); } model.Tag = rbm; return(model); }
public override ModelContent Process(NodeContent input, ContentProcessorContext context) { var attributes = input.Children.ToDictionary(n => n.Name, n => n.OpaqueData); var nodesToRemove = (from node in input.Children where node.OpaqueData.GetAttribute(TYPE_ATTR_NAME, MeshType.Both) == MeshType.Physical select node).ToArray(); ModelContent model = base.Process(input, context); var parts = new List<CompiledPart>(); var materials = new List<Material>(); var mass = new MassProperties(); var centerOfMass = Vector3.Zero; foreach (var mesh in model.Meshes) { MeshType type = MeshType.Both; PhysicalShape shape = PhysicalShape.Mesh; float elasticity = _defaultElasticity, roughness = _defaultRoughness, density = _defaultDensity; if (attributes.ContainsKey(mesh.Name)) { type = attributes[mesh.Name].GetAttribute(TYPE_ATTR_NAME, MeshType.Both); if (type == MeshType.Visual) continue; elasticity = attributes[mesh.Name].GetAttribute(ELASTICITY_ATTR_NAME, _defaultElasticity); roughness = attributes[mesh.Name].GetAttribute(ROUGHNESS_ATTR_NAME, _defaultRoughness); density = attributes[mesh.Name].GetAttribute(DENSITY_ATTR_NAME, _defaultDensity); shape = attributes[mesh.Name].GetAttribute(SHAPE_ATTR_NAME, _defaultShape); } var meshCenterOfMass = Vector3.Zero; var meshMass = MassProperties.Immovable; CompiledPart meshPart = null; if (mesh.MeshParts.Count < 1) { continue; } int[] indices = mesh.MeshParts[0].IndexBuffer.Skip(mesh.MeshParts[0].StartIndex).Take(mesh.MeshParts[0].PrimitiveCount * 3).ToArray(); Vector3[] vertices = MeshToVertexArray(context.TargetPlatform, mesh); if (_windingOrder == WindingOrder.Clockwise) { ReverseWindingOrder(indices); } switch (shape) { case PhysicalShape.Mesh: { meshPart = new CompiledMesh(vertices, indices); meshMass = MassProperties.Immovable; meshCenterOfMass = GetMeshTranslation(mesh); } break; case PhysicalShape.Polyhedron: { var hull = new ConvexHull3D(vertices); meshPart = hull.ToPolyhedron(); meshMass = MassProperties.FromTriMesh(density, vertices, indices, out meshCenterOfMass); } break; case PhysicalShape.Sphere: { Sphere s; Sphere.Fit(vertices, out s); meshPart = new CompiledSphere(s.Center, s.Radius); meshMass = MassProperties.FromSphere(density, s.Center, s.Radius); meshCenterOfMass = s.Center; } break; case PhysicalShape.Capsule: { Capsule c; Capsule.Fit(vertices, out c); meshPart = new CompiledCapsule(c.P1, c.P2, c.Radius); meshMass = MassProperties.FromCapsule(density, c.P1, c.P2, c.Radius, out meshCenterOfMass); } break; } parts.Add(meshPart); materials.Add(new Material(elasticity, roughness)); Vector3.Multiply(ref meshCenterOfMass, meshMass.Mass, out meshCenterOfMass); Vector3.Add(ref centerOfMass, ref meshCenterOfMass, out centerOfMass); mass.Mass += meshMass.Mass; meshMass.Inertia.M44 = 0f; Matrix.Add(ref mass.Inertia, ref meshMass.Inertia, out mass.Inertia); } // compute mass properties Vector3.Divide(ref centerOfMass, mass.Mass, out centerOfMass); mass.Inertia.M44 = 1f; MassProperties.TranslateInertiaTensor(ref mass.Inertia, -mass.Mass, centerOfMass, out mass.Inertia); if (centerOfMass.Length() >= Constants.Epsilon) { var transform = Matrix.CreateTranslation(-centerOfMass.X, -centerOfMass.Y, -centerOfMass.Z); foreach (var p in parts) { p.Transform(ref transform); } transform = model.Root.Transform; transform.M41 -= centerOfMass.X; transform.M42 -= centerOfMass.Y; transform.M43 -= centerOfMass.Z; model.Root.Transform = transform; } mass = new MassProperties(mass.Mass, mass.Inertia); var rbm = new RigidBodyModel(mass, parts.ToArray(), materials.ToArray()); // remove non-visual nodes if (nodesToRemove.Length > 0) { foreach (var node in nodesToRemove) input.Children.Remove(node); model = base.Process(input, context); } model.Tag = rbm; return model; }
//mesh metric public Metric(Part part, string mesh_name, bool compute_hull=false) : this() { if(string.IsNullOrEmpty(mesh_name)) return; MeshFilter m = part.FindModelComponent<MeshFilter>(mesh_name); if(m == null) { Utils.Log("[Metric] {0} does not have '{1}' mesh", part.name, mesh_name); return; } if(compute_hull) hull = new ConvexHull3D(uniqueVertices(m.sharedMesh)); Vector3[] edges = BoundsEdges(m.sharedMesh.bounds); local2local(m.transform, part.partTransform, edges); bounds = initBounds(edges); volume = boundsVolume(bounds); area = boundsArea(bounds); mass = 0f; }
Bounds partsBounds(List<Part> parts, Transform vT, bool compute_hull=false) { //reset metric mass = 0; cost = 0; CrewCapacity = 0; Bounds b = default(Bounds); if(parts == null || parts.Count == 0) { Utils.Log("Metric.partsBounds: WARNING! No parts were provided."); return b; } //calculate bounds and convex hull float b_size = 0; List<Vector3> hull_points = compute_hull ? new List<Vector3>() : null; foreach(Part p in parts) { if(p == null) continue; //EditorLogic.SortedShipList returns List<Part>{null} when all parts are deleted foreach(MeshFilter m in p.FindModelComponents<MeshFilter>()) { //skip meshes without renderer if(m.renderer == null || !m.renderer.enabled) continue; //skip meshes from the blacklist bool skip_mesh = false; foreach(string mesh_name in HangarConfig.Globals.MeshesToSkipList) { if(mesh_name == "") continue; skip_mesh = m.name.IndexOf(mesh_name, StringComparison.OrdinalIgnoreCase) >= 0; if(skip_mesh) break; } if(skip_mesh) continue; //wheels are round and rotating >_< //TODO: rework this block for more efficiency: do not call Mesh.vertices twice Vector3[] edges = m.name.IndexOf("wheel", StringComparison.OrdinalIgnoreCase) >= 0 ? m.sharedMesh.vertices : BoundsEdges(m.sharedMesh.bounds); updateBounds(ref b, local2local(m.transform, vT, edges)); if(compute_hull) { float m_size = Vector3.Scale(m.sharedMesh.bounds.size, m.transform.lossyScale).sqrMagnitude; var verts = m_size > b_size/10? local2local(m.transform, vT, uniqueVertices(m.sharedMesh)) : edges; hull_points.AddRange(verts); b_size = b.size.sqrMagnitude; } } CrewCapacity += p.CrewCapacity; if(p.IsPhysicallySignificant()) mass += p.TotalMass(); cost += p.TotalCost(); } if(compute_hull && hull_points.Count >= 4) hull = new ConvexHull3D(hull_points); return b; }