private GameObject HandleVisualGeometry(XElement geometry, GameObject parentLink) { GameObject visual = null; foreach (var childElement in geometry.Elements()) { var scale = Vector3.one; var rotation = Quaternion.identity; visual = null; switch (childElement.Name.ToString()) { case "mesh": var scaleElem = childElement.Element("scale"); if (scaleElem != null) { scale = ParseSDFSize(scaleElem); } var uri = childElement.Element("uri").Value; var prefab = document.LoadAsset <GameObject>(uri); if (prefab != null) { visual = PrefabUtility.InstantiatePrefab(prefab, parentLink.transform) as GameObject; rotation = Quaternion.Euler(-90, 90, 0); if (uri.ToLower().EndsWith(".stl")) { // STL import package has weird behaviour wrt right handed coordinate system scale.Scale(new Vector3(-1, 1, 1)); } } break; case "box": visual = GameObject.CreatePrimitive(PrimitiveType.Cube); scale = ParseSDFSize(childElement.Element("size")); break; case "sphere": visual = GameObject.CreatePrimitive(PrimitiveType.Sphere); var r = ParseSingle(childElement.Element("radius"), 1.0f); scale = new Vector3(r, r, r); break; case "cylinder": visual = GameObject.CreatePrimitive(PrimitiveType.Cylinder); var radius = ParseSingle(childElement.Element("radius"), 1.0f); var length = ParseSingle(childElement.Element("length"), 1.0f); scale = new Vector3(radius * 2.0f, length * 0.5f, radius * 2.0f); break; case "plane": visual = GameObject.CreatePrimitive(PrimitiveType.Plane); var normal = ParseSDFVector(childElement.Element("normal")); var(scaleX, scaleZ) = ParseXY(childElement.Element("size"), (1.0f, 1.0f)); scale = new Vector3(scaleX, 1.0f, scaleZ); rotation = Quaternion.LookRotation(normal != Vector3.forward ? Vector3.forward : Vector3.left, normal); break; default: Debug.Log("unhandled visual type " + childElement + " in " + geometry); break; } if (visual != null) { foreach (var collider in visual.GetComponentsInChildren <Collider>()) { GameObject.DestroyImmediate(collider); } visual.isStatic = parentLink.isStatic; visual.transform.SetParent(parentLink.transform, false); visual.transform.localPosition = Vector3.zero; visual.transform.localScale = scale; visual.transform.localRotation = rotation; } } return(visual); }
private void HandleCollisionGeometry(XElement geometryElement, GameObject collisionObject) { var scale = Vector3.one; var rotation = Quaternion.identity; var box = geometryElement.Element("box"); var cylinder = geometryElement.Element("cylinder"); var mesh = geometryElement.Element("mesh"); var plane = geometryElement.Element("plane"); if (mesh != null) { var scaleElem = mesh.Element("scale"); if (scaleElem != null) { var parts = scaleElem.Value.Split(' '); scale = new Vector3( Convert.ToSingle(parts[0], CultureInfo.InvariantCulture), Convert.ToSingle(parts[1], CultureInfo.InvariantCulture), Convert.ToSingle(parts[2], CultureInfo.InvariantCulture)); } var meshAsset = document.LoadAsset <Mesh>(mesh.Element("uri")); if (meshAsset != null) { var collider = collisionObject.AddComponent <MeshCollider>(); collider.sharedMesh = meshAsset; collider.convex = !collisionObject.isStatic; rotation = Quaternion.Euler(-90, 90, 0); } } else if (box != null) { var collider = collisionObject.AddComponent <BoxCollider>(); var parts = box.Element("size")?.Value.Split(' '); collider.size = new Vector3( Convert.ToSingle(parts[0], CultureInfo.InvariantCulture), Convert.ToSingle(parts[1], CultureInfo.InvariantCulture), Convert.ToSingle(parts[2], CultureInfo.InvariantCulture)); } else if (cylinder != null) { float length = Convert.ToSingle(cylinder.Element("length")?.Value, CultureInfo.InvariantCulture); float radius = Convert.ToSingle(cylinder.Element("radius")?.Value, CultureInfo.InvariantCulture); if (length < radius * SDFDocument.cylinderUseMeshRadiusLengthFactor) { var collider = collisionObject.AddComponent <MeshCollider>(); var helper = GameObject.CreatePrimitive(PrimitiveType.Cylinder); collider.sharedMesh = helper.GetComponent <MeshFilter>().sharedMesh; GameObject.DestroyImmediate(helper); collider.convex = !collisionObject.isStatic; scale = new Vector3(2 * radius, length * 0.5f, 2 * radius); } else { // FIXME a cylinder is not a capsule actually var collider = collisionObject.AddComponent <CapsuleCollider>(); collider.height = length; collider.radius = radius; } } else if (plane != null) { var helper = GameObject.CreatePrimitive(PrimitiveType.Plane); var collider = collisionObject.AddComponent <MeshCollider>(); collider.sharedMesh = helper.GetComponent <MeshFilter>().sharedMesh; GameObject.DestroyImmediate(helper); var normal = ParseSDFVector(plane.Element("normal")); var(scaleX, scaleZ) = ParseXY(plane.Element("size"), (1.0f, 1.0f)); scale = new Vector3(scaleX, 1.0f, scaleZ); rotation = Quaternion.LookRotation(normal != Vector3.forward ? Vector3.forward : Vector3.left, normal); } else { Debug.Log("unhandled collision type in " + geometryElement); } if (collisionObject.GetComponent <Collider>() != null) { ApplyPose(geometryElement.Parent, collisionObject); collisionObject.transform.localScale = scale; collisionObject.transform.rotation *= rotation; } }