/// <summary> /// Peek at a temporary native instance or the current (if initialized). /// </summary> /// <param name="callback">Callback with temporary or already initialized native instance. Callback signature ( nativeRb, isTemporary ).</param> /// <remarks> /// Always assume the native instance to be temporary. It's never safe to cache an instance to the native object. /// </remarks> public void PeekTemporaryNativeOrGetNative(Action <agx.RigidBody, bool> callback) { if (callback == null) { return; } if (m_rb != null) { callback(m_rb, false); } else { Shape[] shapes = GetComponentsInChildren <Shape>(); using (agx.RigidBody rb = new agx.RigidBody()) { foreach (Shape shape in shapes) { agxCollide.Shape nativeShape = shape.CreateTemporaryNative(); if (nativeShape != null) { agxCollide.Geometry geometry = new agxCollide.Geometry(nativeShape); geometry.setEnable(shape.IsEnabled); if (shape.Material != null) { geometry.setMaterial(shape.Material.CreateTemporaryNative()); } rb.add(geometry, shape.GetNativeRigidBodyOffset(this)); } } // For center of mass position/rotation to be correct we have to // synchronize the native transform given current game object transform. SyncNativeTransform(rb); callback(rb, true); // Hitting "Update" (mass or inertia in the Inspector) several times // will crash agx if we don't remove the geometries and shapes. while (rb.getGeometries().Count > 0) { agxCollide.Geometry geometry = rb.getGeometries()[0].get(); if (geometry.getShapes().Count > 0) { geometry.remove(geometry.getShapes()[0].get()); } rb.remove(geometry); } } } }
/// <summary> /// Merges all source objects to one mesh and creates a native trimesh. /// </summary> /// <param name="meshes">Source meshes.</param> /// <returns>Native trimesh.</returns> private agxCollide.Geometry Create(UnityEngine.Mesh[] meshes) { var geometry = new agxCollide.Geometry(); if (m_precomputedCollisionMeshes.Count > 0) { // The vertices are assumed to be stored in local coordinates of the // given transform. For the scale to be correct w var toWorld = transform.localToWorldMatrix; Func <Vector3, Vector3> transformer = v => { return(transform.InverseTransformDirection(toWorld * v.ToLeftHanded())); }; var mode = Options != null ? Options.Mode : CollisionMeshOptions.MeshMode.Trimesh; for (int i = 0; i < m_precomputedCollisionMeshes.Count; ++i) { var collisionMesh = m_precomputedCollisionMeshes[i]; if (collisionMesh == null) { Debug.LogWarning($"AGXUnity.Collide.Mesh: Null precomputed collision mesh at index {i}.", this); continue; } var shape = collisionMesh.CreateShape(transformer, mode); if (shape == null) { Debug.LogWarning($"AGXUnity.Collide.Mesh: Precomputed collision mesh at index {i} resulted in an invalid shape.", this); continue; } geometry.add(shape, GetNativeGeometryOffset()); } } else { if (m_precomputedCollisionMeshes.Count > 0) { Debug.LogWarning("AGXUnity.Mesh: Failed to create shapes from precomputed data - using Trimesh as fallback.", this); } var merger = MeshMerger.Merge(transform, meshes); geometry.add(new agxCollide.Trimesh(merger.Vertices, merger.Indices, "AGXUnity.Mesh: Trimesh"), GetNativeGeometryOffset()); } if (geometry.getShapes().Count == 0) { geometry.Dispose(); geometry = null; } return(geometry); }
/// <summary> /// Add shape to a rigid body instance. /// NOTE: This method is used by the RigidBody object. /// </summary> /// <param name="rb"></param> public void SetRigidBody(RigidBody rb) { if (m_geometry == null || m_geometry.getShapes().Count == 0 || m_geometry.getRigidBody() != null) { return; } // Search in our game object for rigid body and remove this? if (!rb.gameObject.HasChild(gameObject)) { throw new Exception("RigidBody not parent to Shape."); } m_geometry.setEnable(IsEnabled); rb.Native.add(m_geometry, GetNativeRigidBodyOffset(rb)); }
/// <summary> /// Add shape to a rigid body instance. /// NOTE: This method is used by the RigidBody object. /// </summary> /// <param name="rb"></param> public void SetRigidBody(RigidBody rb) { if (m_geometry == null || m_geometry.getShapes().Count == 0 || m_geometry.getRigidBody() != null) { return; } // Search in our game object for rigid body and remove this? if (!rb.gameObject.HasChild(gameObject)) { throw new Exception("RigidBody not parent to Shape."); } m_geometry.setEnable(IsEnabled); rb.Native.add(m_geometry, GetNativeRigidBodyOffset(rb)); // Removing us from synchronization the transform since // we're implicitly updated from the synchronization of // the body. Simulation.Instance.StepCallbacks.PostSynchronizeTransforms -= OnPostSynchronizeTransformsCallback; }
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() }); } }