private Node CreateNode(NodeType type, agx.Uuid uuid, bool isRoot) { Node node = new Node() { Type = type, Uuid = uuid }; if (isRoot) { if (type == NodeType.Constraint) { m_constraintRoot.AddChild(node); } else if (type == NodeType.Material) { m_materialRoot.AddChild(node); } else if (type == NodeType.ContactMaterial) { m_contactMaterialRoot.AddChild(node); } else if (type == NodeType.Wire) { m_wireRoot.AddChild(node); } else if (type == NodeType.Cable) { m_cableRoot.AddChild(node); } else if (type == NodeType.ObserverFrame) { m_observerFrameRoot.AddChild(node); } else if (m_roots.FindIndex(n => n.Uuid == uuid) >= 0) { Debug.LogError("Node already present as root."); } else { m_roots.Add(node); } } m_nodeCache.Add(uuid, node); return(node); }
private T AddOrReplaceAsset <T>(T asset, Node node, AGXUnity.IO.AssetType type) where T : UnityEngine.Object { var existingAsset = AssetDatabase.LoadAssetAtPath <T>(FileInfo.GetAssetPath(asset)); if (existingAsset == null) { FileInfo.AddAssetToDataDirectory(asset, type); existingAsset = asset; } else { EditorUtility.CopySerialized(asset, existingAsset); } return(existingAsset); }
private GameObject GetOrCreateGameObject(Node node) { if (node.GameObject != null) { return(node.GameObject); } node.GameObject = FileInfo.ObjectDb.GetGameObject(node.Uuid) ?? new GameObject(); node.GameObject.GetOrCreateComponent <AGXUnity.IO.Uuid>().Native = node.Uuid; // Is it safe to exit if the node has a parent? // I.e., the node has been read from an existing prefab. if (FileInfo.PrefabInstance.HasChild(node.GameObject)) { return(node.GameObject); } // Passing parents with null game objects - e.g., shapes // has geometry as parent but we're not creating objects // for geometries. Node localParent = node.Parent; while (localParent != null && localParent.GameObject == null) { localParent = localParent.Parent; } if (localParent != null) { localParent.GameObject.AddChild(node.GameObject); } else { FileInfo.PrefabInstance.AddChild(node.GameObject); } return(node.GameObject); }
private void Parse(agxCollide.Geometry geometry, Node parent) { var geometryNode = GetOrCreateGeometry(geometry, parent == null); if (parent != null) { parent.AddChild(geometryNode); } foreach (var shape in geometry.getShapes()) { var shapeNode = GetOrCreateShape(shape.get()); geometryNode.AddChild(shapeNode); } if (geometry.getMaterial() != null) { var materialNode = GetOrCreateMaterial(geometry.getMaterial()); geometryNode.AddReference(materialNode); } var groupsCollection = geometry.findGroupIdCollection(); foreach (var name in groupsCollection.getNames()) { geometryNode.AddReference(new Node() { Type = NodeType.GroupId, Object = name }); } foreach (var id in groupsCollection.getIds()) { geometryNode.AddReference(new Node() { Type = NodeType.GroupId, Object = id.ToString() }); } }
private bool CreateCable(Node node) { var nativeCable = m_tree.GetCable(node.Uuid); if (nativeCable == null) { Debug.LogWarning("Unable to find native instance of cable: " + node.GameObject.name + " (UUID: " + node.Uuid.str() + ")"); return(false); } var cable = node.GameObject.GetOrCreateComponent <Cable>(); var route = cable.Route; route.Clear(); cable.RestoreLocalDataFrom(nativeCable); cable.RouteAlgorithm = Cable.RouteType.Identity; var properties = CableProperties.Create <CableProperties>().RestoreLocalDataFrom(nativeCable.getCableProperties(), nativeCable.getCablePlasticity()); properties.name = cable.name + "_properties"; cable.Properties = properties = AddOrReplaceAsset(properties, node, AGXUnity.IO.AssetType.CableProperties); for (var it = nativeCable.getSegments().begin(); !it.EqualWith(nativeCable.getSegments().end()); it.inc()) { var segment = it.get(); route.Add(segment, attachment => { if (attachment == null || attachment.getRigidBody() == null) { return(FileInfo.PrefabInstance); } var rbNode = m_tree.GetNode(attachment.getRigidBody().getUuid()); if (rbNode == null) { Debug.LogWarning("Unable to find rigid body in cable attachment."); return(FileInfo.PrefabInstance); } return(rbNode.GameObject); }); } var materials = node.GetReferences(Node.NodeType.Material); if (materials.Length > 0) { cable.Material = materials[0].Asset as ShapeMaterial; } cable.GetComponent <CableRenderer>().InitializeRenderer(); cable.GetComponent <CableRenderer>().Material = null; // Adding collision group from restored instance since the disabled pair // will be read from Space (cable.setEnableCollisions( foo, false ) will // work out of the box). var collisionGroups = cable.gameObject.GetOrCreateComponent <CollisionGroups>(); collisionGroups.AddGroup(nativeCable.getUniqueId().ToString(), false); var referencedGroups = node.GetReferences(Node.NodeType.GroupId); foreach (var group in referencedGroups) { if (group.Object is string) { collisionGroups.AddGroup(group.Object as string, false); } } return(true); }
private bool CreateWire(Node node) { var nativeWire = m_tree.GetWire(node.Uuid); if (nativeWire == null) { Debug.LogWarning("Unable to find native instance of wire: " + node.GameObject.name + " (UUID: " + node.Uuid.str() + ")"); return(false); } Func <agx.RigidBody, GameObject> findRigidBody = (nativeRb) => { if (nativeRb == null) { return(FileInfo.PrefabInstance); } // Do not reference lumped nodes! if (agxWire.Wire.isLumpedNode(nativeRb)) { return(FileInfo.PrefabInstance); } Node rbNode = m_tree.GetNode(nativeRb.getUuid()); if (rbNode == null) { Debug.LogWarning("Unable to find reference rigid body: " + nativeRb.getName() + " (UUID: " + nativeRb.getUuid().str() + ")"); return(FileInfo.PrefabInstance); } if (rbNode.GameObject == null) { Debug.LogWarning("Referenced native rigid body hasn't a game object: " + nativeRb.getName() + " (UUID: " + rbNode.Uuid.str() + ")"); return(FileInfo.PrefabInstance); } return(rbNode.GameObject); }; var wire = node.GameObject.GetOrCreateComponent <Wire>(); var route = wire.Route; route.Clear(); wire.RestoreLocalDataFrom(nativeWire); var nativeIt = nativeWire.getRenderBeginIterator(); var nativeEndIt = nativeWire.getRenderEndIterator(); var nativeBeginWinch = nativeWire.getWinchController(0u); var nativeEndWinch = nativeWire.getWinchController(1u); if (nativeBeginWinch != null) { route.Add(nativeBeginWinch, findRigidBody(nativeBeginWinch.getRigidBody())); } // Connecting nodes will show up in render iterators. else if (nativeIt.get().getNodeType() != agxWire.WireNode.Type.CONNECTING && nativeWire.getFirstNode().getNodeType() == agxWire.WireNode.Type.BODY_FIXED) { route.Add(nativeWire.getFirstNode(), findRigidBody(nativeWire.getFirstNode().getRigidBody())); } while (!nativeIt.EqualWith(nativeEndIt)) { var nativeNode = nativeIt.get(); // Handing ContactNode and ShapeContactNode parenting. GameObject nodeParent = null; if (nativeNode.getType() == agxWire.WireNode.Type.CONTACT) { var nativeGeometry = nativeNode.getAsContact().getGeometry(); var geometryNode = m_tree.GetNode(nativeGeometry.getUuid()); if (geometryNode != null && geometryNode.GetChildren(Node.NodeType.Shape).Length > 0) { nodeParent = geometryNode.GetChildren(Node.NodeType.Shape)[0].GameObject; } } else if (nativeNode.getType() == agxWire.WireNode.Type.SHAPE_CONTACT) { var nativeShape = nativeNode.getAsShapeContact().getShape(); var shapeNode = m_tree.GetNode(nativeShape.getUuid()); if (shapeNode != null) { nodeParent = shapeNode.GameObject; } } if (nodeParent == null) { nodeParent = findRigidBody(nativeNode.getRigidBody()); } route.Add(nativeNode, nodeParent); nativeIt.inc(); } // Remove last node if we should have a winch or a body fixed node there. if (route.Last().Type == Wire.NodeType.FreeNode && nativeWire.getLastNode().getNodeType() == agxWire.WireNode.Type.BODY_FIXED) { route.Remove(route.Last()); } if (nativeEndWinch != null) { route.Add(nativeEndWinch, findRigidBody(nativeEndWinch.getRigidBody())); } else if (nativeIt.prev().get().getNodeType() != agxWire.WireNode.Type.CONNECTING && nativeWire.getLastNode().getNodeType() == agxWire.WireNode.Type.BODY_FIXED) { route.Add(nativeWire.getLastNode(), findRigidBody(nativeWire.getLastNode().getRigidBody())); } var materials = node.GetReferences(Node.NodeType.Material); if (materials.Length > 0) { wire.Material = materials[0].Asset as ShapeMaterial; } wire.GetComponent <WireRenderer>().InitializeRenderer(); // Reset to assign default material. wire.GetComponent <WireRenderer>().Material = null; // Adding collision group from restored instance since the disabled pair // will be read from Space (wire.setEnableCollisions( foo, false ) will // work out of the box). var collisionGroups = wire.gameObject.GetOrCreateComponent <CollisionGroups>(); collisionGroups.AddGroup(nativeWire.getGeometryController().getDisabledCollisionsGroupId().ToString(), false); foreach (var id in nativeWire.getGeometryController().getGroupIds()) { collisionGroups.AddGroup(id.ToString(), false); } return(true); }
private bool CreateConstraint(Node node) { var nativeConstraint = m_tree.GetConstraint(node.Uuid); if (nativeConstraint == null) { Debug.LogWarning("Unable to find native constraint instance with name: " + node.GameObject.name + " (UUID: " + node.Uuid.str() + ")"); return(false); } var bodyNodes = node.GetReferences(Node.NodeType.RigidBody); if (bodyNodes.Length < 1 || bodyNodes.Length > 2) { Debug.LogWarning("Unsupported number of body references to constraint with name: " + node.GameObject.name + " (#bodies: " + bodyNodes.Length + ")"); return(false); } var constraintType = Constraint.FindType(nativeConstraint); if (constraintType == ConstraintType.Unknown) { Debug.LogWarning("Unknown/unsupported constraint type of constraint with name: " + node.GameObject.name + " (UUID: " + node.Uuid.str() + ")"); return(false); } Constraint constraint = node.GameObject.GetOrCreateComponent <Constraint>(); // Is the constraint enabled/active? // Somewhat strange though: Why is not only the Constraint component disabled? // For RigidBody component, only that component is disabled, but the below code disables the whole constraint GameObject. // Works for now constraint.gameObject.SetActive(nativeConstraint.isEnabled()); constraint.SetType(constraintType, true); try { constraint.TryAddElementaryConstraints(nativeConstraint); constraint.VerifyImplementation(); } catch (System.Exception e) { Debug.LogException(e); return(false); } // Scaling damping to our (sigh) hard coded time step. float fixedStepTime = AGXUnity.Simulation.DefaultTimeStep; float readTimeStep = Convert.ToSingle(Simulation.getTimeStep()); float timeStepRatio = fixedStepTime / readTimeStep; if (!Mathf.Approximately(timeStepRatio, 1.0f)) { foreach (var ec in constraint.ElementaryConstraints) { foreach (var rowData in ec.RowData) { if (rowData.Compliance < -float.Epsilon) { Debug.LogWarning("Constraint: " + constraint.name + " (ec name: " + rowData.ElementaryConstraint.NativeName + ")," + " has too low compliance: " + rowData.Compliance + ". Setting to zero."); rowData.Compliance = 0.0f; } else if (rowData.Compliance > float.MaxValue) { Debug.LogWarning("Constraint: " + constraint.name + " (ec name: " + rowData.ElementaryConstraint.NativeName + ")," + " has too high compliance: " + rowData.Compliance + ". Setting to a large value."); rowData.Compliance = 0.5f * float.MaxValue; } rowData.Damping *= timeStepRatio; } } } constraint.AttachmentPair.ReferenceFrame.SetParent(bodyNodes[0].GameObject); constraint.AttachmentPair.ReferenceFrame.LocalPosition = nativeConstraint.getAttachment(0ul).getFrame().getLocalTranslate().ToHandedVector3(); constraint.AttachmentPair.ReferenceFrame.LocalRotation = nativeConstraint.getAttachment(0ul).getFrame().getLocalRotate().ToHandedQuaternion(); if (bodyNodes.Length > 1) { constraint.AttachmentPair.ConnectedFrame.SetParent(bodyNodes[1].GameObject); } else { constraint.AttachmentPair.ConnectedFrame.SetParent(FileInfo.PrefabInstance); } constraint.AttachmentPair.ConnectedFrame.LocalPosition = nativeConstraint.getAttachment(1ul).getFrame().getLocalTranslate().ToHandedVector3(); constraint.AttachmentPair.ConnectedFrame.LocalRotation = nativeConstraint.getAttachment(1ul).getFrame().getLocalRotate().ToHandedQuaternion(); constraint.AttachmentPair.Synchronized = constraintType != ConstraintType.DistanceJoint; return(true); }
private bool CreateRenderData(Node node) { var nativeShape = m_tree.GetShape(node.Uuid); var renderData = nativeShape.getRenderData(); if (renderData == null || !renderData.getShouldRender()) { return(false); } var nativeGeometry = m_tree.GetGeometry(node.Parent.Uuid); var shape = node.GameObject.GetComponent <AGXUnity.Collide.Shape>(); var toWorld = nativeGeometry.getTransform(); var toLocal = shape.transform.worldToLocalMatrix; var meshes = new Mesh[] { }; if (renderData.getVertexArray().Count > UInt16.MaxValue) { Debug.LogWarning("Render data contains more than " + UInt16.MaxValue + " vertices. Splitting it into smaller meshes."); var splitter = MeshSplitter.Split(renderData.getVertexArray(), renderData.getIndexArray(), v => toLocal.MultiplyPoint3x4(toWorld.preMult(v).ToHandedVector3())); meshes = splitter.Meshes; for (int i = 0; i < meshes.Length; ++i) { meshes[i].name = shape.name + "_Visual_Mesh_" + i.ToString(); } } else { var mesh = new Mesh(); mesh.name = shape.name + "_Visual_Mesh"; // Assigning and converting vertices. // Note: RenderData vertices assumed to be given in geometry coordinates. mesh.SetVertices((from v in renderData.getVertexArray() select toLocal.MultiplyPoint3x4(toWorld.preMult(v).ToHandedVector3())).ToList()); // Assigning and converting colors. mesh.SetColors((from c in renderData.getColorArray() select c.ToColor()).ToList()); // Unsure about this one. mesh.SetUVs(0, (from uv in renderData.getTexCoordArray() select uv.ToVector2()).ToList()); // Converting counter clockwise -> clockwise. var triangles = new List <int>(); var indexArray = renderData.getIndexArray(); for (int i = 0; i < indexArray.Count; i += 3) { triangles.Add(Convert.ToInt32(indexArray[i + 0])); triangles.Add(Convert.ToInt32(indexArray[i + 2])); triangles.Add(Convert.ToInt32(indexArray[i + 1])); } mesh.SetTriangles(triangles, 0, false); mesh.RecalculateBounds(); mesh.RecalculateNormals(); mesh.RecalculateTangents(); meshes = new Mesh[] { mesh }; } var shader = Shader.Find("Standard") ?? Shader.Find("Diffuse"); if (shader == null) { Debug.LogError("Unable to find standard shaders."); } var renderMaterial = renderData.getRenderMaterial(); var material = new Material(shader); material.name = shape.name + "_Visual_Material"; if (renderMaterial.hasDiffuseColor()) { var color = renderMaterial.getDiffuseColor().ToColor(); color.a = 1.0f - renderMaterial.getTransparency(); material.SetVector("_Color", color); } if (renderMaterial.hasEmissiveColor()) { material.SetVector("_EmissionColor", renderMaterial.getEmissiveColor().ToColor()); } material.SetFloat("_Metallic", 0.3f); material.SetFloat("_Glossiness", 0.8f); if (renderMaterial.getTransparency() > 0.0f) { material.SetBlendMode(BlendMode.Transparent); } material = AddOrReplaceAsset(material, node, AGXUnity.IO.AssetType.Material); foreach (var mesh in meshes) { AddOrReplaceAsset(mesh, node, AGXUnity.IO.AssetType.RenderMesh); } var shapeVisual = ShapeVisual.Find(shape); if (shapeVisual != null) { // Verify so that the meshes matches the current configuration? } else { ShapeVisual.CreateRenderData(shape, meshes, material); } return(true); }
private bool CreateShape(Node node) { var nativeGeometry = m_tree.GetGeometry(node.Parent.Uuid); var nativeShape = m_tree.GetShape(node.Uuid); var nativeShapeType = (agxCollide.Shape.Type)nativeShape.getType(); if (nativeShapeType == agxCollide.Shape.Type.BOX) { node.GameObject.GetOrCreateComponent <AGXUnity.Collide.Box>().HalfExtents = nativeShape.asBox().getHalfExtents().ToVector3(); } else if (nativeShapeType == agxCollide.Shape.Type.CYLINDER) { var cylinder = node.GameObject.GetOrCreateComponent <AGXUnity.Collide.Cylinder>(); cylinder.Radius = Convert.ToSingle(nativeShape.asCylinder().getRadius()); cylinder.Height = Convert.ToSingle(nativeShape.asCylinder().getHeight()); } else if (nativeShapeType == agxCollide.Shape.Type.CAPSULE) { var capsule = node.GameObject.GetOrCreateComponent <AGXUnity.Collide.Capsule>(); capsule.Radius = Convert.ToSingle(nativeShape.asCapsule().getRadius()); capsule.Height = Convert.ToSingle(nativeShape.asCapsule().getHeight()); } else if (nativeShapeType == agxCollide.Shape.Type.SPHERE) { var sphere = node.GameObject.GetOrCreateComponent <AGXUnity.Collide.Sphere>(); sphere.Radius = Convert.ToSingle(nativeShape.asSphere().getRadius()); } else if (nativeShapeType == agxCollide.Shape.Type.CONVEX || nativeShapeType == agxCollide.Shape.Type.TRIMESH || nativeShapeType == agxCollide.Shape.Type.HEIGHT_FIELD) { var mesh = node.GameObject.GetOrCreateComponent <AGXUnity.Collide.Mesh>(); var collisionData = nativeShape.asMesh().getMeshData(); var nativeToWorld = nativeShape.getTransform(); var meshToLocal = mesh.transform.worldToLocalMatrix; if (collisionData.getVertices().Count > UInt16.MaxValue) { var nativeVertices = collisionData.getVertices(); var nativeIndicies = collisionData.getIndices(); var splitter = MeshSplitter.Split(nativeVertices, nativeIndicies, v => meshToLocal.MultiplyPoint3x4(nativeToWorld.preMult(v).ToHandedVector3())); var subMeshes = splitter.Meshes; for (int i = 0; i < subMeshes.Length; ++i) { subMeshes[i].name = "Mesh_" + mesh.name + (i == 0 ? "" : "_Sub_" + i.ToString()); mesh.AddSourceObject(AddOrReplaceAsset(subMeshes[i], node, AGXUnity.IO.AssetType.CollisionMesh)); } } else { var source = new Mesh(); source.name = "Mesh_" + mesh.name; source.SetVertices((from v in collisionData.getVertices() select meshToLocal.MultiplyPoint3x4(nativeToWorld.preMult(v).ToHandedVector3())).ToList()); // Converting counter clockwise -> clockwise. var triangles = new List <int>(); var indexArray = collisionData.getIndices(); triangles.Capacity = indexArray.Count; for (int i = 0; i < indexArray.Count; i += 3) { triangles.Add(Convert.ToInt32(indexArray[i + 0])); triangles.Add(Convert.ToInt32(indexArray[i + 2])); triangles.Add(Convert.ToInt32(indexArray[i + 1])); } source.SetTriangles(triangles, 0, false); source.RecalculateBounds(); source.RecalculateNormals(); source.RecalculateTangents(); source = AddOrReplaceAsset(source, node, AGXUnity.IO.AssetType.CollisionMesh); mesh.SetSourceObject(source); } } else { Debug.LogWarning("Unsupported shape type: " + nativeShapeType); return(false); } var shape = node.GameObject.GetComponent <AGXUnity.Collide.Shape>(); // Is the geometry enabled? shape.gameObject.SetActive(nativeGeometry.isEnabled()); if (nativeGeometry.getMaterial() != null) { var shapeMaterial = m_tree.GetNode(nativeGeometry.getMaterial().getUuid()).Asset as ShapeMaterial; if (shapeMaterial == null) { Debug.LogWarning("Shape material from geometry: " + nativeGeometry.getName() + " isn't found in UUID database."); } shape.Material = shapeMaterial; } shape.CollisionsEnabled = nativeGeometry.getEnableCollisions(); // Groups referenced in geometry node. var groups = node.Parent.GetReferences(Node.NodeType.GroupId); if (groups.Length > 0) { var groupsComponent = shape.gameObject.GetOrCreateComponent <CollisionGroups>(); foreach (var group in groups) { if (group.Object is string) { groupsComponent.AddGroup(group.Object as string, false); } } } CreateRenderData(node); return(true); }
private void Generate(Node node) { if (node == null) { return; } // TODO: Skip if node.GameObject != null means "use Unity configuration". switch (node.Type) { case Node.NodeType.Assembly: agx.Frame frame = m_tree.GetAssembly(node.Uuid); node.GameObject = GetOrCreateGameObject(node); node.GameObject.name = FindName("", node.Type.ToString()); node.GameObject.transform.position = frame.getTranslate().ToHandedVector3(); node.GameObject.transform.rotation = frame.getRotate().ToHandedQuaternion(); node.GameObject.GetOrCreateComponent <Assembly>(); break; case Node.NodeType.RigidBody: agx.RigidBody nativeRb = m_tree.GetRigidBody(node.Uuid); node.GameObject = GetOrCreateGameObject(node); node.GameObject.name = FindName(nativeRb.getName(), node.Type.ToString()); node.GameObject.transform.position = nativeRb.getPosition().ToHandedVector3(); node.GameObject.transform.rotation = nativeRb.getRotation().ToHandedQuaternion(); node.GameObject.GetOrCreateComponent <RigidBody>().RestoreLocalDataFrom(nativeRb); break; case Node.NodeType.Geometry: // Ignoring geometries - handling Shape == Geometry. // The shapes are children to this node. break; case Node.NodeType.Shape: var nativeGeometry = m_tree.GetGeometry(node.Parent.Uuid); var nativeShape = m_tree.GetShape(node.Uuid); var nativeShapeType = (agxCollide.Shape.Type)nativeShape.getType(); node.GameObject = GetOrCreateGameObject(node); node.GameObject.name = FindName(nativeGeometry.getName() + "_" + nativeShapeType.ToString().ToLower().FirstCharToUpperCase(), node.Type.ToString()); node.GameObject.transform.position = nativeShape.getTransform().getTranslate().ToHandedVector3(); node.GameObject.transform.rotation = nativeShape.getTransform().getRotate().ToHandedQuaternion(); if (!CreateShape(node)) { GameObject.DestroyImmediate(node.GameObject); } break; case Node.NodeType.Material: var nativeMaterial = m_tree.GetMaterial(node.Uuid); node.Asset = ScriptAsset.Create <ShapeMaterial>().RestoreLocalDataFrom(nativeMaterial); node.Asset.name = FindName(nativeMaterial.getName(), node.Type.ToString()); node.Asset = AddOrReplaceAsset(node.Asset as ShapeMaterial, node, AGXUnity.IO.AssetType.ShapeMaterial); break; case Node.NodeType.ContactMaterial: var nativeContactMaterial = m_tree.GetContactMaterial(node.Uuid); var nativeFrictionModel = nativeContactMaterial.getFrictionModel(); var contactMaterial = ScriptAsset.Create <ContactMaterial>().RestoreLocalDataFrom(nativeContactMaterial); contactMaterial.name = FindName("ContactMaterial_" + nativeContactMaterial.getMaterial1().getName() + "_" + nativeContactMaterial.getMaterial2().getName(), node.Type.ToString()); var materials = node.GetReferences(Node.NodeType.Material); if (materials.Length == 0) { Debug.LogWarning("No materials referenced to ContactMaterial node."); } else if (materials.Length == 1) { contactMaterial.Material1 = contactMaterial.Material2 = materials[0].Asset as ShapeMaterial; } else if (materials.Length > 1) { contactMaterial.Material1 = materials[0].Asset as ShapeMaterial; contactMaterial.Material2 = materials[1].Asset as ShapeMaterial; if (materials.Length > 2) { Debug.LogWarning("More than two materials referenced to ContactMaterial (" + node.Asset.name + "). First two are used."); } } if (nativeFrictionModel != null) { var frictionModelAsset = ScriptAsset.Create <FrictionModel>().RestoreLocalDataFrom(nativeFrictionModel); frictionModelAsset.name = "FrictionModel_" + contactMaterial.name; contactMaterial.FrictionModel = AddOrReplaceAsset(frictionModelAsset, node, AGXUnity.IO.AssetType.FrictionModel); } node.Asset = contactMaterial = AddOrReplaceAsset(contactMaterial, node, AGXUnity.IO.AssetType.ContactMaterial); break; case Node.NodeType.Constraint: var nativeConstraint = m_tree.GetConstraint(node.Uuid); node.GameObject = GetOrCreateGameObject(node); node.GameObject.name = FindName(nativeConstraint.getName(), "AGXUnity." + Constraint.FindType(nativeConstraint)); if (!CreateConstraint(node)) { GameObject.DestroyImmediate(node.GameObject); } break; case Node.NodeType.Wire: var nativeWire = m_tree.GetWire(node.Uuid); node.GameObject = GetOrCreateGameObject(node); node.GameObject.name = FindName(nativeWire.getName(), "AGXUnity.Wire"); if (!CreateWire(node)) { GameObject.DestroyImmediate(node.GameObject); } break; case Node.NodeType.Cable: var nativeCable = m_tree.GetCable(node.Uuid); node.GameObject = GetOrCreateGameObject(node); node.GameObject.name = FindName(nativeCable.getName(), "AGXUnity.Cable"); if (!CreateCable(node)) { GameObject.DestroyImmediate(node.GameObject); } break; } foreach (var child in node.Children) { Generate(child); } }
private bool CreateRenderData(Node node, AGXUnity.Collide.Shape shape) { if (shape == null) { return(false); } var nativeShape = m_tree.GetShape(node.Uuid); var nativeRenderData = nativeShape.getRenderData(); var shapeVisual = ShapeVisual.Find(shape); if (nativeRenderData == null || !nativeRenderData.getShouldRender()) { if (shapeVisual != null) { UnityEngine.Object.DestroyImmediate(shapeVisual.gameObject); EditorUtility.SetDirty(FileInfo.PrefabInstance); } return(false); } var currentMeshes = shapeVisual == null ? new Mesh[] {} : (from proxy in shapeVisual.GetComponentsInChildren <OnSelectionProxy>() where proxy.Component == shape && proxy.GetComponent <MeshFilter>() != null && proxy.GetComponent <MeshFilter>().sharedMesh != null select proxy.GetComponent <MeshFilter>().sharedMesh).ToArray(); var currentMaterials = shapeVisual == null ? new Material[] { } : (from proxy in shapeVisual.GetComponentsInChildren <OnSelectionProxy>() where proxy.Component == shape && proxy.GetComponent <MeshRenderer>() != null && proxy.GetComponent <MeshRenderer>().sharedMaterial != null select proxy.GetComponent <MeshRenderer>().sharedMaterial).ToArray(); var nativeGeometry = m_tree.GetGeometry(node.Parent.Uuid); var toWorld = nativeGeometry.getTransform(); var toLocal = shape.transform.worldToLocalMatrix; Mesh[] meshes = MeshSplitter.Split(nativeRenderData.getVertexArray(), nativeRenderData.getIndexArray(), nativeRenderData.getTexCoordArray(), v => toLocal.MultiplyPoint3x4(toWorld.preMult(v).ToHandedVector3())).Meshes; // Initial import with currentMeshes.Length == 0 and shape mesh source // matches render data - use shape mesh sources instead. if (shape is AGXUnity.Collide.Mesh && currentMeshes.Length == 0 && meshes.Length == (shape as AGXUnity.Collide.Mesh).SourceObjects.Length) { var shapeMesh = shape as AGXUnity.Collide.Mesh; var matching = true; for (int i = 0; matching && i < meshes.Length; ++i) { matching = meshes[i].vertexCount == shapeMesh.SourceObjects[i].vertexCount; if (!matching) { continue; } var v1 = meshes[i].vertices; var v2 = shapeMesh.SourceObjects[i].vertices; for (int j = 0; matching && j < v1.Length; ++j) { matching = AGXUnity.Utils.Math.Approximately(v1[j], v2[j], 1.0E-5f); } } if (matching) { currentMeshes = new Mesh[meshes.Length]; for (int i = 0; i < meshes.Length; ++i) { shapeMesh.SourceObjects[i].SetUVs(0, meshes[i].uv.ToList()); currentMeshes[i] = meshes[i] = shapeMesh.SourceObjects[i]; } } } // No structural changes from previous read visuals. if (shapeVisual != null && currentMeshes.Length == meshes.Length && currentMaterials.Length == meshes.Length) { for (int i = 0; i < meshes.Length; ++i) { // Meshes and materials are already referenced so we don't have to // assign them again to the ShapeVisuals. FileInfo.ObjectDb.GetOrCreateAsset(currentMeshes[i], $"{shape.name}_Visual_Mesh_{i}", m => { m.Clear(); EditorUtility.CopySerialized(meshes[i], m); }); RestoreRenderMaterial(currentMaterials[i], $"{shape.name}_Visual_Material", nativeRenderData.getRenderMaterial()); EditorUtility.SetDirty(shapeVisual); } } else { if (shapeVisual != null) { UnityEngine.Object.DestroyImmediate(shapeVisual.gameObject, true); EditorUtility.SetDirty(FileInfo.PrefabInstance); shapeVisual = null; } var material = RestoreRenderMaterial(currentMaterials.Length > 0 ? currentMaterials[0] : null, $"{shape.name}_Visual_Material", nativeRenderData.getRenderMaterial()); for (int i = 0; i < meshes.Length; ++i) { meshes[i] = FileInfo.ObjectDb.GetOrCreateAsset(i < currentMeshes.Length ? currentMeshes[i] : null, $"{shape.name}_Visual_Mesh_{i}", m => { m.Clear(); EditorUtility.CopySerialized(meshes[i], m); }); } ShapeVisual.CreateRenderData(shape, meshes, material); } return(true); }
private bool CreateShape(Node node) { var nativeGeometry = m_tree.GetGeometry(node.Parent.Uuid); var nativeShape = m_tree.GetShape(node.Uuid); var nativeShapeType = (agxCollide.Shape.Type)nativeShape.getType(); if (nativeShapeType == agxCollide.Shape.Type.BOX) { node.GameObject.GetOrCreateComponent <AGXUnity.Collide.Box>().HalfExtents = nativeShape.asBox().getHalfExtents().ToVector3(); } else if (nativeShapeType == agxCollide.Shape.Type.CYLINDER) { var cylinder = node.GameObject.GetOrCreateComponent <AGXUnity.Collide.Cylinder>(); cylinder.Radius = Convert.ToSingle(nativeShape.asCylinder().getRadius()); cylinder.Height = Convert.ToSingle(nativeShape.asCylinder().getHeight()); } else if (nativeShapeType == agxCollide.Shape.Type.HOLLOW_CYLINDER) { var hollowCylinder = node.GameObject.GetOrCreateComponent <AGXUnity.Collide.HollowCylinder>(); hollowCylinder.Thickness = Convert.ToSingle(nativeShape.asHollowCylinder().getThickness()); hollowCylinder.Radius = Convert.ToSingle(nativeShape.asHollowCylinder().getOuterRadius()); hollowCylinder.Height = Convert.ToSingle(nativeShape.asHollowCylinder().getHeight()); } else if (nativeShapeType == agxCollide.Shape.Type.CONE) { var cone = node.GameObject.GetOrCreateComponent <AGXUnity.Collide.Cone>(); cone.BottomRadius = Convert.ToSingle(nativeShape.asCone().getBottomRadius()); cone.TopRadius = Convert.ToSingle(nativeShape.asCone().getTopRadius()); cone.Height = Convert.ToSingle(nativeShape.asCone().getHeight()); } else if (nativeShapeType == agxCollide.Shape.Type.HOLLOW_CONE) { var hollowCone = node.GameObject.GetOrCreateComponent <AGXUnity.Collide.HollowCone>(); hollowCone.Thickness = Convert.ToSingle(nativeShape.asHollowCone().getThickness()); hollowCone.BottomRadius = Convert.ToSingle(nativeShape.asHollowCone().getBottomOuterRadius()); hollowCone.TopRadius = Convert.ToSingle(nativeShape.asHollowCone().getTopOuterRadius()); hollowCone.Height = Convert.ToSingle(nativeShape.asHollowCone().getHeight()); } else if (nativeShapeType == agxCollide.Shape.Type.CAPSULE) { var capsule = node.GameObject.GetOrCreateComponent <AGXUnity.Collide.Capsule>(); capsule.Radius = Convert.ToSingle(nativeShape.asCapsule().getRadius()); capsule.Height = Convert.ToSingle(nativeShape.asCapsule().getHeight()); } else if (nativeShapeType == agxCollide.Shape.Type.SPHERE) { var sphere = node.GameObject.GetOrCreateComponent <AGXUnity.Collide.Sphere>(); sphere.Radius = Convert.ToSingle(nativeShape.asSphere().getRadius()); } else if (nativeShapeType == agxCollide.Shape.Type.CONVEX || nativeShapeType == agxCollide.Shape.Type.TRIMESH || nativeShapeType == agxCollide.Shape.Type.HEIGHT_FIELD) { var mesh = node.GameObject.GetOrCreateComponent <AGXUnity.Collide.Mesh>(); var collisionData = nativeShape.asMesh().getMeshData(); var nativeToWorld = nativeShape.getTransform(); var meshToLocal = mesh.transform.worldToLocalMatrix; var sourceObjects = mesh.SourceObjects; var meshes = MeshSplitter.Split(collisionData.getVertices(), collisionData.getIndices(), v => meshToLocal.MultiplyPoint3x4(nativeToWorld.preMult(v).ToHandedVector3()), UInt16.MaxValue).Meshes; // Clearing previous sources. mesh.SetSourceObject(null); for (int i = 0; i < meshes.Length; ++i) { var source = FileInfo.ObjectDb.GetOrCreateAsset(i < sourceObjects.Length ? sourceObjects[i] : null, $"Mesh_{mesh.name}{(meshes.Length > 1 ? $"_{i}" : "")}", m => { m.Clear(); EditorUtility.CopySerialized(meshes[i], m); }); mesh.AddSourceObject(source); } } else { Debug.LogWarning("Unsupported shape type: " + nativeShapeType); return(false); } var shape = node.GameObject.GetComponent <AGXUnity.Collide.Shape>(); shape.gameObject.SetActive(nativeGeometry.isEnabled()); shape.IsSensor = nativeGeometry.isSensor(); shape.Material = RestoreShapeMaterial(shape.Material, nativeGeometry.getMaterial()); shape.CollisionsEnabled = nativeGeometry.getEnableCollisions(); // Groups referenced in geometry node. var groups = node.Parent.GetReferences(Node.NodeType.GroupId); if (groups.Length > 0) { var groupsComponent = shape.gameObject.GetOrCreateComponent <CollisionGroups>(); foreach (var group in groups) { if (group.Object is string) { groupsComponent.AddGroup(group.Object as string, false); } } } CreateRenderData(node, shape); return(true); }
private void Generate(Node node) { if (node == null) { return; } switch (node.Type) { case Node.NodeType.Assembly: agx.Frame frame = m_tree.GetAssembly(node.Uuid); node.GameObject = GetOrCreateGameObject(node); node.GameObject.name = FindName("", node.Type.ToString()); node.GameObject.transform.position = frame.getTranslate().ToHandedVector3(); node.GameObject.transform.rotation = frame.getRotate().ToHandedQuaternion(); node.GameObject.GetOrCreateComponent <Assembly>(); break; case Node.NodeType.RigidBody: agx.RigidBody nativeRb = m_tree.GetRigidBody(node.Uuid); node.GameObject = GetOrCreateGameObject(node); node.GameObject.name = FindName(nativeRb.getName(), node.Type.ToString()); node.GameObject.transform.position = nativeRb.getPosition().ToHandedVector3(); node.GameObject.transform.rotation = nativeRb.getRotation().ToHandedQuaternion(); node.GameObject.GetOrCreateComponent <RigidBody>().RestoreLocalDataFrom(nativeRb); break; case Node.NodeType.Geometry: // Ignoring geometries - handling Shape == Geometry. // The shapes are children to this node. break; case Node.NodeType.Shape: var nativeGeometry = m_tree.GetGeometry(node.Parent.Uuid); var nativeShape = m_tree.GetShape(node.Uuid); var nativeShapeType = (agxCollide.Shape.Type)nativeShape.getType(); node.GameObject = GetOrCreateGameObject(node); node.GameObject.name = FindName(nativeGeometry.getName() + "_" + nativeShapeType.ToString().ToLower().FirstCharToUpperCase(), node.Type.ToString()); node.GameObject.transform.position = nativeShape.getTransform().getTranslate().ToHandedVector3(); node.GameObject.transform.rotation = nativeShape.getTransform().getRotate().ToHandedQuaternion(); if (!CreateShape(node)) { GameObject.DestroyImmediate(node.GameObject); } break; case Node.NodeType.Material: // Ignoring materials - the referenced materials should have been restored // by now using RestoreShapeMaterial. break; case Node.NodeType.ContactMaterial: var materialNodes = node.GetReferences(Node.NodeType.Material); Func <string> contactMaterialMaterialNames = () => { return(m_tree.GetMaterial(materialNodes[0].Uuid).getName() + " <-> " + m_tree.GetMaterial(materialNodes[1].Uuid).getName()); }; if (materialNodes.Length == 0) { Debug.LogWarning("No materials referenced to ContactMaterial node - ignoring contact material."); break; } else if (materialNodes.Length > 2) { Debug.LogWarning("More than two materials referenced to contact material - first two will be used: " + contactMaterialMaterialNames()); } var materials = new ShapeMaterial[2] { materialNodes[0].Asset as ShapeMaterial, materialNodes.Length > 1 ? materialNodes[1].Asset as ShapeMaterial : materialNodes[0].Asset as ShapeMaterial }; var nativeContactMaterial = m_tree.GetContactMaterial(node.Uuid); var nativeFrictionModel = nativeContactMaterial.getFrictionModel(); if (materials[0] == null || materials[1] == null) { Debug.LogWarning($"Unreferenced ShapeMaterial(s) in ContactMaterial: {contactMaterialMaterialNames()} - ignoring contact material."); break; } Predicate <ContactMaterial> materialsMatcher = cm => (cm.Material1 == materials[0] && cm.Material2 == materials[1]) || (cm.Material2 == materials[0] && cm.Material1 == materials[1]); var contactMaterial = FileInfo.ObjectDb.GetOrCreateAsset(materialsMatcher, FindName($"ContactMaterial_{materials[ 0 ].name}_{materials[ 1 ].name}", node.Type.ToString()), cm => { cm.Material1 = materials[0]; cm.Material2 = materials[1]; cm.RestoreLocalDataFrom(nativeContactMaterial); }); if (nativeFrictionModel != null) { contactMaterial.FrictionModel = FileInfo.ObjectDb.GetOrCreateAsset(contactMaterial.FrictionModel, $"FrictionModel_{contactMaterial.name}", fm => fm.RestoreLocalDataFrom(nativeFrictionModel)); } node.Asset = contactMaterial; break; case Node.NodeType.Constraint: var nativeConstraint = m_tree.GetConstraint(node.Uuid); node.GameObject = GetOrCreateGameObject(node); node.GameObject.name = FindName(nativeConstraint.getName(), "AGXUnity." + Constraint.FindType(nativeConstraint)); if (!CreateConstraint(node)) { GameObject.DestroyImmediate(node.GameObject); } break; case Node.NodeType.Wire: var nativeWire = m_tree.GetWire(node.Uuid); node.GameObject = GetOrCreateGameObject(node); node.GameObject.name = FindName(nativeWire.getName(), "AGXUnity.Wire"); if (!CreateWire(node)) { GameObject.DestroyImmediate(node.GameObject); } break; case Node.NodeType.Cable: var nativeCable = m_tree.GetCable(node.Uuid); node.GameObject = GetOrCreateGameObject(node); node.GameObject.name = FindName(nativeCable.getName(), "AGXUnity.Cable"); if (!CreateCable(node)) { GameObject.DestroyImmediate(node.GameObject); } break; case Node.NodeType.ObserverFrame: var nativeObserverFrame = m_tree.GetObserverFrame(node.Uuid); node.GameObject = GetOrCreateGameObject(node); node.GameObject.name = FindName(nativeObserverFrame.getName(), "AGXUnity.ObserverFrame"); var rbNode = node.GetReferences(Node.NodeType.RigidBody).FirstOrDefault(); node.GameObject.GetOrCreateComponent <ObserverFrame>().RestoreLocalDataFrom(nativeObserverFrame, rbNode != null ? rbNode.GameObject : null); break; } foreach (var child in node.Children) { Generate(child); } }