250 lines
9.9 KiB
C#
250 lines
9.9 KiB
C#
/*=========================================================================
|
|
|
|
Library: iMSTK-Unity
|
|
|
|
Copyright (c) Kitware, Inc.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0.txt
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
|
|
=========================================================================*/
|
|
|
|
using Unity.Profiling;
|
|
using UnityEngine;
|
|
|
|
namespace ImstkUnity
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
/// Used for models with deformable vertices. That is the vertices are changing
|
|
/// per update of the model in global configuration.
|
|
/// </summary>
|
|
public abstract class DeformableModel : DynamicalModel
|
|
{
|
|
static readonly ProfilerMarker s_UpdatePerfMarker = new ProfilerMarker(ProfilerCategory.Physics, "Imstk.DeformableUpdate");
|
|
TimingBuffer _updateTimes = new TimingBuffer(100);
|
|
|
|
// These filters can accept either imstk or unity geometry input
|
|
// and output imstk geometry
|
|
public GeometryFilter visualGeomFilter = null;
|
|
public GeometryFilter physicsGeomFilter = null;
|
|
public GeometryFilter collisionGeomFilter = null;
|
|
|
|
public bool cleanVisualMesh;
|
|
|
|
public TimingBuffer UpdateTimes {
|
|
get { return _updateTimes; }
|
|
}
|
|
|
|
protected override void OnImstkInit()
|
|
{
|
|
if (imstkObject != null) return;
|
|
// Get dependencies
|
|
meshFilter = visualGeomFilter.gameObject.GetComponentFatal<MeshFilter>();
|
|
|
|
if (meshFilter.mesh == null)
|
|
{
|
|
meshFilter.mesh = new Mesh();
|
|
}
|
|
// Make sure mesh filter is read/writable
|
|
meshFilter.mesh.MarkDynamic();
|
|
if (!meshFilter.mesh.isReadable)
|
|
{
|
|
Debug.LogError(gameObject.name + "'s MeshFilter Mesh must be readable (check the meshes import settings)");
|
|
return;
|
|
}
|
|
|
|
imstkObject = InitObject();
|
|
|
|
// TODO move to simulation manager
|
|
SimulationManager.sceneManager.getActiveScene().addSceneObject(imstkObject);
|
|
InitGeometry();
|
|
InitGeometryMaps();
|
|
ProcessBoundaryConditions(gameObject.GetComponents<BoundaryCondition>());
|
|
Configure();
|
|
}
|
|
|
|
protected override void InitGeometry()
|
|
{
|
|
// Copy all the geometries over to imstk, set the transform and
|
|
// apply later. (to avoid applying transform twice *since two
|
|
// geometries could point to the same one*)
|
|
|
|
Imstk.Geometry visualGeom = null;
|
|
// Setup the visual geometry
|
|
if (visualGeomFilter != null)
|
|
{
|
|
visualGeom = GetVisualGeometry();
|
|
visualGeomFilter.MoveToGlobalSpace();
|
|
imstkObject.setVisualGeometry(visualGeom);
|
|
}
|
|
|
|
// Visual geometry is Unity this also means it's either a surface or a line mesh
|
|
// For either we do want to clean up the mesh.
|
|
// As the indices not going to match after cleanup a map from the (cleaned) physics mesh
|
|
// to the visual mesh needs to be added as well
|
|
Imstk.Geometry physicsGeom = null;
|
|
Imstk.PointwiseMap physicsToUnityMeshMap = null;
|
|
if (visualGeomFilter == physicsGeomFilter && cleanVisualMesh)
|
|
{
|
|
var visualMesh = Imstk.Utils.CastTo<Imstk.SurfaceMesh>(visualGeom);
|
|
Debug.Assert(visualMesh != null);
|
|
|
|
Debug.Log("Cleaning Mesh");
|
|
Debug.Log("Visual Mesh " + visualMesh.getNumVertices() + " vertices");
|
|
|
|
var cleaner = new Imstk.CleanMesh();
|
|
cleaner.setInputMesh(visualMesh);
|
|
cleaner.setTolerance(0.001);
|
|
cleaner.update();
|
|
var physicsMesh = cleaner.getOutputMesh();
|
|
physicsGeom = physicsMesh;
|
|
Debug.Log("Physics Mesh " + physicsMesh.getNumVertices() + " vertices");
|
|
|
|
|
|
physicsToUnityMeshMap = new Imstk.PointwiseMap(physicsGeom, visualGeom);
|
|
// Tolerance needed to avoid issues with double/float conversions
|
|
physicsToUnityMeshMap.setTolerance(1e-4);
|
|
physicsToUnityMeshMap.compute();
|
|
// TODO Should warn the user if the map doesn't actually map any points
|
|
|
|
(imstkObject as Imstk.DynamicObject).setPhysicsGeometry(physicsGeom);
|
|
(imstkObject as Imstk.DynamicObject).getDynamicalModel().setModelGeometry(physicsGeom);
|
|
(imstkObject as Imstk.DynamicObject).setPhysicsToVisualMap(physicsToUnityMeshMap);
|
|
}
|
|
else if (physicsGeomFilter != null)
|
|
{
|
|
physicsGeom = GetPhysicsGeometry();
|
|
physicsGeomFilter.MoveToGlobalSpace();
|
|
(imstkObject as Imstk.DynamicObject).setPhysicsGeometry(physicsGeom);
|
|
(imstkObject as Imstk.DynamicObject).getDynamicalModel().setModelGeometry(physicsGeom);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("No physics geometry provided to DynamicalModel on object " + gameObject.name);
|
|
}
|
|
|
|
|
|
if (collisionGeomFilter != null)
|
|
{
|
|
if (visualGeomFilter == collisionGeomFilter && visualGeomFilter == physicsGeomFilter)
|
|
{
|
|
imstkObject.setCollidingGeometry(physicsGeom);
|
|
}
|
|
else
|
|
{
|
|
Imstk.Geometry colGeom = GetCollidingGeometry();
|
|
collisionGeomFilter.MoveToGlobalSpace();
|
|
imstkObject.setCollidingGeometry(colGeom);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Debug.LogError("No collision geometry provided to DynamicalModel on object " + gameObject.name);
|
|
}
|
|
}
|
|
|
|
protected void InitGeometryMaps()
|
|
{
|
|
// Setup any geometry maps on the object
|
|
// \todo: Generalize geometry maps in imstk, currently
|
|
// well test geometry types to figure out maps
|
|
GeometryMap[] geomMaps = gameObject.GetComponents<GeometryMap>();
|
|
|
|
// \todo: Currently imstk only supports physicstovisual and physicstocollision
|
|
// this needs to be generalized. For now we will only support two maps. There are
|
|
// some other minute but tricky details to be worked out here.
|
|
for (int i = 0; i < geomMaps.Length; i++)
|
|
{
|
|
GeometryMap map = geomMaps[i];
|
|
// Test if map contains physics or visual
|
|
if (map.parentGeom == physicsGeomFilter &&
|
|
map.childGeom == collisionGeomFilter)
|
|
{
|
|
Imstk.DynamicObject dynObj = imstkObject as Imstk.DynamicObject;
|
|
Imstk.GeometryMap geomMap = map.GetMap();
|
|
if (geomMap != null)
|
|
{
|
|
dynObj.setPhysicsToCollidingMap(geomMap);
|
|
Debug.Log("Set up Physics to Collision Map");
|
|
geomMap.compute();
|
|
}
|
|
}
|
|
else if (map.parentGeom == physicsGeomFilter &&
|
|
map.childGeom == visualGeomFilter)
|
|
{
|
|
Imstk.DynamicObject dynObj = imstkObject as Imstk.DynamicObject;
|
|
Imstk.GeometryMap geomMap = map.GetMap();
|
|
if (geomMap != null)
|
|
{
|
|
dynObj.setPhysicsToVisualMap(geomMap);
|
|
Debug.Log("Set up Physics to Visual Map");
|
|
geomMap.compute();
|
|
}
|
|
}
|
|
else if (map.parentGeom == collisionGeomFilter &&
|
|
map.childGeom == visualGeomFilter)
|
|
{
|
|
Imstk.GeometryMap geomMap = map.GetMap();
|
|
if (geomMap != null)
|
|
{
|
|
imstkObject.setCollidingToVisualMap(geomMap);
|
|
Debug.Log("Set up Physics to Visual Map");
|
|
geomMap.compute();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Visual update of the geometry (only needs to call before render)
|
|
/// </summary>
|
|
public void Update()
|
|
{
|
|
if (SimulationManager.sceneManager == null)
|
|
{
|
|
Debug.LogWarning("Failed to update dynamical model on " + gameObject.name + " no sceneManager from the SimulationManager");
|
|
return;
|
|
}
|
|
|
|
s_UpdatePerfMarker.Begin();
|
|
_updateTimes.Begin();
|
|
|
|
Imstk.PointSet visualGeom = Imstk.Utils.CastTo<Imstk.PointSet>(imstkObject.getVisualGeometry());
|
|
meshFilter.mesh.vertices = MathUtil.ToVector3Array(visualGeom.getVertexPositions());
|
|
|
|
if (meshFilter.mesh.GetTopology(0) == MeshTopology.Triangles ||
|
|
meshFilter.mesh.GetTopology(0) == MeshTopology.Quads)
|
|
{
|
|
meshFilter.mesh.RecalculateNormals();
|
|
}
|
|
meshFilter.mesh.RecalculateBounds();
|
|
|
|
_updateTimes.End();
|
|
s_UpdatePerfMarker.End();
|
|
}
|
|
|
|
public override Imstk.Geometry GetVisualGeometry()
|
|
{
|
|
return visualGeomFilter.GetOutputGeometry();
|
|
}
|
|
public override Imstk.Geometry GetPhysicsGeometry()
|
|
{
|
|
return physicsGeomFilter.GetOutputGeometry();
|
|
}
|
|
public override Imstk.Geometry GetCollidingGeometry()
|
|
{
|
|
return collisionGeomFilter.GetOutputGeometry();
|
|
}
|
|
}
|
|
} |