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(); node.GameObject.GetOrCreateComponent <CableRenderer>(); 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 = FileInfo.AddOrUpdateExistingAsset(properties, 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 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 = FileInfo.AddOrUpdateExistingAsset(material, AGXUnity.IO.AssetType.Material); foreach (var mesh in meshes) { FileInfo.AddOrUpdateExistingAsset(mesh, 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 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 = FileInfo.AddOrUpdateExistingAsset(node.Asset as ShapeMaterial, 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 = frictionModelAsset = FileInfo.AddOrUpdateExistingAsset(frictionModelAsset, AGXUnity.IO.AssetType.FrictionModel); } node.Asset = contactMaterial = FileInfo.AddOrUpdateExistingAsset(contactMaterial, 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 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(FileInfo.AddOrUpdateExistingAsset(subMeshes[i], 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 = FileInfo.AddOrUpdateExistingAsset(source, AGXUnity.IO.AssetType.CollisionMesh); mesh.SetSourceObject(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(); 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); }
/// <summary> /// Trying to generate the objects given the simulation tree. /// Throws if something goes wrong. /// </summary> public void TryGenerate() { FileInfo.GetOrCreateDataDirectory(); // Adding one for disabled collisions. int numSubProgresses = m_tree.Roots.Length + 1; using (var subProgress = m_progressBar.Progress("Generating: " + FileInfo.NameWithExtension, numSubProgresses)) { FileInfo.PrefabInstance.transform.position = Vector3.zero; FileInfo.PrefabInstance.transform.rotation = Quaternion.identity; var fileData = FileInfo.PrefabInstance.GetOrCreateComponent <AGXUnity.IO.RestoredAGXFile>(); fileData.DataDirectoryId = FileInfo.DataDirectoryId; fileData.SolverSettings = ScriptAsset.Create <SolverSettings>().RestoreLocalDataFrom(Simulation); fileData.SolverSettings.name = FindName("SolverSettings_" + FileInfo.Name, "SolverSettings"); fileData.SolverSettings = FileInfo.AddOrUpdateExistingAsset(fileData.SolverSettings, AGXUnity.IO.AssetType.Unknown); foreach (var root in m_tree.Roots) { subProgress.Tick(root.Name == string.Empty ? root.Type.ToString() : root.Name); Generate(root); subProgress.Tack(); } subProgress.Tick("Disabled collisions"); var disabledCollisionsState = Simulation.getSpace().findDisabledCollisionsState(); foreach (var namePair in disabledCollisionsState.getDisabledNames()) { fileData.AddDisabledPair(namePair.first, namePair.second); } foreach (var idPair in disabledCollisionsState.getDisabledIds()) { fileData.AddDisabledPair(idPair.first.ToString(), idPair.second.ToString()); } foreach (var geometryPair in disabledCollisionsState.getDisabledGeometyPairs()) { if (!Tree.IsValid(geometryPair.first) || !Tree.IsValid(geometryPair.second)) { continue; } var geometry1Node = m_tree.GetNode(geometryPair.first.getUuid()); var geometry2Node = m_tree.GetNode(geometryPair.second.getUuid()); if (geometry1Node == null || geometry2Node == null) { Debug.LogWarning("Unreferenced geometry in disabled collisions pair."); continue; } var geometry1Id = geometry2Node.Uuid.str(); foreach (var shapeNode in geometry1Node.GetChildren(Node.NodeType.Shape)) { shapeNode.GameObject.GetOrCreateComponent <CollisionGroups>().AddGroup(geometry1Id, false); } var geometry2Id = geometry1Node.Uuid.str(); foreach (var shapeNode in geometry2Node.GetChildren(Node.NodeType.Shape)) { shapeNode.GameObject.GetOrCreateComponent <CollisionGroups>().AddGroup(geometry2Id, false); } fileData.AddDisabledPair(geometry1Id, geometry2Id); } subProgress.Tack(); } }