Initial Commit
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
[AddComponentMenu("iMSTK/BoundaryCondition")]
|
||||
/// <summary>
|
||||
/// Use this behavior to mark vertices on a deformable object as `fixed`.
|
||||
/// </summary>
|
||||
/// This means they won't move but are still part of the overall system.
|
||||
/// In general this will mean that the object will be attached to the points
|
||||
/// selected. As the shape assigned can be any mesh this is an easy way to fix
|
||||
/// an object in space. To indicate which points should be you can use any unity
|
||||
/// Boundary condition points are considered to have infinite mass, this may cause
|
||||
/// issues with collision response, prefer the "Constraint" behaviors over this one.
|
||||
public class BoundaryCondition : MonoBehaviour
|
||||
{
|
||||
public GameObject bcObj = null;
|
||||
public bool hideMesh = true;
|
||||
void Start()
|
||||
{
|
||||
var renderer = bcObj.GetComponent<MeshRenderer>();
|
||||
if (renderer != null && hideMesh)
|
||||
{
|
||||
renderer.enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bf8aea0333eb6ef45a80749e21dc3e65
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,289 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
[RequireComponent(typeof(MeshFilter))]
|
||||
[RequireComponent(typeof(MeshRenderer))]
|
||||
/// <summary>
|
||||
/// This component represents connective tissue as a multitude of strands between
|
||||
/// opposing surfaces.
|
||||
/// </summary>
|
||||
/// Given two opposing geometries strands will be generated with
|
||||
/// configurable parameters. The generated object is physical and can be interacted
|
||||
/// with. The connective tissue will consist of multiple "strands" each going from
|
||||
/// one of the reference objects to the other. Each strand will be made up of the give
|
||||
/// number of segments. The amount of strands is roughly NumberOfFaces(ObjectA) * strandsPerFace
|
||||
/// Note that increasing the density and/or the number of segments per strand will also
|
||||
/// increase the computational load to simulation this object.
|
||||
public class ConnectiveTissue : DynamicalModel
|
||||
{
|
||||
/// <value>objectA and deformable are the objects that delimit the connective tissue</value>
|
||||
public Deformable objectA;
|
||||
public Deformable objectB;
|
||||
|
||||
/// <value>
|
||||
/// <c>maxDistance</c> represents the maximum distance between A and B where conn
|
||||
/// connective tissue will be generated
|
||||
/// </value>
|
||||
public double maxDistance = 10;
|
||||
|
||||
/// <value>
|
||||
/// <c>strandsPerFace</c> indicates the amount of strands total number will be roughly
|
||||
/// NumberOfFaces(ObjectA) * strandsPerFace
|
||||
/// </value>
|
||||
public double strandsPerFace = 2.0;
|
||||
|
||||
/// <value>
|
||||
/// <c>segmentsPerStrand</c> indicates how many subdivisions each strand has
|
||||
/// </value>
|
||||
public int segmentsPerStrand = 2;
|
||||
|
||||
/// <value>
|
||||
/// <c>distanceStiffness</c> how much (or little) give the connective tissue has (0-infinity)
|
||||
/// </value>
|
||||
public double distanceStiffness = 10;
|
||||
|
||||
public double uniformMassValue = 0.1;
|
||||
|
||||
public double viscousDampingCoeff = 0.01;
|
||||
|
||||
private Mesh _mesh;
|
||||
private MeshFilter _meshFilter;
|
||||
private MeshRenderer _meshRenderer;
|
||||
|
||||
private Imstk.PbdObject _connectiveTissue;
|
||||
private bool _needUV = true;
|
||||
|
||||
private Vector3[] _normals;
|
||||
private Vector3[] _vertices;
|
||||
private Vector4[] _tangents;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private Imstk.LineMesh _editorCollisionMesh;
|
||||
#endif
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_meshFilter = GetComponent<MeshFilter>();
|
||||
_meshRenderer = GetComponent<MeshRenderer>();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
|
||||
if (objectA == null || objectB == null)
|
||||
{
|
||||
Debug.LogError("Connective Tissue needs two objects to span");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnImstkInit()
|
||||
{
|
||||
if (_connectiveTissue != null) return;
|
||||
|
||||
objectA.ImstkInit();
|
||||
objectB.ImstkInit();
|
||||
|
||||
var aPbdObject = objectA.GetDynamicObject() as Imstk.PbdObject;
|
||||
var bPbdObject = objectB.GetDynamicObject() as Imstk.PbdObject;
|
||||
|
||||
// HS 20230201 TODO can't pass mass and distStiffness as we don't have proximitySelector wrapped
|
||||
_connectiveTissue = Imstk.Utils.makeConnectiveTissue(aPbdObject, bPbdObject, SimulationManager.pbdModel,
|
||||
maxDistance, strandsPerFace, segmentsPerStrand);
|
||||
|
||||
// Superclass object
|
||||
imstkObject = _connectiveTissue;
|
||||
|
||||
var visualGeometry = Imstk.Utils.CastTo<Imstk.PointSet>(_connectiveTissue.getPhysicsGeometry());
|
||||
_mesh = new Mesh();
|
||||
_mesh.name = "Connective Tissue Mesh (Imstk)";
|
||||
_mesh.MarkDynamic();
|
||||
GeomUtil.CopyMesh(visualGeometry.ToMesh(), _mesh);
|
||||
_meshFilter.mesh = _mesh;
|
||||
|
||||
var config = SimulationManager.pbdModel.getConfig();
|
||||
config.enableConstraint(Imstk.PbdModelConfig.ConstraintGenType.Distance, distanceStiffness,
|
||||
_connectiveTissue.getPbdBody().bodyHandle);
|
||||
config.m_linearDampingCoeff = viscousDampingCoeff;
|
||||
//_connectiveTissue.getPbdBody().uniformMassValue = uniformMassValue;
|
||||
|
||||
SimulationManager.pbdModel.configure(config);
|
||||
|
||||
// TODO refactor to move to simulation _manager
|
||||
SimulationManager.sceneManager.getActiveScene().addSceneObject(GetSceneObject());
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
var geometry = Imstk.Utils.CastTo<Imstk.LineMesh>(_connectiveTissue.getPhysicsGeometry());
|
||||
|
||||
_vertices = MathUtil.ToVector3Array(geometry.getVertexPositions());
|
||||
|
||||
_mesh.vertices = _vertices;
|
||||
if (_mesh.vertexCount > 0 && _needUV)
|
||||
{
|
||||
GenerateUVAndNormals(_mesh);
|
||||
}
|
||||
|
||||
if (dynamicGeometry)
|
||||
{
|
||||
int[] indices = MathUtil.ToIntArray(geometry.getLinesIndices());
|
||||
_mesh.SetIndices(indices, MeshTopology.Lines, 0);
|
||||
}
|
||||
|
||||
_mesh.RecalculateBounds();
|
||||
UpdateNormals(_mesh);
|
||||
_mesh.MarkModified();
|
||||
}
|
||||
|
||||
public Imstk.SceneObject GetSceneObject()
|
||||
{
|
||||
return Imstk.Utils.CastTo<Imstk.SceneObject>(_connectiveTissue);
|
||||
}
|
||||
|
||||
|
||||
private void GenerateUVAndNormals(Mesh mesh)
|
||||
{
|
||||
var vertices = mesh.vertices;
|
||||
var uvs = new Vector2[vertices.Length];
|
||||
_normals = new Vector3[vertices.Length];
|
||||
_tangents = new Vector4[vertices.Length];
|
||||
|
||||
int pointsPerStrand = segmentsPerStrand + 1;
|
||||
for (int strand = 0; strand < mesh.vertices.Length / pointsPerStrand; ++strand)
|
||||
{
|
||||
float rand = Random.Range(0.1f, 0.9f);
|
||||
for (int i = 0; i < pointsPerStrand; ++i)
|
||||
{
|
||||
Vector3 dir;
|
||||
var index = strand * pointsPerStrand + i;
|
||||
if (i < pointsPerStrand - 1)
|
||||
{
|
||||
dir = vertices[index + 1] - vertices[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
dir = vertices[index] - vertices[index - 1];
|
||||
}
|
||||
|
||||
uvs[index] = new Vector2(rand, (float)i / (float)pointsPerStrand);
|
||||
|
||||
// For now just connect through the origin
|
||||
_normals[index] = vertices[index].normalized;
|
||||
|
||||
// Just a guess for now
|
||||
Vector3 tangent = Vector3.Cross(_normals[index], dir).normalized;
|
||||
_tangents[index] = new Vector4(tangent.x, tangent.y, tangent.z, -1);
|
||||
}
|
||||
}
|
||||
|
||||
mesh.SetUVs(0, uvs);
|
||||
mesh.SetNormals(_normals);
|
||||
mesh.SetTangents(_tangents);
|
||||
_needUV = false;
|
||||
}
|
||||
|
||||
private void UpdateNormals(Mesh mesh)
|
||||
{
|
||||
int pointsPerStrand = segmentsPerStrand + 1;
|
||||
|
||||
Vector3 dir;
|
||||
Vector4 tangent;
|
||||
for (int strand = 0; strand < _vertices.Length / pointsPerStrand; ++strand)
|
||||
{
|
||||
for (int i = 0; i < pointsPerStrand; ++i)
|
||||
{
|
||||
|
||||
var index = strand * pointsPerStrand + i;
|
||||
if (i < pointsPerStrand - 1)
|
||||
{
|
||||
dir = _vertices[index + 1] - _vertices[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
dir = _vertices[index] - _vertices[index - 1];
|
||||
}
|
||||
|
||||
_normals[index] = _vertices[index].normalized;
|
||||
|
||||
// Just a guess for now
|
||||
tangent = Vector3.Cross(_normals[index], dir).normalized;
|
||||
_tangents[index].x = tangent.x;
|
||||
_tangents[index].y = tangent.y;
|
||||
_tangents[index].z = tangent.x;
|
||||
}
|
||||
}
|
||||
mesh.SetNormals(_normals);
|
||||
mesh.SetTangents(_tangents);
|
||||
}
|
||||
|
||||
protected override Imstk.CollidingObject InitObject()
|
||||
{
|
||||
return imstkObject;
|
||||
}
|
||||
|
||||
protected override void Configure()
|
||||
{
|
||||
// Don't need this for connective tissue
|
||||
}
|
||||
|
||||
protected override void InitGeometry()
|
||||
{
|
||||
// Don't need this for connective tissue
|
||||
}
|
||||
|
||||
public override Imstk.Geometry GetVisualGeometry()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
public override Imstk.Geometry GetPhysicsGeometry()
|
||||
{
|
||||
return _connectiveTissue.getPhysicsGeometry();
|
||||
}
|
||||
public override Imstk.Geometry GetCollidingGeometry()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// Editor only, provide the _editorCollisionMesh for
|
||||
// the purpose of detecting the collision type
|
||||
if (_connectiveTissue != null)
|
||||
{
|
||||
return _connectiveTissue.getCollidingGeometry();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_editorCollisionMesh == null)
|
||||
{
|
||||
_editorCollisionMesh = new Imstk.LineMesh();
|
||||
}
|
||||
return _editorCollisionMesh;
|
||||
}
|
||||
#else
|
||||
if (_connectiveTissue != null)
|
||||
{
|
||||
return _connectiveTissue.getCollidingGeometry();
|
||||
}
|
||||
else return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bff9fbc647133d24f81f32d47c01d429
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,133 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
/// <summary>
|
||||
/// This will set up a set of distance constraints between two deformable objects.
|
||||
/// </summary>
|
||||
/// The constraints will be limited to the area encompassed by the assigned mesh
|
||||
/// constraints will be generated for _all_ pairs of points whose distance is smaller than
|
||||
/// or equal the cutoff distance.The length of the constraint will be set to
|
||||
/// the original distance * restLength. Use this if you want to attach a deformable
|
||||
/// to another deformable. E.g. a vessel to another organ.
|
||||
public class ConstrainDeformables : ImstkBehaviour
|
||||
{
|
||||
public Deformable objectA = null;
|
||||
public Deformable objectB = null;
|
||||
|
||||
[Tooltip("Area that is searched for points")]
|
||||
public MeshFilter constrainedArea = null;
|
||||
[Tooltip("Hides the constraining mesh")]
|
||||
public bool hideMesh = true;
|
||||
|
||||
[Tooltip("Ignore points that are farther apart than `cutoff`")]
|
||||
public float cutoff = 0.01f;
|
||||
|
||||
[Tooltip("Affects the resting length of the constraint")]
|
||||
[Min(0)]
|
||||
public float restLengthFactor = 0.0f;
|
||||
|
||||
[Tooltip("How stiff this constraint should be")]
|
||||
[Min(0)]
|
||||
public float stiffness = 1.0e5f;
|
||||
|
||||
void Start()
|
||||
{
|
||||
var renderer = constrainedArea.gameObject.GetComponent<MeshRenderer>();
|
||||
if (renderer != null && hideMesh)
|
||||
{
|
||||
renderer.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Needs to run after objectA and deformable have been initialized
|
||||
|
||||
protected override void OnImstkStart()
|
||||
{
|
||||
if (!isActiveAndEnabled) return;
|
||||
if (objectA == null || !objectA.isActiveAndEnabled || objectB == null || !objectB.isActiveAndEnabled ||
|
||||
constrainedArea == null)
|
||||
{
|
||||
enabled = false;
|
||||
Debug.Log(name + " disabled due to missing or disabled dependency.");
|
||||
return;
|
||||
}
|
||||
|
||||
ImstkMesh bcGeometry = constrainedArea.sharedMesh.ToImstkMesh(constrainedArea.transform.localToWorldMatrix);
|
||||
Imstk.SurfaceMesh bcImstkGeometry = bcGeometry.ToImstkGeometry() as Imstk.SurfaceMesh;
|
||||
|
||||
Imstk.Geometry geomA = (objectA.GetDynamicObject() as Imstk.PbdObject).getPhysicsGeometry();
|
||||
var pointsA = GeomUtil.PointsInside(bcImstkGeometry, Imstk.Utils.CastTo<Imstk.PointSet>(geomA));
|
||||
|
||||
Imstk.Geometry geomB = (objectB.GetDynamicObject() as Imstk.PbdObject).getPhysicsGeometry();
|
||||
var pointsB = GeomUtil.PointsInside(bcImstkGeometry, Imstk.Utils.CastTo<Imstk.PointSet>(geomB));
|
||||
|
||||
if (pointsA.Count == 0 || pointsB.Count == 0)
|
||||
{
|
||||
Debug.LogWarning("No points in constraint area " + gameObject.name);
|
||||
}
|
||||
|
||||
ConstrainPoints(objectA, pointsA, objectB, pointsB);
|
||||
}
|
||||
|
||||
private void ConstrainPoints(Deformable objectA, List<uint> pointsA, Deformable objectB, List<uint> pointsB)
|
||||
{
|
||||
int count = 0;
|
||||
// NOTE HS - 20230215 need to investigate type conversion for result of .getVertexPosition() etc
|
||||
// returns a wrapped swig type rather than Vec3d for example
|
||||
Imstk.Geometry geomA = (objectA.GetDynamicObject() as Imstk.PbdObject).getPhysicsGeometry();
|
||||
var pointSetA = Imstk.Utils.CastTo<Imstk.PointSet>(geomA);
|
||||
var verticesA = MathUtil.ToVector3Array(pointSetA.getVertexPositions());
|
||||
|
||||
|
||||
|
||||
Imstk.Geometry geomB = (objectB.GetDynamicObject() as Imstk.PbdObject).getPhysicsGeometry();
|
||||
var pointSetB = Imstk.Utils.CastTo<Imstk.PointSet>(geomB);
|
||||
var verticesB = MathUtil.ToVector3Array(pointSetB.getVertexPositions());
|
||||
|
||||
foreach (var indexA in pointsA)
|
||||
{
|
||||
var pointA = verticesA[indexA];
|
||||
foreach(var indexB in pointsB)
|
||||
{
|
||||
var pointB = verticesB[indexB];
|
||||
var dist = (pointB - pointA).sqrMagnitude;
|
||||
if (dist <= cutoff)
|
||||
{
|
||||
var constraint = new Imstk.PbdDistanceConstraint();
|
||||
var p1 = new Imstk.IntPair((objectA.GetDynamicObject() as Imstk.PbdObject).getPbdBody().bodyHandle, (int)indexA);
|
||||
var p2 = new Imstk.IntPair((objectB.GetDynamicObject() as Imstk.PbdObject).getPbdBody().bodyHandle, (int)indexB);
|
||||
constraint.initConstraint(dist * restLengthFactor, p1, p2);
|
||||
SimulationManager.pbdModel.getConstraints().addConstraint(constraint);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Debug.Log(name + " Added " + count.ToString() + " constraints.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2d6a9310b1ae3d4e8bf7ad691f4f69e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,157 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 Imstk;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
/// <summary>
|
||||
/// This will set up a set of distance constraints between the points of deformable
|
||||
/// that are found inside the constrained area and virtual points, effectively
|
||||
/// attaching the deformable to those points in space.
|
||||
/// </summary>
|
||||
/// The constraints will be limited to the area encompassed by the assigned mesh
|
||||
/// constraints will be generated for _all_ points. The length of the constraint will be set to
|
||||
/// restLength. Use this if you want to attach a deformable to a point in space
|
||||
/// e.g. Suspend an organ in the body cavity.
|
||||
public class ConstrainInSpace : ImstkBehaviour
|
||||
{
|
||||
public Deformable deformable = null;
|
||||
|
||||
[Tooltip("Area that is searched for points")]
|
||||
public MeshFilter constrainedArea = null;
|
||||
[Tooltip("Hides the constraining mesh")]
|
||||
public bool hideMesh = true;
|
||||
|
||||
[Tooltip("Affects the resting length of the constraint")]
|
||||
[Min(0)]
|
||||
public float restLength = 0.0f;
|
||||
|
||||
public float stiffness = 1.0e5f;
|
||||
|
||||
public bool runOnStart = true;
|
||||
|
||||
List<Imstk.PbdConstraint> _constraints = new List<Imstk.PbdConstraint>();
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
var renderer = constrainedArea.gameObject.GetComponent<MeshRenderer>();
|
||||
if (renderer != null && hideMesh)
|
||||
{
|
||||
renderer.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected override void OnImstkStart()
|
||||
{
|
||||
if (!isActiveAndEnabled) return;
|
||||
if (deformable == null || !deformable.isActiveAndEnabled ||
|
||||
constrainedArea == null)
|
||||
{
|
||||
enabled = false;
|
||||
Debug.Log(name + " disabled due to missing or disabled dependency.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (runOnStart)
|
||||
{
|
||||
Constrain();
|
||||
}
|
||||
}
|
||||
|
||||
public void Constrain()
|
||||
{
|
||||
ImstkMesh bcGeometry = constrainedArea.sharedMesh.ToImstkMesh(constrainedArea.transform.localToWorldMatrix);
|
||||
Imstk.SurfaceMesh bcImstkGeometry = bcGeometry.ToImstkGeometry() as Imstk.SurfaceMesh;
|
||||
|
||||
Imstk.Geometry geom = (deformable.GetDynamicObject() as Imstk.PbdObject).getPhysicsGeometry();
|
||||
var points = PointsInside(bcImstkGeometry, Imstk.Utils.CastTo<Imstk.PointSet>(geom));
|
||||
|
||||
if (points.Count == 0)
|
||||
{
|
||||
Debug.LogWarning("No points in constraint area " + gameObject.name);
|
||||
}
|
||||
|
||||
ConstrainPoints(deformable, points);
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
var model = SimulationManager.pbdModel;
|
||||
var constraints = model.getConstraints();
|
||||
foreach (var constraint in _constraints)
|
||||
{
|
||||
constraints.removeConstraint(constraint);
|
||||
}
|
||||
}
|
||||
|
||||
// Refactor to common functions
|
||||
List<uint> PointsInside(SurfaceMesh enclosingMesh, PointSet sampleMesh)
|
||||
{
|
||||
var result = new List<uint>();
|
||||
// Compute mask of enclosed points
|
||||
Imstk.SelectEnclosedPoints selectEnclosed = new Imstk.SelectEnclosedPoints();
|
||||
selectEnclosed.setInputMesh(enclosingMesh);
|
||||
selectEnclosed.setInputPoints(sampleMesh);
|
||||
selectEnclosed.setUsePruning(false);
|
||||
selectEnclosed.update();
|
||||
|
||||
Imstk.DataArrayuc isInside = selectEnclosed.getIsInsideMask();
|
||||
byte[] isInsideBytes = new byte[isInside.size()];
|
||||
isInside.getValues(isInsideBytes);
|
||||
for (int i = 0; i < isInsideBytes.Length; i++)
|
||||
{
|
||||
if (isInsideBytes[i] == 1)
|
||||
result.Add((uint)i);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void ConstrainPoints(Deformable deformable, List<uint> points)
|
||||
{
|
||||
int count = 0;
|
||||
Imstk.Geometry geom = (deformable.GetDynamicObject() as Imstk.PbdObject).getPhysicsGeometry();
|
||||
var pointSet = Imstk.Utils.CastTo<Imstk.PointSet>(geom);
|
||||
var vertices = MathUtil.ToVector3Array(pointSet.getVertexPositions());
|
||||
var model = SimulationManager.pbdModel;
|
||||
Vec3d zero = new Vec3d(0, 0, 0);
|
||||
foreach(var indexB in points)
|
||||
{
|
||||
var pointB = vertices[indexB].ToImstkVec();
|
||||
var p1 = model.addVirtualParticle(pointB, 0, zero, true);
|
||||
var constraint = new Imstk.PbdDistanceConstraint();
|
||||
var p2 = new Imstk.IntPair((deformable.GetDynamicObject() as Imstk.PbdObject).getPbdBody().bodyHandle, (int)indexB);
|
||||
constraint.initConstraint(restLength, p1, p2);
|
||||
constraint.setStiffness(stiffness);
|
||||
model.getConstraints().addConstraint(constraint);
|
||||
_constraints.Add(constraint);
|
||||
count++;
|
||||
}
|
||||
Debug.Log(name + " Added " + count.ToString() + " constraints.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2cb80ed1cc676ca49879918dcfce3566
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a529bbd4ff961aa4088136c67013adab
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
public abstract class ImstkControllerBehaviour : MonoBehaviour
|
||||
{
|
||||
public TrackingDevice device = null;
|
||||
|
||||
public abstract Imstk.DeviceControl GetController();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 698941b5df545604d963b6ae514eebcf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,167 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
/// <summary>
|
||||
/// Object used between a device handled by the user and a ``Rigid``.
|
||||
/// </summary>
|
||||
/// It utilizes a mass spring system to correct for latency in the system.
|
||||
/// It corrects for problems with haptics in simulation systems. By manipulating
|
||||
/// the spring parameters the haptic response can be tuned to the behavior of
|
||||
/// the computer and the simulated system.
|
||||
[AddComponentMenu("iMSTK/RigidController")]
|
||||
public class RigidController : ImstkControllerBehaviour
|
||||
{
|
||||
Imstk.PbdObjectController controller = null;
|
||||
public Rigid rigid = null;
|
||||
|
||||
public double angularKd = 50.0;
|
||||
public double angularKs = 1000.0;
|
||||
public double linearKd = 100.0;
|
||||
public double linearKs = 10000.0;
|
||||
public bool useCriticalDamping = true;
|
||||
|
||||
public double forceScale = 0.00001;
|
||||
public bool useForceSmoothing = true;
|
||||
public int forceSmoothingKernelSize = 15;
|
||||
|
||||
// All these transforms below could really just be one
|
||||
public Vector3 attachmentPoint = Vector3.zero;
|
||||
public Vector3 translationalOffset = Vector3.zero;
|
||||
public Quaternion rotationalOffset = Quaternion.identity;
|
||||
public Quaternion localRotationalOffset = Quaternion.identity;
|
||||
public double translationScaling = 1;
|
||||
|
||||
// Unity uses LHS, while imstk uses RHS, invert X positional
|
||||
public bool invertX = false;
|
||||
public bool invertY = false;
|
||||
public bool invertZ = true;
|
||||
|
||||
// Unity uses LHS, while imstk uses RHS, invert Y,Z planes
|
||||
public bool invertRotX = true;
|
||||
public bool invertRotY = true;
|
||||
public bool invertRotZ = false;
|
||||
|
||||
public bool debugController = false;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// These are used to drive the editor foldouts
|
||||
public bool _forceFoldout = false;
|
||||
public bool _offsetFoldout = false;
|
||||
public bool _axisMappingFoldout = false;
|
||||
#endif
|
||||
|
||||
public Vector3 GetPosition()
|
||||
{
|
||||
Imstk.Vec3d pos = controller.getPosition();
|
||||
return pos.ToUnityVec();
|
||||
}
|
||||
public Quaternion GetOrientation()
|
||||
{
|
||||
Imstk.Quatd quat = controller.getOrientation();
|
||||
return quat.ToUnityQuat();
|
||||
}
|
||||
|
||||
public override Imstk.DeviceControl GetController()
|
||||
{
|
||||
if (device == null)
|
||||
{
|
||||
Debug.LogError("Failed to create controller, no device given");
|
||||
return null;
|
||||
}
|
||||
if (rigid == null)
|
||||
{
|
||||
Debug.LogError("Failed to create controller, no controlled object given");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (controller != null)
|
||||
{
|
||||
return controller;
|
||||
}
|
||||
|
||||
controller = new Imstk.PbdObjectController(gameObject.name);
|
||||
controller.setControlledObject(rigid.GetDynamicObject());
|
||||
controller.setDevice(device.GetDevice());
|
||||
controller.setAngularKd(angularKd);
|
||||
controller.setAngularKs(angularKs);
|
||||
controller.setLinearKd(linearKd);
|
||||
controller.setLinearKs(linearKs);
|
||||
|
||||
controller.setUseCritDamping(useCriticalDamping);
|
||||
|
||||
controller.setForceScaling(forceScale);
|
||||
controller.setUseForceSmoothening(useForceSmoothing);
|
||||
controller.setSmoothingKernelSize(forceSmoothingKernelSize);
|
||||
|
||||
controller.setHapticOffset(attachmentPoint.ToImstkVec());
|
||||
|
||||
;
|
||||
controller.setTranslationOffset((translationalOffset + transform.TransformDirection(attachmentPoint)).ToImstkVec());
|
||||
controller.setRotationOffset(rotationalOffset.ToImstkQuat());
|
||||
controller.setEffectorRotationOffset(localRotationalOffset.ToImstkQuat());
|
||||
controller.setTranslationScaling(translationScaling);
|
||||
|
||||
Imstk.TrackingDeviceControl.InvertFlag invertFlag = 0x00;
|
||||
if (invertX)
|
||||
{
|
||||
invertFlag = invertFlag | Imstk.TrackingDeviceControl.InvertFlag.transX;
|
||||
}
|
||||
if (invertY)
|
||||
{
|
||||
invertFlag = invertFlag | Imstk.TrackingDeviceControl.InvertFlag.transY;
|
||||
}
|
||||
if (invertZ)
|
||||
{
|
||||
invertFlag = invertFlag | Imstk.TrackingDeviceControl.InvertFlag.transZ;
|
||||
}
|
||||
if (invertRotX)
|
||||
{
|
||||
invertFlag = invertFlag | Imstk.TrackingDeviceControl.InvertFlag.rotX;
|
||||
}
|
||||
if (invertRotY)
|
||||
{
|
||||
invertFlag = invertFlag | Imstk.TrackingDeviceControl.InvertFlag.rotY;
|
||||
}
|
||||
if (invertRotZ)
|
||||
{
|
||||
invertFlag = invertFlag | Imstk.TrackingDeviceControl.InvertFlag.rotZ;
|
||||
}
|
||||
|
||||
controller.setInversionFlags((byte)invertFlag);
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
// Leaving this on in the built version causes unexpected behavior
|
||||
public void Update()
|
||||
{
|
||||
if (debugController)
|
||||
{
|
||||
gameObject.transform.SetPositionAndRotation(GetPosition(), GetOrientation());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 170eeb0fc124ca24f9d638781ae042cf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,188 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
[AddComponentMenu("iMSTK/Deformable")]
|
||||
/// <summary>
|
||||
/// Use this to represent deformable objects. Position Based Dynamics (PBD),
|
||||
/// is used to model the deformation.
|
||||
/// </summary>
|
||||
/// This model supports Lines (1D), Surface Meshes (2D) and, Tetrahedral Meshes (3D)
|
||||
/// dynamical models see the iMSTK Documentation <https://imstk.gitlab.io/Dynamical_Models/PbdModel.html>
|
||||
/// for more information on constraints and models. Visual, physics and collision
|
||||
/// geometry can be assigned separately. If you do, a separate map will be necessary
|
||||
/// to update the various meshes.
|
||||
/// The physics geometry determines the type of constraint that can be used,
|
||||
/// an invalid constraint may cause problems.
|
||||
/// | Physics Geometry Type | Valid Constraints |
|
||||
/// | --------------------- | ----------------- |
|
||||
/// | Line Mesh(Threads) | Distance Stiffness, Bend Stiffness |
|
||||
/// | Surface Mesh(Membranes, Bags) | Distance Stiffness, Dihedral Stiffness, Area Stiffness |
|
||||
/// | Volumetric Mesh(Tissue) | Distance Stiffness, Volume Stiffness, Fem(all models) |
|
||||
public class Deformable : DeformableModel
|
||||
{
|
||||
public double distanceStiffness = 100.0;
|
||||
public bool useDistanceConstraint = true;
|
||||
|
||||
public double dihedralStiffness = 10.0;
|
||||
public bool useDihedralConstraint = true;
|
||||
|
||||
public double areaStiffness = 10.0;
|
||||
public bool useAreaConstraint = true;
|
||||
|
||||
public double bendStiffness = 10.0;
|
||||
public int maxBendStride = 2;
|
||||
public bool useBendConstraint = false;
|
||||
|
||||
public double volumeStiffness = 10.0;
|
||||
public bool useVolumeConstraint = false;
|
||||
|
||||
public double youngsModulus = 5000.0;
|
||||
public double possionsRatio = 0.4;
|
||||
public double mu = 0.0;
|
||||
public double lambda = 0.0;
|
||||
public double viscousDampingCoeff = 0.01;
|
||||
public bool useYoungsModulus = true;
|
||||
public bool useFEMConstraint = false;
|
||||
public Imstk.PbdFemConstraint.MaterialType materialType = Imstk.PbdFemConstraint.MaterialType.StVK;
|
||||
|
||||
public double uniformMassValue = 1.0;
|
||||
|
||||
public HashSet<int> fixedIndices = new HashSet<int>();
|
||||
|
||||
public bool useBodyDamping = false;
|
||||
public double linearDampingCoeff = 0.01;
|
||||
public double angularDampingCoeff = 0.01;
|
||||
|
||||
protected override Imstk.CollidingObject InitObject()
|
||||
{
|
||||
Imstk.PbdObject pbdObject = new Imstk.PbdObject(GetFullName());
|
||||
pbdObject.setDynamicalModel(SimulationManager.pbdModel);
|
||||
return pbdObject;
|
||||
}
|
||||
|
||||
protected override void Configure()
|
||||
{
|
||||
Imstk.PbdModelConfig config = SimulationManager.pbdModel.getConfig();
|
||||
Imstk.PbdBody pbdBody = (imstkObject as Imstk.PbdObject).getPbdBody();
|
||||
int bodyHandle = pbdBody.bodyHandle;
|
||||
|
||||
if (useDistanceConstraint)
|
||||
config.enableConstraint(Imstk.PbdModelConfig.ConstraintGenType.Distance, distanceStiffness, bodyHandle);
|
||||
|
||||
if (useDihedralConstraint)
|
||||
config.enableConstraint(Imstk.PbdModelConfig.ConstraintGenType.Dihedral, dihedralStiffness, bodyHandle);
|
||||
|
||||
if (useAreaConstraint)
|
||||
config.enableConstraint(Imstk.PbdModelConfig.ConstraintGenType.Area, areaStiffness, bodyHandle);
|
||||
|
||||
if (useVolumeConstraint)
|
||||
config.enableConstraint(Imstk.PbdModelConfig.ConstraintGenType.Volume, volumeStiffness, bodyHandle);
|
||||
|
||||
if (useBendConstraint)
|
||||
{
|
||||
for (int i = 1; i <= maxBendStride; i++)
|
||||
{
|
||||
config.enableBendConstraint(bendStiffness, i, true, bodyHandle);
|
||||
}
|
||||
}
|
||||
|
||||
if (useFEMConstraint)
|
||||
{
|
||||
if ((imstkObject as Imstk.DynamicObject).getPhysicsGeometry().getTypeName() != "TetrahedralMesh")
|
||||
{
|
||||
Debug.Log("Currently only Tetrahedral mesh is supported for FEM constraints");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (useYoungsModulus)
|
||||
{
|
||||
config.m_femParams = new Imstk.PbdFemConstraintConfig(0.0, 0.0, youngsModulus, possionsRatio);
|
||||
}
|
||||
else
|
||||
{
|
||||
config.m_femParams = new Imstk.PbdFemConstraintConfig(mu, lambda, 0.0, 0.0);
|
||||
}
|
||||
config.enableFemConstraint(materialType,bodyHandle);
|
||||
}
|
||||
}
|
||||
|
||||
if (useBodyDamping)
|
||||
{
|
||||
config.setBodyDamping(bodyHandle, linearDampingCoeff, angularDampingCoeff);
|
||||
}
|
||||
|
||||
pbdBody.uniformMassValue = uniformMassValue;
|
||||
pbdBody.bodyGravity = !ignoreGravity;
|
||||
|
||||
var fixedNodes = new Imstk.VectorInt();
|
||||
foreach (int id in fixedIndices)
|
||||
{
|
||||
fixedNodes.Add(id);
|
||||
}
|
||||
pbdBody.fixedNodeIds = fixedNodes;
|
||||
}
|
||||
|
||||
protected override void ProcessBoundaryConditions(BoundaryCondition[] conditions)
|
||||
{
|
||||
// This model currently uses fixed vertices for BC, this is what we will compute
|
||||
// Clear them to start with
|
||||
fixedIndices.Clear();
|
||||
if (conditions.Length == 0)
|
||||
return;
|
||||
|
||||
// For every BC test intersection to find fixed vertices
|
||||
foreach (BoundaryCondition condition in conditions)
|
||||
{
|
||||
if (!condition.enabled) return;
|
||||
// Create the surface mesh the points will be tested if inside of
|
||||
MeshFilter meshFilter = condition.bcObj.GetComponent<MeshFilter>();
|
||||
Transform transform = condition.bcObj.GetComponent<Transform>();
|
||||
if (meshFilter == null)
|
||||
continue;
|
||||
|
||||
// Convert unity to imstk geometry
|
||||
ImstkMesh bcGeometry = meshFilter.sharedMesh.ToImstkMesh(transform.localToWorldMatrix);
|
||||
Imstk.SurfaceMesh bcImstkGeometry = bcGeometry.ToImstkGeometry() as Imstk.SurfaceMesh;
|
||||
|
||||
// Compute mask of enclosed points
|
||||
Imstk.SelectEnclosedPoints selectEnclosed = new Imstk.SelectEnclosedPoints();
|
||||
selectEnclosed.setInputMesh(bcImstkGeometry);
|
||||
Imstk.Geometry physicsGeom = (imstkObject as Imstk.PbdObject).getPhysicsGeometry();
|
||||
selectEnclosed.setInputPoints(Imstk.Utils.CastTo<Imstk.PointSet>(physicsGeom));
|
||||
selectEnclosed.setUsePruning(false);
|
||||
selectEnclosed.update();
|
||||
|
||||
Imstk.DataArrayuc isInside = selectEnclosed.getIsInsideMask();
|
||||
byte[] isInsideBytes = new byte[isInside.size()];
|
||||
isInside.getValues(isInsideBytes);
|
||||
for (int i = 0; i < isInsideBytes.Length; i++)
|
||||
{
|
||||
if (isInsideBytes[i] == 1)
|
||||
fixedIndices.Add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8010250de4d49fa4296e91342e4f0907
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,65 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows the use of separate meshes for the deformable, visual and collision representation.
|
||||
/// </summary>
|
||||
/// Will move the vertices of the target mesh according to matching points on the source mesh.
|
||||
/// The points do not have to completely coincide. In almost all cases you will need to map
|
||||
/// FROM the physics mesh TO the visual mesh, and FROM the physics mesh TO the collision mesh.
|
||||
[AddComponentMenu("iMSTK/DeformableMap")]
|
||||
public class DeformableMap : GeometryMap
|
||||
{
|
||||
public bool forceOneOne = false;
|
||||
protected override Imstk.GeometryMap MakeMap()
|
||||
{
|
||||
Imstk.Geometry parent = parentGeom.GetOutputGeometry();
|
||||
Imstk.Geometry child = childGeom.GetOutputGeometry();
|
||||
|
||||
if (parentGeom == null || childGeom == null)
|
||||
{
|
||||
Debug.LogError("GeometryMap: can't create map when one or more inputs is null");
|
||||
}
|
||||
|
||||
|
||||
if (!forceOneOne && (parent.getTypeName() == Imstk.TetrahedralMesh.getStaticTypeName()
|
||||
|| child.getTypeName() == Imstk.TetrahedralMesh.getStaticTypeName()))
|
||||
{
|
||||
Debug.Log("Trying to make tetrahedral map with " + parent.getTypeName() + " and " + child.getTypeName());
|
||||
var map = new Imstk.PointToTetMap(parent, child);
|
||||
map.compute();
|
||||
return map;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Trying to make one to one map with " + parent.getTypeName() + " and " + child.getTypeName());
|
||||
var map = new Imstk.PointwiseMap(parent, child);
|
||||
// Tolerance needed to avoid issues with double/float conversions
|
||||
map.setTolerance(1e-4);
|
||||
map.compute();
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 127fba25d5cdc4445a9fa44afd5ec2a7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,250 @@
|
||||
/*=========================================================================
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0b6c41fdfe3e6cd488427dbb4c2b5899
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2bd3c65d7e413c4f99541baad2babac
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,129 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
using System.Threading;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
// HS-2022-feb-02 Should be refactored to remove the "manager" functionality from the
|
||||
// Device, see the VRPNDevice for the pattern. Remove `static` components
|
||||
// from here
|
||||
|
||||
#if IMSTK_USE_OPENHAPTICS
|
||||
// If this is not defined iMSTK was not built with Open Haptics enabled
|
||||
// to use build iMSTK with the flag iMSTK_USE_OpenHaptics set to ON
|
||||
[AddComponentMenu("iMSTK/OpenHapticsDevice")]
|
||||
public class OpenHapticsDevice : TrackingDevice
|
||||
{
|
||||
public string deviceName = "default";
|
||||
|
||||
public static Imstk.OpenHapticDeviceManager openHapticDeviceManager = null;
|
||||
public static bool hapticsRunning = false;
|
||||
public static Thread hapticThread = null;
|
||||
|
||||
public static void InitManager()
|
||||
{
|
||||
if (openHapticDeviceManager != null)
|
||||
{
|
||||
openHapticDeviceManager.init();
|
||||
}
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
GetDevice();
|
||||
}
|
||||
|
||||
public static void StartManager()
|
||||
{
|
||||
// Launch haptics on a separate thread if using
|
||||
if (openHapticDeviceManager != null)
|
||||
{
|
||||
hapticsRunning = true;
|
||||
Debug.Log("OpenHaptics Thread Starting");
|
||||
hapticThread = new Thread(() =>
|
||||
{
|
||||
while (hapticsRunning)
|
||||
{
|
||||
if (openHapticDeviceManager != null)
|
||||
{
|
||||
openHapticDeviceManager.update();
|
||||
}
|
||||
}
|
||||
});
|
||||
hapticThread.Start();
|
||||
}
|
||||
}
|
||||
public static void StopManager()
|
||||
{
|
||||
if (openHapticDeviceManager != null)
|
||||
{
|
||||
hapticsRunning = false;
|
||||
hapticThread.Join();
|
||||
|
||||
Debug.Log("OpenHaptics Thread Stopping");
|
||||
openHapticDeviceManager.uninit();
|
||||
openHapticDeviceManager = null;
|
||||
hapticThread = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override Imstk.DeviceClient MakeDevice()
|
||||
{
|
||||
if (openHapticDeviceManager == null)
|
||||
{
|
||||
openHapticDeviceManager = new Imstk.OpenHapticDeviceManager();
|
||||
}
|
||||
Debug.Log("MakeDeviceClient <" + deviceName + ">");
|
||||
// Creates the default device (specify name for specific one)
|
||||
if (deviceName == "default")
|
||||
{
|
||||
return openHapticDeviceManager.makeDeviceClient();
|
||||
}
|
||||
else
|
||||
{
|
||||
return openHapticDeviceManager.makeDeviceClient(deviceName);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
public class OpenHapticsDevice : TrackingDevice
|
||||
{
|
||||
public string deviceName = "default";
|
||||
|
||||
public static void InitManager()
|
||||
{
|
||||
Debug.LogError("OpenHaptics is not enable in this build");
|
||||
}
|
||||
|
||||
public void Start() {}
|
||||
|
||||
public static void StartManager() {}
|
||||
public static void StopManager() {}
|
||||
|
||||
protected override Imstk.DeviceClient MakeDevice() {
|
||||
Debug.LogError("OpenHaptics is not enable in this build, " +
|
||||
"see the documentation for more information ");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8117a352c4c15c4893e11073f5a3a39
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,105 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
enum ButtonState
|
||||
{
|
||||
// From Imstk
|
||||
BUTTON_RELEASED = 0,
|
||||
BUTTON_TOUCHED = 1,
|
||||
BUTTON_UNTOUCHED = 2,
|
||||
BUTTON_PRESSED = 3
|
||||
}
|
||||
|
||||
|
||||
public abstract class TrackingDevice : MonoBehaviour
|
||||
{
|
||||
Imstk.DeviceClient trackingDevice = null;
|
||||
|
||||
public Vector3 GetPosition()
|
||||
{
|
||||
Imstk.Vec3d pos = trackingDevice.getPosition();
|
||||
return pos.ToUnityVec();
|
||||
}
|
||||
public Quaternion GetOrientation()
|
||||
{
|
||||
Imstk.Quatd quat = trackingDevice.getOrientation();
|
||||
return quat.ToUnityQuat();
|
||||
}
|
||||
|
||||
public Vector3 GetForce()
|
||||
{
|
||||
Imstk.Vec3d vec = trackingDevice.getForce();
|
||||
return vec.ToUnityVec();
|
||||
}
|
||||
|
||||
public bool IsButtonDown(int id)
|
||||
{
|
||||
var val = trackingDevice.getButton(id);
|
||||
if (val == (int)ButtonState.BUTTON_PRESSED || val == (int)ButtonState.BUTTON_TOUCHED) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
public int[] GetButtons()
|
||||
{
|
||||
var result = new int[8];
|
||||
|
||||
for (int i = 0; i<8;++i)
|
||||
{
|
||||
result[i] = trackingDevice.getButton(i);
|
||||
}
|
||||
var b = trackingDevice.getButtons();
|
||||
return result;
|
||||
}
|
||||
|
||||
public float GetAnalog(int id)
|
||||
{
|
||||
var values = trackingDevice.getAnalog();
|
||||
if (values.Count > id) return (float)values[id];
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("Id " + id.ToString() + " not found ");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Imstk.DeviceClient MakeDevice();
|
||||
|
||||
public void Update()
|
||||
{
|
||||
// This is not directly used, but displayed
|
||||
Transform transform = gameObject.GetComponentFatal<Transform>();
|
||||
transform.SetPositionAndRotation(GetPosition(), GetOrientation());
|
||||
}
|
||||
|
||||
public Imstk.DeviceClient GetDevice()
|
||||
{
|
||||
if (trackingDevice == null)
|
||||
{
|
||||
trackingDevice = MakeDevice();
|
||||
trackingDevice.setButtonsEnabled(true);
|
||||
}
|
||||
return trackingDevice;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c4b75e1c7ff86c46be94008f67ce2e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,57 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
[AddComponentMenu("iMSTK/VrpnDevice")]
|
||||
public class VrpnDevice : TrackingDevice
|
||||
{
|
||||
|
||||
public string Name = "Tracker0";
|
||||
private int _type = 0;
|
||||
public int Type { get { return _type; } }
|
||||
|
||||
public bool TrackAnalog = false;
|
||||
public bool TrackButtons = false;
|
||||
public bool TrackPosition = true;
|
||||
|
||||
public ImstkUnity.VrpnDeviceManager manager;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
if (TrackAnalog) _type |= 0x1;
|
||||
if (TrackButtons) _type |= 0x2;
|
||||
if (TrackPosition) _type |= 0x4;
|
||||
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
GetDevice();
|
||||
}
|
||||
|
||||
protected override Imstk.DeviceClient MakeDevice()
|
||||
{
|
||||
return manager.MakeDeviceClient(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 79de4454bc1384f40b18333f30326fb5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,126 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 System.Threading;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
#if IMSTK_USE_VRPN
|
||||
// If this is not defined iMSTK was not built with VRPN enabled
|
||||
// to use build iMSTK with the flag iMSTK_USE_VRPN set to ON
|
||||
[AddComponentMenu("iMSTK/VrpnDeviceManager")]
|
||||
public class VrpnDeviceManager : MonoBehaviour
|
||||
{
|
||||
private static VrpnDeviceManager _instance;
|
||||
|
||||
// Probably Refactor to Singleton base class
|
||||
public static VrpnDeviceManager Instance
|
||||
{
|
||||
get { return _instance; }
|
||||
}
|
||||
|
||||
public string host = "localhost";
|
||||
public int port = 3883;
|
||||
|
||||
private Imstk.VRPNDeviceManager _manager;
|
||||
private Thread thread;
|
||||
private bool running = false;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
_instance = this;
|
||||
}
|
||||
|
||||
public void InitManager()
|
||||
{
|
||||
if (_manager == null)
|
||||
{
|
||||
_manager = new Imstk.VRPNDeviceManager(host, port);
|
||||
if (_manager == null) Debug.LogError("Could not create VRPNDevice Manager");
|
||||
_manager.setSleepDelay(20);
|
||||
_manager.init();
|
||||
}
|
||||
}
|
||||
|
||||
public Imstk.DeviceClient MakeDeviceClient(ImstkUnity.VrpnDevice device)
|
||||
{
|
||||
InitManager();
|
||||
return _manager.makeDeviceClient(device.Name, device.Type);
|
||||
}
|
||||
|
||||
public void StartManager()
|
||||
{
|
||||
if (running) return;
|
||||
|
||||
InitManager();
|
||||
running = true;
|
||||
Debug.Log("VRPN Thread Starting");
|
||||
thread = new Thread(() =>
|
||||
{
|
||||
while (running)
|
||||
{
|
||||
_manager.update();
|
||||
}
|
||||
});
|
||||
thread.Start();
|
||||
}
|
||||
public void StopManager()
|
||||
{
|
||||
if (_manager == null) return;
|
||||
if (!running) return;
|
||||
running = false;
|
||||
thread.Join();
|
||||
|
||||
Debug.Log("VRPN Thread Stopping");
|
||||
_manager.uninit();
|
||||
thread = null;
|
||||
}
|
||||
}
|
||||
#else
|
||||
[AddComponentMenu("iMSTK/VrpnDeviceManager")]
|
||||
public class VrpnDeviceManager : MonoBehaviour
|
||||
{
|
||||
// Probably Refactor to Singleton base class
|
||||
public static VrpnDeviceManager Instance
|
||||
{
|
||||
get {
|
||||
Debug.LogError("VRPN is not enable in this build");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
var a = Instance;
|
||||
}
|
||||
|
||||
public void InitManager() {}
|
||||
|
||||
public Imstk.DeviceClient MakeDeviceClient(ImstkUnity.VrpnDevice device) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void StartManager() {}
|
||||
public void StopManager() {}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1644d13714b4c8446a7bc7df42c96612
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,70 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
[RequireComponent(typeof(Transform))]
|
||||
public abstract class DynamicalModel : ImstkBehaviour
|
||||
{
|
||||
// HS 20221220 Need to figure out what we need at this level
|
||||
// - What is common setup, what can just move into Deformable/Rigid
|
||||
// - What distinguishes an object that can collied to one that doesn't (this is
|
||||
// needed for setting up the collision handling object)
|
||||
|
||||
// Components
|
||||
protected MeshFilter meshFilter = null;
|
||||
|
||||
protected Imstk.CollidingObject imstkObject;
|
||||
|
||||
// Indicates that geometry changes may happen as opposed to just
|
||||
// position changes
|
||||
// If true update needs to refresh vertex and triangle indices rather
|
||||
// than just copying positions
|
||||
public bool dynamicGeometry = false;
|
||||
|
||||
// Tells the object to ignore the global gravity parameter
|
||||
public bool ignoreGravity = false;
|
||||
|
||||
/// <summary>
|
||||
/// Get the pointer to the object in c (not available until after initialize)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Imstk.CollidingObject GetDynamicObject() { return imstkObject; }
|
||||
|
||||
// NOTE HS 20221220 Refactor readonly properties, initialize in each object
|
||||
public abstract Imstk.Geometry GetVisualGeometry();
|
||||
public abstract Imstk.Geometry GetPhysicsGeometry();
|
||||
public abstract Imstk.Geometry GetCollidingGeometry();
|
||||
|
||||
protected abstract Imstk.CollidingObject InitObject();
|
||||
|
||||
protected abstract void Configure();
|
||||
|
||||
/// <summary>
|
||||
/// Each subclassed model may *apply* boundary conditions differently
|
||||
/// </summary>
|
||||
/// <param name="conditions">All the conditions to be processed</param>
|
||||
protected virtual void ProcessBoundaryConditions(BoundaryCondition[] conditions) { }
|
||||
|
||||
protected abstract void InitGeometry();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf91fa9a7a7898e479e5e362b62d2a0d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4971aef8039238944818264e2cf5a626
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,117 @@
|
||||
using Imstk;
|
||||
using ImstkUnity;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
[CustomEditor(typeof(ImstkUnity.CollisionInteraction), true)]
|
||||
public class CollisionInteractionEditor : Editor
|
||||
{
|
||||
double _friction = 0.0;
|
||||
double _restitution = 0.0;
|
||||
|
||||
double _deformableStiffness1 = 0.2;
|
||||
double _deformableStiffness2 = 0.2;
|
||||
|
||||
double _rigidBodyCompliance = 0.0001;
|
||||
|
||||
DynamicalModel _model1;
|
||||
DynamicalModel _model2;
|
||||
|
||||
static string[] _options;
|
||||
public static string[] CDOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_options == null)
|
||||
{
|
||||
var names = CDObjectFactory.getNames();
|
||||
_options = new string[names.Count + 1];
|
||||
_options[0] = "Auto";
|
||||
for (int i = 0; i < names.Count; ++i)
|
||||
{
|
||||
_options[i + 1] = names[i];
|
||||
}
|
||||
}
|
||||
return _options;
|
||||
}
|
||||
}
|
||||
|
||||
string _message;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
var script = target as ImstkUnity.CollisionInteraction;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
_message = "Model 1 " + GetGeometryType(script.model1);
|
||||
_model1 = EditorGUILayout.ObjectField(_message, script.model1, typeof(DynamicalModel), true) as DynamicalModel;
|
||||
|
||||
|
||||
_message = "Model 2 " + GetGeometryType(script.model2);
|
||||
_model2 = EditorGUILayout.ObjectField(_message, script.model2, typeof(DynamicalModel), true) as DynamicalModel;
|
||||
|
||||
var selected = System.Array.IndexOf(CDOptions, script.collisionTypeName);
|
||||
selected = EditorGUILayout.Popup("Detection Type", selected, CDOptions);
|
||||
|
||||
_message = "Auto Type: ";
|
||||
if (_model1 != null && _model1.GetCollidingGeometry() != null &&
|
||||
_model2 != null && _model2.GetCollidingGeometry() != null)
|
||||
{
|
||||
_message += ImstkUnity.CollisionInteraction.GetCDType(_model1, _model2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_message += " None";
|
||||
}
|
||||
EditorGUILayout.LabelField(_message);
|
||||
|
||||
_friction = EditorGUILayout.DoubleField("Friction", script.friction);
|
||||
_restitution = EditorGUILayout.DoubleField("Restitution", script.restitution);
|
||||
|
||||
var guiContent = new GUIContent("Deform. Stiffness 1", "A good default value is 1/number of iterations from the simulation manager");
|
||||
_deformableStiffness1 = EditorGUILayout.DoubleField(guiContent, script.deformableStiffness1);
|
||||
|
||||
guiContent = new GUIContent("Deform. Stiffness 2", "A good default value is 1/number of iterations from the simulation manager");
|
||||
_deformableStiffness2 = EditorGUILayout.DoubleField(guiContent, script.deformableStiffness2);
|
||||
|
||||
_rigidBodyCompliance = EditorGUILayout.DoubleField("Rigid Compliance", script.rigidBodyCompliance);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
script.friction = _friction;
|
||||
script.restitution = _restitution;
|
||||
|
||||
script.model1 = _model1;
|
||||
script.model2 = _model2;
|
||||
|
||||
script.collisionTypeName = CDOptions[selected];
|
||||
|
||||
script.deformableStiffness1 = _deformableStiffness1;
|
||||
script.deformableStiffness2 = _deformableStiffness2;
|
||||
|
||||
script.rigidBodyCompliance = _rigidBodyCompliance;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetGeometryType(DynamicalModel model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
Imstk.Geometry geom = model.GetCollidingGeometry();
|
||||
if (geom == null)
|
||||
{
|
||||
return "<no geometry>";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "<" + geom.getTypeName() + ">";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e1e3f82b50dba9749aa16e4b978717e3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
using ImstkUnity;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
[CustomEditor(typeof(ConnectiveTissue))]
|
||||
public class ConnectiveTissueEditor : Editor
|
||||
{
|
||||
// Local variables for caching editor results
|
||||
Deformable sideA;
|
||||
Deformable sideB;
|
||||
|
||||
double maxDistance;
|
||||
double strandsPerFace;
|
||||
int segmentsPerStrand;
|
||||
double distanceStiffness;
|
||||
double uniformMassValue;
|
||||
double viscousDampingCoeff;
|
||||
|
||||
GUIContent sideAContent = new GUIContent("Side A", "One side of the objects that should be connected.");
|
||||
GUIContent sideBContent = new GUIContent("Side B", "One side of the objects that should be connected.");
|
||||
GUIContent maxDistContent = new GUIContent("Maximum Distance", "If side a and b are closer than this value" +
|
||||
" connective tissue strands will be generated. If 0 the distance between the centers will be used");
|
||||
GUIContent strandsPerFaceContent = new GUIContent("Strands per Face", "Indicates the density of strands " +
|
||||
"that are being generated, fractions can be used e.g. 0.5 will generate a strand for half the faces");
|
||||
GUIContent segmentsPerStrandContent = new GUIContent("Segments per Strand", "Determines the number of " +
|
||||
"segments for each strand");
|
||||
GUIContent distanceStiffnessContent = new GUIContent("Distance Stiffness", "Determines how much the " +
|
||||
"connective tissue will resist extension.");
|
||||
GUIContent massValueContent = new GUIContent("Uniform Mass Value", "Mass per vertex of the object");
|
||||
GUIContent viscousDampingContent = new GUIContent("Viscous Damping", "Dampens the system");
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
var script = target as ConnectiveTissue;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
sideA = EditorGUILayout.ObjectField(sideAContent, script.objectA, typeof(ImstkUnity.Deformable), true) as ImstkUnity.Deformable;
|
||||
sideB = EditorGUILayout.ObjectField(sideBContent,script.objectB, typeof(ImstkUnity.Deformable), true) as ImstkUnity.Deformable;
|
||||
|
||||
maxDistance = EditorGUILayout.DoubleField(maxDistContent, script.maxDistance);
|
||||
strandsPerFace = EditorGUILayout.DoubleField(strandsPerFaceContent, script.strandsPerFace);
|
||||
segmentsPerStrand = EditorGUILayout.IntField(segmentsPerStrandContent, script.segmentsPerStrand);
|
||||
distanceStiffness = EditorGUILayout.DoubleField(distanceStiffnessContent, script.distanceStiffness);
|
||||
uniformMassValue = EditorGUILayout.DoubleField(massValueContent, script.uniformMassValue);
|
||||
viscousDampingCoeff = EditorGUILayout.DoubleField(viscousDampingContent, script.viscousDampingCoeff);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if ((sideA == null && sideB == null) || sideA != sideB)
|
||||
{
|
||||
script.objectA = sideA;
|
||||
script.objectB = sideB;
|
||||
}
|
||||
|
||||
script.maxDistance = maxDistance;
|
||||
script.strandsPerFace = strandsPerFace;
|
||||
script.segmentsPerStrand = segmentsPerStrand;
|
||||
script.distanceStiffness = distanceStiffness;
|
||||
script.uniformMassValue = uniformMassValue;
|
||||
script.viscousDampingCoeff = viscousDampingCoeff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b4588cff62e4364d93013f493396304
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given define symbols to PlayerSettings define symbols.
|
||||
/// Just add your own define symbols to the Symbols property at the below.
|
||||
/// see https://forum.unity.com/threads/scripting-define-symbols-access-in-code.174390/
|
||||
/// </summary>
|
||||
[InitializeOnLoad]
|
||||
public class DefineSymbols : Editor
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Symbols that will be added to the editor
|
||||
/// </summary>
|
||||
public static readonly string[] StaticSymbols = new string[] { };
|
||||
public static bool runonce = false;
|
||||
|
||||
/// <summary>
|
||||
/// Add define symbols as soon as Unity gets done compiling.
|
||||
/// </summary>
|
||||
static DefineSymbols()
|
||||
{
|
||||
string definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
|
||||
List<string> allDefines = definesString.Split(';').ToList();
|
||||
List<string> originalDefines = new List<string>(allDefines);
|
||||
allDefines.AddRange(StaticSymbols.Except(allDefines));
|
||||
allDefines.AddRange(GetDeviceSymbols().Except(allDefines));
|
||||
if (Enumerable.SequenceEqual(allDefines, originalDefines)) return;
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(
|
||||
EditorUserBuildSettings.selectedBuildTargetGroup,
|
||||
string.Join(";", allDefines.ToArray()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check through the known device names and see if it exists in the factory,
|
||||
/// if yes, set the appropriate symbol so that the device class will be compiled
|
||||
/// </summary>
|
||||
private static List<string> GetDeviceSymbols()
|
||||
{
|
||||
var factory = new Imstk.DeviceManagerFactory();
|
||||
var names = new string[] { "OpenHapticDeviceManager", "IMSTK_USE_OPENHAPTICS",
|
||||
"HaplyDeviceManager", "IMSTK_USE_HAPLY",
|
||||
"VRPNDeviceManager", "IMSTK_USE_VRPN" };
|
||||
var symbols = new List<string>();
|
||||
for (int i = 0; i < names.Length; i += 2)
|
||||
{
|
||||
if (Imstk.DeviceManagerFactory.contains(names[i]))
|
||||
{
|
||||
symbols.Add(names[i + 1]);
|
||||
}
|
||||
}
|
||||
return symbols;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5409589cb14fa6e4eb717abe09f3a86b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,195 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
[CustomEditor(typeof(Deformable))]
|
||||
public class DeformableEditor : DynamicalModelEditor
|
||||
{
|
||||
bool _cleanVisualMesh = false;
|
||||
|
||||
bool _bodyDamping = false;
|
||||
double _linearDampingCoeff = 0.0;
|
||||
double _angularDampingCoeff = 0.0;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
Deformable script = target as Deformable;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
GeometryFilter visualGeomFilter = EditorUtils.GeomFilterField("Visual Geometry", script.visualGeomFilter);
|
||||
GeometryFilter physicsGeomFilter = EditorUtils.GeomFilterField("Physics Geometry", script.physicsGeomFilter);
|
||||
GeometryFilter collisionGeomFilter = EditorUtils.GeomFilterField("Collision Geometry", script.collisionGeomFilter);
|
||||
|
||||
if (visualGeomFilter != null && visualGeomFilter == physicsGeomFilter)
|
||||
{
|
||||
bool val = script.cleanVisualMesh;
|
||||
if (visualGeomFilter != script.visualGeomFilter)
|
||||
{
|
||||
val = visualGeomFilter.type == GeometryType.UnityMesh;
|
||||
}
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
EditorGUILayout.HelpBox(
|
||||
"Some Mesh import may create `duplicate vertices` this will cause your physics object" +
|
||||
" to fall apart at seams that might not be visible in the data. use the `Clean Visual Mesh` option" +
|
||||
" to prevent this." ,MessageType.Warning);
|
||||
_cleanVisualMesh = EditorGUILayout.Toggle("Clean Visual Mesh", val);
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
bool useDistanceConstraint = EditorGUILayout.Toggle("Distance Stiffness", script.useDistanceConstraint);
|
||||
double distanceStiffness = script.distanceStiffness;
|
||||
if (useDistanceConstraint)
|
||||
distanceStiffness = EditorGUILayout.DoubleField("Stiffness", script.distanceStiffness);
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
bool useBendConstraint = EditorGUILayout.Toggle("Bend Stiffness", script.useBendConstraint);
|
||||
double bendStiffness = script.bendStiffness;
|
||||
int bendStride = script.maxBendStride;
|
||||
if (useBendConstraint)
|
||||
{
|
||||
bendStiffness = EditorGUILayout.DoubleField("Stiffness", script.bendStiffness);
|
||||
bendStride = EditorGUILayout.IntField("Stride", script.maxBendStride);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
bool useDihedralConstraint = EditorGUILayout.Toggle("Dihedral Stiffness", script.useDihedralConstraint);
|
||||
double dihedralStiffness = script.dihedralStiffness;
|
||||
if (useDihedralConstraint)
|
||||
dihedralStiffness = EditorGUILayout.DoubleField("Stiffness", script.dihedralStiffness);
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
bool useAreaConstraint = EditorGUILayout.Toggle("Area Stiffness", script.useAreaConstraint);
|
||||
double areaStiffness = script.areaStiffness;
|
||||
if (useAreaConstraint)
|
||||
areaStiffness = EditorGUILayout.DoubleField("Stiffness", script.areaStiffness);
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
bool useVolumeConstraint = EditorGUILayout.Toggle("Volume Stiffness", script.useVolumeConstraint);
|
||||
double volumeStiffness = script.volumeStiffness;
|
||||
if (useVolumeConstraint)
|
||||
volumeStiffness = EditorGUILayout.DoubleField("Stiffness", script.volumeStiffness);
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
bool useFEMConstraint = EditorGUILayout.Toggle("FEM", script.useFEMConstraint);
|
||||
double youngsModulus = script.youngsModulus;
|
||||
double possionsRatio = script.possionsRatio;
|
||||
bool useYoungsModulus = script.useYoungsModulus;
|
||||
double mu = script.mu;
|
||||
double lambda = script.lambda;
|
||||
Imstk.PbdFemConstraint.MaterialType materialType = script.materialType;
|
||||
if (useFEMConstraint)
|
||||
{
|
||||
useYoungsModulus = EditorGUILayout.Toggle("Use Youngs Modulus", script.useYoungsModulus);
|
||||
if (useYoungsModulus)
|
||||
{
|
||||
youngsModulus = EditorGUILayout.DoubleField("Youngs Modulus", script.youngsModulus);
|
||||
possionsRatio = EditorGUILayout.DoubleField("Possions Ratio", script.possionsRatio);
|
||||
}
|
||||
else
|
||||
{
|
||||
mu = EditorGUILayout.DoubleField("Mu", script.mu);
|
||||
lambda = EditorGUILayout.DoubleField("Lambda", script.lambda);
|
||||
}
|
||||
materialType = (Imstk.PbdFemConstraint.MaterialType)EditorGUILayout.EnumPopup("Material Type", script.materialType);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
|
||||
bool ignoreGravity = EditorGUILayout.Toggle("Ignore Gravity", script.ignoreGravity);
|
||||
|
||||
double uniformMassValue = EditorGUILayout.DoubleField("Uniform Mass Value", script.uniformMassValue);
|
||||
if (script.physicsGeomFilter != null)
|
||||
{
|
||||
var physicsGeom = Imstk.Utils.CastTo<Imstk.PointSet>(script.GetPhysicsGeometry());
|
||||
if (physicsGeom != null)
|
||||
{
|
||||
var count = physicsGeom.getNumVertices();
|
||||
double mass = EditorGUILayout.DoubleField("Mass ", count * uniformMassValue);
|
||||
if (mass != count * uniformMassValue)
|
||||
{
|
||||
uniformMassValue = mass / count;
|
||||
}
|
||||
}
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
_bodyDamping = EditorGUILayout.Toggle("Use Body Damping", script.useBodyDamping);
|
||||
if (_bodyDamping)
|
||||
{
|
||||
_linearDampingCoeff = EditorGUILayout.Slider("Linear Damping Coeff", (float)script.linearDampingCoeff, 0, 1);
|
||||
_angularDampingCoeff = EditorGUILayout.Slider("Angular Damping Coeff", (float)script.angularDampingCoeff, 0, 1);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(script, "Change of Parameters");
|
||||
script.useDistanceConstraint = useDistanceConstraint;
|
||||
script.distanceStiffness = distanceStiffness;
|
||||
script.useBendConstraint = useBendConstraint;
|
||||
script.bendStiffness = bendStiffness;
|
||||
script.maxBendStride = bendStride;
|
||||
script.useDihedralConstraint = useDihedralConstraint;
|
||||
script.dihedralStiffness = dihedralStiffness;
|
||||
script.useAreaConstraint = useAreaConstraint;
|
||||
script.areaStiffness = areaStiffness;
|
||||
script.useVolumeConstraint = useVolumeConstraint;
|
||||
script.volumeStiffness = volumeStiffness;
|
||||
script.useFEMConstraint = useFEMConstraint;
|
||||
script.youngsModulus = youngsModulus;
|
||||
script.possionsRatio = possionsRatio;
|
||||
script.mu = mu;
|
||||
script.lambda = lambda;
|
||||
script.uniformMassValue = uniformMassValue;
|
||||
script.useYoungsModulus = useYoungsModulus;
|
||||
script.materialType = materialType;
|
||||
|
||||
script.useBodyDamping = _bodyDamping;
|
||||
script.linearDampingCoeff = _linearDampingCoeff;
|
||||
script.angularDampingCoeff = _angularDampingCoeff;
|
||||
|
||||
script.visualGeomFilter = visualGeomFilter;
|
||||
script.cleanVisualMesh = _cleanVisualMesh;
|
||||
script.physicsGeomFilter = physicsGeomFilter;
|
||||
script.collisionGeomFilter = collisionGeomFilter;
|
||||
|
||||
script.ignoreGravity = ignoreGravity;
|
||||
}
|
||||
|
||||
base.HandleColliders(script);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9387229fe45d625478e06d841a78066b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,146 @@
|
||||
using ImstkUnity;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
public class DynamicalModelEditor : Editor
|
||||
{
|
||||
bool _collisionsFolded = false;
|
||||
List<DynamicalModel> _allDeformables;
|
||||
|
||||
public DynamicalModelEditor()
|
||||
{
|
||||
EditorApplication.hierarchyChanged += OnHierarchyChanged;
|
||||
}
|
||||
|
||||
~DynamicalModelEditor()
|
||||
{
|
||||
EditorApplication.hierarchyChanged -= OnHierarchyChanged;
|
||||
}
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
}
|
||||
|
||||
private void OnHierarchyChanged()
|
||||
{
|
||||
_allDeformables = (Resources.FindObjectsOfTypeAll(typeof(DynamicalModel)) as DynamicalModel[]).ToList<DynamicalModel>();
|
||||
SimulationManager.Instance().collisions.RemoveAllNull();
|
||||
}
|
||||
|
||||
public void HandleColliders(DynamicalModel script)
|
||||
{
|
||||
if (_allDeformables == null)
|
||||
{
|
||||
OnHierarchyChanged();
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var editorData = DrawColliders(script);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
var simulationManager = SimulationManager.Instance();
|
||||
Undo.RegisterCompleteObjectUndo(simulationManager, "Update Collisions");
|
||||
simulationManager.collisions = editorData;
|
||||
}
|
||||
}
|
||||
|
||||
protected CollisionInteractions DrawColliders(DynamicalModel script)
|
||||
{
|
||||
var allCollisions = SimulationManager.Instance().collisions;
|
||||
var editorData = new CollisionInteractions(allCollisions);
|
||||
|
||||
_collisionsFolded = EditorGUILayout.Foldout(_collisionsFolded, "Colliding Objects");
|
||||
if (_collisionsFolded)
|
||||
{
|
||||
EditorGUILayout.BeginVertical();
|
||||
for (int i = 0; i < _allDeformables.Count; ++i)
|
||||
{
|
||||
var item = _allDeformables[i];
|
||||
if (item == script) continue;
|
||||
EditorGUILayout.BeginVertical();
|
||||
|
||||
// Title line with Toggle
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
var enabled = allCollisions.IsEnabled(script, item);
|
||||
|
||||
var autoType = ImstkUnity.CollisionInteraction.GetCDType(script, item);
|
||||
|
||||
var newEnabled = false;
|
||||
|
||||
EditorGUI.BeginDisabledGroup(autoType == "");
|
||||
newEnabled = EditorGUILayout.Toggle(enabled, GUILayout.Width(20));
|
||||
EditorGUI.EndDisabledGroup();
|
||||
if (enabled != newEnabled)
|
||||
{
|
||||
if (newEnabled)
|
||||
{
|
||||
editorData.Add(script, item);
|
||||
}
|
||||
else
|
||||
{
|
||||
editorData.Remove(script, item);
|
||||
}
|
||||
}
|
||||
EditorGUI.BeginDisabledGroup(!newEnabled && autoType == "");
|
||||
EditorGUILayout.LabelField(item.name);
|
||||
if (autoType == "")
|
||||
{
|
||||
EditorGUILayout.LabelField("No collision type available");
|
||||
}
|
||||
EditorGUI.EndDisabledGroup();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
if (newEnabled)
|
||||
{
|
||||
EditorGUILayout.BeginVertical();
|
||||
var d = editorData.GetData(script, item);
|
||||
|
||||
var _message = "Auto Type: ";
|
||||
if (d.model1 != null && d.model1.GetCollidingGeometry() != null &&
|
||||
d.model2 != null && d.model2.GetCollidingGeometry() != null)
|
||||
{
|
||||
_message += ImstkUnity.CollisionInteraction.GetCDType(d.model1, d.model2);
|
||||
}
|
||||
else
|
||||
{
|
||||
_message += " None ";
|
||||
}
|
||||
EditorGUILayout.LabelField(_message);
|
||||
|
||||
var selected = System.Array.IndexOf(CollisionInteractionEditor.CDOptions, d.collisionTypeName);
|
||||
|
||||
if (selected < 0) selected = 0;
|
||||
|
||||
selected = EditorGUILayout.Popup("Detection Type", selected, CollisionInteractionEditor.CDOptions);
|
||||
d.collisionTypeName = CollisionInteractionEditor.CDOptions[selected];
|
||||
|
||||
d.friction = EditorGUILayout.DoubleField("Friction", d.friction);
|
||||
d.restitution = EditorGUILayout.DoubleField("Restitution", d.restitution);
|
||||
|
||||
var guiContent = new GUIContent("Deform. Stiffness 1", "A good default value is 1/number of iterations from the simulation manager");
|
||||
d.deformableStiffness1 = EditorGUILayout.DoubleField(guiContent, d.deformableStiffness1);
|
||||
|
||||
guiContent = new GUIContent("Deform. Stiffness 2", "A good default value is 1/number of iterations from the simulation manager");
|
||||
d.deformableStiffness2 = EditorGUILayout.DoubleField(guiContent, d.deformableStiffness2);
|
||||
|
||||
d.rigidBodyCompliance = EditorGUILayout.DoubleField("Rigid Compliance", d.rigidBodyCompliance);
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
// Needs to move into the undo section
|
||||
|
||||
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
|
||||
return editorData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8717cb3ee56ae44ba778d9c36370886
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,132 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using ImstkUnity;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
public static class EditorUtils
|
||||
{
|
||||
public static GeometryFilter GeomFilterField(string fieldName, GeometryFilter filter)
|
||||
{
|
||||
return EditorGUILayout.ObjectField(fieldName, filter, typeof(GeometryFilter), true) as GeometryFilter;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all plugins and iMSTKSharp directory ".cs" files. Reinstalls
|
||||
/// from installSourcePath
|
||||
/// </summary>
|
||||
/// <param name="installSourcePath"></param>
|
||||
public static void InstallImstk(string installSourcePath)
|
||||
{
|
||||
// Get the install directory
|
||||
if (installSourcePath.Length != 0)
|
||||
{
|
||||
// First check the directory exists
|
||||
if (!Directory.Exists(installSourcePath))
|
||||
{
|
||||
Debug.LogError("Failed to install imstk, source location does not exist: " + installSourcePath);
|
||||
}
|
||||
// Next check that a file exists to lightly verify we have the right directory
|
||||
if (!Directory.Exists(installSourcePath + "/lib/cmake/iMSTK-5.0") ||
|
||||
!File.Exists(installSourcePath + "/lib/cmake/iMSTK-5.0/iMSTKConfig.cmake"))
|
||||
{
|
||||
Debug.LogError("Could not find relevant files, check the imstk install directory is specified properly: " + installSourcePath);
|
||||
}
|
||||
|
||||
// Determine the directory what this script resides in and therefore the location of
|
||||
// the Plugins directory
|
||||
|
||||
string[] res = System.IO.Directory.GetFiles(Application.dataPath, "EditorUtils.cs", SearchOption.AllDirectories);
|
||||
if (res.Length == 0)
|
||||
{
|
||||
Debug.LogError("Could not find target directory");
|
||||
return;
|
||||
}
|
||||
string dataPath = res[0].Replace("EditorUtils.cs", "").Replace("\\", "/") + "../../";
|
||||
|
||||
// Clear plugins directory and copy all files from bin to plugins
|
||||
ClearFiles(dataPath + "/Plugins/");
|
||||
CopyFiles(installSourcePath + "/bin/", dataPath + "/Plugins/", new string[] { ".dll", ".so" });
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all files at path
|
||||
/// </summary>
|
||||
public static void ClearFiles(string path)
|
||||
{
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] files = Directory.GetFiles(path);
|
||||
|
||||
for (int i = 0; i < files.Length; i++)
|
||||
{
|
||||
File.Delete(files[i]);
|
||||
}
|
||||
|
||||
Directory.Delete(path);
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy all files from srcPath to destPath directory
|
||||
/// </summary>
|
||||
public static void CopyFiles(string srcPath, string destPath, string[] extFilter)
|
||||
{
|
||||
if (!Directory.Exists(srcPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!Directory.Exists(destPath))
|
||||
{
|
||||
Directory.CreateDirectory(destPath);
|
||||
}
|
||||
|
||||
string[] hi = Directory.GetFiles(srcPath);
|
||||
for (int i = 0; i < hi.Length; i++)
|
||||
{
|
||||
string ext = Path.GetExtension(hi[i]);
|
||||
bool validExt = false;
|
||||
for (int j = 0; j < extFilter.Length; j++)
|
||||
{
|
||||
if (ext == extFilter[j])
|
||||
{
|
||||
validExt = true;
|
||||
}
|
||||
}
|
||||
if (validExt)
|
||||
{
|
||||
File.Copy(hi[i], destPath + Path.GetFileName(hi[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f60b332d6af09a04e9fc7bf700b3df3d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,371 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// This class adds menu items for various parts of Unity
|
||||
/// </summary>
|
||||
/// It can also do other things
|
||||
public class GameObjectMenuItems : Editor
|
||||
{
|
||||
[MenuItem("GameObject/iMSTK/SimulationManager")]
|
||||
[MenuItem("CONTEXT/iMSTK/SimulationManager")]
|
||||
[MenuItem("iMSTK/GameObject/SimulationManager")]
|
||||
private static void CreateSimulationManagerGameObject()
|
||||
{
|
||||
GameObject newObj = new GameObject("SimulationManager");
|
||||
newObj.AddComponent(typeof(SimulationManager));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a GameObject with a Deformable and Tet cube
|
||||
/// </summary>
|
||||
[MenuItem("GameObject/iMSTK/Deformables/Cube")]
|
||||
[MenuItem("CONTEXT/iMSTK/Deformables/Cube")]
|
||||
[MenuItem("iMSTK/GameObject/Deformables/Cube")]
|
||||
private static void CreateDeformableVolume()
|
||||
{
|
||||
GameObject newObj = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
newObj.name = "Cube";
|
||||
DestroyImmediate(newObj.GetComponent<Collider>());
|
||||
|
||||
Deformable model = newObj.AddComponent<Deformable>();
|
||||
model.useDistanceConstraint = false;
|
||||
model.useAreaConstraint = false;
|
||||
model.useDihedralConstraint = false;
|
||||
model.useVolumeConstraint = false;
|
||||
model.useFEMConstraint = true;
|
||||
model.viscousDampingCoeff = 0.01;
|
||||
|
||||
ImstkMesh tetCubeMesh = Utility.GetTetCubeMesh();
|
||||
Imstk.TetrahedralMesh imstkTetMesh = tetCubeMesh.ToImstkGeometry() as Imstk.TetrahedralMesh;
|
||||
ImstkMesh surfMesh = imstkTetMesh.extractSurfaceMesh().ToImstkMesh();
|
||||
surfMesh.name = tetCubeMesh.name + "_surface";
|
||||
|
||||
MeshFilter meshFilter = newObj.GetComponent<MeshFilter>();
|
||||
meshFilter.sharedMesh = surfMesh.ToMesh();
|
||||
GeometryFilter visualGeom = newObj.AddComponent<GeometryFilter>();
|
||||
visualGeom.SetGeometry(meshFilter.sharedMesh);
|
||||
visualGeom.showHandles = false;
|
||||
GeometryFilter physicsGeom = newObj.AddComponent<GeometryFilter>();
|
||||
physicsGeom.SetGeometry(tetCubeMesh);
|
||||
physicsGeom.showHandles = false;
|
||||
|
||||
model.visualGeomFilter = visualGeom;
|
||||
model.physicsGeomFilter = physicsGeom;
|
||||
model.collisionGeomFilter = visualGeom;
|
||||
|
||||
DeformableMap map = newObj.AddComponent<DeformableMap>();
|
||||
map.parentGeom = physicsGeom;
|
||||
map.childGeom = visualGeom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a GameObject with a Deformable and a Plane
|
||||
/// </summary>
|
||||
[MenuItem("GameObject/iMSTK/Deformables/Cloth")]
|
||||
[MenuItem("CONTEXT/iMSTK/Deformables/Cloth")]
|
||||
[MenuItem("iMSTK/GameObject/Deformables/Cloth")]
|
||||
private static void CreatePbdCloth()
|
||||
{
|
||||
GameObject newObj = GameObject.CreatePrimitive(PrimitiveType.Plane);
|
||||
newObj.name = "Cloth";
|
||||
DestroyImmediate(newObj.GetComponent<Collider>());
|
||||
|
||||
Deformable model = newObj.AddComponent<Deformable>();
|
||||
model.useDistanceConstraint = true;
|
||||
model.useDihedralConstraint = true;
|
||||
model.useAreaConstraint = false;
|
||||
model.useVolumeConstraint = false;
|
||||
model.useFEMConstraint = false;
|
||||
model.distanceStiffness = 100.0;
|
||||
model.dihedralStiffness = 10.0;
|
||||
model.viscousDampingCoeff = 0.01;
|
||||
model.uniformMassValue = 0.05;
|
||||
|
||||
ImstkMesh mesh = Utility.GetXYPlane(19, 19);
|
||||
MeshFilter meshFilter = newObj.GetComponent<MeshFilter>();
|
||||
meshFilter.sharedMesh = mesh.ToMesh();
|
||||
GeometryFilter visualGeom = newObj.AddComponent<GeometryFilter>();
|
||||
visualGeom.SetGeometry(meshFilter.sharedMesh);
|
||||
visualGeom.showHandles = false;
|
||||
|
||||
model.visualGeomFilter = visualGeom;
|
||||
model.physicsGeomFilter = visualGeom;
|
||||
model.collisionGeomFilter = visualGeom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a GameObject with a Deformable and tetrahedral grid
|
||||
/// </summary>
|
||||
[MenuItem("GameObject/iMSTK/Deformables/Subdivided Cube")]
|
||||
[MenuItem("CONTEXT/iMSTK/Deformables/Subdivided Cube")]
|
||||
[MenuItem("iMSTK/GameObject/Deformables/Subdivided Cube")]
|
||||
private static void CreatePbdGridVolume()
|
||||
{
|
||||
GameObject newObj = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
newObj.name = "Cube";
|
||||
DestroyImmediate(newObj.GetComponent<Collider>());
|
||||
|
||||
// Add PbdModel to the object
|
||||
Deformable model = newObj.AddComponent<Deformable>();
|
||||
model.useDistanceConstraint = false;
|
||||
model.useAreaConstraint = false;
|
||||
model.useDihedralConstraint = false;
|
||||
model.useVolumeConstraint = false;
|
||||
model.useFEMConstraint = true;
|
||||
model.viscousDampingCoeff = 0.01;
|
||||
model.youngsModulus = 5000.0;
|
||||
model.possionsRatio = 0.4;
|
||||
model.materialType = Imstk.PbdFemConstraint.MaterialType.StVK;
|
||||
|
||||
// Create a new mesh, store the old one
|
||||
MeshFilter meshFilter = newObj.GetComponentOrCreate<MeshFilter>();
|
||||
Mesh inputMesh = meshFilter.sharedMesh;
|
||||
meshFilter.sharedMesh = new Mesh();
|
||||
meshFilter.sharedMesh.name = inputMesh.name;
|
||||
|
||||
// Create a new tet geometry
|
||||
GeometryFilter physicsGeom = newObj.AddComponent<GeometryFilter>();
|
||||
ImstkMesh tetMesh = ScriptableObject.CreateInstance<ImstkMesh>();
|
||||
tetMesh.geomType = GeometryType.TetrahedralMesh;
|
||||
physicsGeom.SetGeometry(tetMesh);
|
||||
physicsGeom.showHandles = false;
|
||||
|
||||
GeometryFilter visualGeom = newObj.AddComponent<GeometryFilter>();
|
||||
visualGeom.SetGeometry(meshFilter.sharedMesh);
|
||||
visualGeom.showHandles = false;
|
||||
|
||||
model.visualGeomFilter = visualGeom;
|
||||
model.physicsGeomFilter = physicsGeom;
|
||||
model.collisionGeomFilter = visualGeom;
|
||||
|
||||
DeformableMap map = newObj.AddComponent<DeformableMap>();
|
||||
map.parentGeom = physicsGeom;
|
||||
map.childGeom = visualGeom;
|
||||
|
||||
// Use editor to add fill geometries
|
||||
TetrahedralGridEditor.Init(meshFilter.sharedMesh, physicsGeom.inputImstkGeom as ImstkMesh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a GameObject with a Deformable and line mesh
|
||||
/// </summary>
|
||||
[MenuItem("GameObject/iMSTK/Deformables/Thread")]
|
||||
[MenuItem("CONTEXT/iMSTK/Deformables/Thread")]
|
||||
[MenuItem("iMSTK/GameObject/Deformables/Thread")]
|
||||
private static void CreatePbdThread()
|
||||
{
|
||||
GameObject newObj = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
newObj.name = "PbdThread";
|
||||
DestroyImmediate(newObj.GetComponent<Collider>());
|
||||
|
||||
// Add PbdModel to the object
|
||||
Deformable model = newObj.AddComponent<Deformable>();
|
||||
model.useDistanceConstraint = true;
|
||||
model.useBendConstraint = true;
|
||||
model.useAreaConstraint = false;
|
||||
model.useDihedralConstraint = false;
|
||||
model.useVolumeConstraint = false;
|
||||
model.useFEMConstraint = false;
|
||||
model.viscousDampingCoeff = 0.01;
|
||||
model.distanceStiffness = 100.0;
|
||||
model.bendStiffness = 100.0;
|
||||
model.maxBendStride = 3;
|
||||
|
||||
// Create a new mesh, store the old one
|
||||
MeshFilter meshFilter = newObj.GetComponentOrCreate<MeshFilter>();
|
||||
Mesh inputMesh = meshFilter.sharedMesh;
|
||||
inputMesh.name = "LineMesh";
|
||||
meshFilter.sharedMesh = new Mesh();
|
||||
meshFilter.sharedMesh.name = inputMesh.name;
|
||||
|
||||
GeometryFilter visualGeom = newObj.AddComponent<GeometryFilter>();
|
||||
visualGeom.SetGeometry(meshFilter.sharedMesh);
|
||||
visualGeom.showHandles = false;
|
||||
|
||||
model.visualGeomFilter = visualGeom;
|
||||
model.physicsGeomFilter = visualGeom;
|
||||
model.collisionGeomFilter = visualGeom;
|
||||
|
||||
// Use editor to add fill geometries
|
||||
LineMeshEditor.Init(meshFilter.sharedMesh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a GameObject with a RbdModel and sphere
|
||||
/// </summary>
|
||||
[MenuItem("GameObject/iMSTK/Rigids/Sphere")]
|
||||
[MenuItem("CONTEXT/iMSTK/Rigids/Sphere")]
|
||||
[MenuItem("iMSTK/GameObject/Rigids/Sphere")]
|
||||
private static void CreateRigidSphere()
|
||||
{
|
||||
GameObject newObj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||||
newObj.name = "Rigid Sphere";
|
||||
DestroyImmediate(newObj.GetComponent<Collider>());
|
||||
|
||||
// Add PbdModel to the object
|
||||
Rigid model = newObj.AddComponent<Rigid>();
|
||||
model.mass = 1.0;
|
||||
model.inertia = new Vector3[]
|
||||
{
|
||||
new Vector3(1.0f, 0.0f, 0.0f),
|
||||
new Vector3(0.0f, 1.0f, 0.0f),
|
||||
new Vector3(0.0f, 0.0f, 1.0f)
|
||||
};
|
||||
|
||||
// Create a new mesh, store the old one
|
||||
MeshFilter meshFilter = newObj.GetComponentOrCreate<MeshFilter>();
|
||||
GeometryFilter visualGeom = newObj.AddComponent<GeometryFilter>();
|
||||
visualGeom.SetGeometry(meshFilter.sharedMesh);
|
||||
visualGeom.showHandles = false;
|
||||
|
||||
Sphere sphere = CreateInstance<Sphere>();
|
||||
sphere.radius = 0.5f;
|
||||
sphere.center = Vector3.zero;
|
||||
GeometryFilter collisionGeom = newObj.AddComponent<GeometryFilter>();
|
||||
collisionGeom.SetGeometry(sphere);
|
||||
|
||||
model.visualGeomFilter = visualGeom;
|
||||
model.physicsGeomFilter = collisionGeom;
|
||||
model.collisionGeomFilter = collisionGeom;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a GameObject with an OpenHapticsDevice
|
||||
/// </summary>
|
||||
[MenuItem("GameObject/iMSTK/Devices/OpenHapticsDevice")]
|
||||
[MenuItem("CONTEXT/iMSTK/Devices/OpenHapticsDevice")]
|
||||
[MenuItem("iMSTK/GameObject/Devices/OpenHapticsDevice")]
|
||||
private static void CreateOpenHapticsDevice()
|
||||
{
|
||||
GameObject newObj = new GameObject("OpenHapticsDevice");
|
||||
newObj.AddComponent(typeof(OpenHapticsDevice));
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MenuItem("GameObject/iMSTK/Static Objects/Line")]
|
||||
[MenuItem("CONTEXT/iMSTK/Static Objects/Line")]
|
||||
[MenuItem("iMSTK/GameObject/Static Objects/Line")]
|
||||
private static void CreateLineStaticObject()
|
||||
{
|
||||
GameObject newObj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||||
newObj.name = "StaticLineObject";
|
||||
DestroyImmediate(newObj.GetComponent<Collider>());
|
||||
|
||||
StaticModel model = newObj.AddComponent<StaticModel>();
|
||||
|
||||
ImstkMesh mesh = ScriptableObject.CreateInstance<ImstkMesh>();
|
||||
mesh.geomType = GeometryType.LineMesh;
|
||||
mesh.vertices = new Vector3[] { new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f) };
|
||||
mesh.indices = new int[] { 0, 1 };
|
||||
MeshFilter meshFilter = newObj.GetComponent<MeshFilter>();
|
||||
meshFilter.sharedMesh = mesh.ToMesh();
|
||||
meshFilter.sharedMesh.name = "LineMesh";
|
||||
|
||||
GeometryFilter collisionGeom = newObj.AddComponent<GeometryFilter>();
|
||||
collisionGeom.SetGeometry(meshFilter.sharedMesh);
|
||||
model.collisionGeomFilter = collisionGeom;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/iMSTK/Static Objects/Sphere")]
|
||||
[MenuItem("CONTEXT/iMSTK/Static Objects/Sphere")]
|
||||
[MenuItem("iMSTK/GameObject/Static Objects/Sphere")]
|
||||
private static void CreateSphereStaticObject()
|
||||
{
|
||||
GameObject newObj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
|
||||
newObj.name = "Static Sphere";
|
||||
DestroyImmediate(newObj.GetComponent<Collider>());
|
||||
|
||||
StaticModel model = newObj.AddComponent<StaticModel>();
|
||||
|
||||
Sphere sphere = new Sphere();
|
||||
|
||||
GeometryFilter collisionGeom = newObj.AddComponent<GeometryFilter>();
|
||||
collisionGeom.SetGeometry(sphere);
|
||||
model.collisionGeomFilter = collisionGeom;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/iMSTK/Static Objects/Capsule")]
|
||||
[MenuItem("CONTEXT/iMSTK/Static Objects/Capsule")]
|
||||
[MenuItem("iMSTK/GameObject/Static Objects/Capsule")]
|
||||
private static void CreateCapsuleStaticObject()
|
||||
{
|
||||
GameObject newObj = GameObject.CreatePrimitive(PrimitiveType.Capsule);
|
||||
newObj.name = "Static Capsule";
|
||||
DestroyImmediate(newObj.GetComponent<Collider>());
|
||||
|
||||
StaticModel model = newObj.AddComponent<StaticModel>();
|
||||
|
||||
Capsule capsule = new Capsule();
|
||||
|
||||
GeometryFilter collisionGeom = newObj.AddComponent<GeometryFilter>();
|
||||
collisionGeom.SetGeometry(capsule);
|
||||
model.collisionGeomFilter = collisionGeom;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/iMSTK/Static Objects/Oriented Box")]
|
||||
[MenuItem("CONTEXT/iMSTK/Static Objects/Oriented Box")]
|
||||
[MenuItem("iMSTK/GameObject/Static Objects/Oriented Box")]
|
||||
private static void CreateOrientedBoxStaticObject()
|
||||
{
|
||||
GameObject newObj = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
newObj.name = "StaticOrientedBoxObject";
|
||||
DestroyImmediate(newObj.GetComponent<Collider>());
|
||||
|
||||
StaticModel model = newObj.AddComponent<StaticModel>();
|
||||
|
||||
OrientedBox obb = new OrientedBox();
|
||||
|
||||
GeometryFilter collisionGeom = newObj.AddComponent<GeometryFilter>();
|
||||
collisionGeom.SetGeometry(obb);
|
||||
model.collisionGeomFilter = collisionGeom;
|
||||
}
|
||||
|
||||
[MenuItem("GameObject/iMSTK/Static Objects/Plane")]
|
||||
[MenuItem("CONTEXT/iMSTK/Static Objects/Plane")]
|
||||
[MenuItem("iMSTK/GameObject/Static Objects/Plane")]
|
||||
private static void CreatePlaneStaticObject()
|
||||
{
|
||||
GameObject newObj = GameObject.CreatePrimitive(PrimitiveType.Plane);
|
||||
newObj.name = "StaticPlaneObject";
|
||||
DestroyImmediate(newObj.GetComponent<Collider>());
|
||||
|
||||
StaticModel model = newObj.AddComponent<StaticModel>();
|
||||
|
||||
ImstkUnity.Plane plane = new ImstkUnity.Plane();
|
||||
plane.visualWidth = 5.1f;
|
||||
|
||||
GeometryFilter collisionGeom = newObj.AddComponent<GeometryFilter>();
|
||||
collisionGeom.SetGeometry(plane);
|
||||
model.collisionGeomFilter = collisionGeom;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bafd05c20034eca4081b3d878dd89662
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,115 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
/// <summary>
|
||||
/// Editor for the asset, most commonly shown when selecting the asset in
|
||||
/// the project explorer
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(Geometry), true)]
|
||||
class GeometryEditor : Editor
|
||||
{
|
||||
private PreviewRenderUtility m_PreviewUtility = null;
|
||||
private Material previewMaterial = null;
|
||||
private Mesh previewMesh = null;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
// Check the config file toggle for change
|
||||
Geometry asset = target as Geometry;
|
||||
if (asset.IsMesh)
|
||||
{
|
||||
ImstkMesh mesh = asset as ImstkMesh;
|
||||
GUILayout.Label("Vertex Count: " + mesh.vertices.Length);
|
||||
GUILayout.Label("Index Count: " + mesh.indices.Length);
|
||||
GUILayout.Label("Cell Count: " + mesh.indices.Length / ImstkMesh.typeToNumPts[mesh.geomType]);
|
||||
}
|
||||
GUILayout.Label("Geom Type: " + asset.geomType.ToString());
|
||||
}
|
||||
|
||||
public override bool HasPreviewGUI() { return true; }
|
||||
|
||||
public override GUIContent GetPreviewTitle() { return new GUIContent(target.name); }
|
||||
|
||||
public override void OnPreviewGUI(Rect r, GUIStyle background)
|
||||
{
|
||||
Geometry asset = target as Geometry;
|
||||
// Preview only works with meshes
|
||||
if (!asset.IsMesh)
|
||||
return;
|
||||
ImstkMesh imstkMesh = asset as ImstkMesh;
|
||||
|
||||
if (m_PreviewUtility == null)
|
||||
{
|
||||
m_PreviewUtility = new PreviewRenderUtility();
|
||||
previewMaterial = new Material(Shader.Find("Diffuse"));
|
||||
|
||||
// If a tet or hex mesh extract surface for display (we could use some other method to better indicate
|
||||
// that this is a tet mesh)
|
||||
if (asset.IsVolume)
|
||||
{
|
||||
// Extract the surface mesh for display
|
||||
Imstk.TetrahedralMesh tetMesh = Imstk.Utils.CastTo<Imstk.TetrahedralMesh>(imstkMesh.ToPointSet());
|
||||
Imstk.SurfaceMesh surfMesh = tetMesh.extractSurfaceMesh();
|
||||
previewMesh = surfMesh.ToMesh();
|
||||
}
|
||||
}
|
||||
|
||||
if (Event.current.type != EventType.Repaint)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Camera camera = m_PreviewUtility.camera;
|
||||
float size = previewMesh.bounds.size.magnitude;
|
||||
Vector3 center = previewMesh.bounds.center;
|
||||
camera.transform.position = center + new Vector3(0.0f, size * 2.0f, -size * 2.0f);
|
||||
camera.transform.LookAt(center);
|
||||
camera.farClipPlane = 300.0f;
|
||||
|
||||
m_PreviewUtility.BeginPreview(r, background);
|
||||
m_PreviewUtility.DrawMesh(previewMesh, Matrix4x4.identity, previewMaterial, 0);
|
||||
|
||||
bool fog = RenderSettings.fog;
|
||||
Unsupported.SetRenderSettingsUseFogNoDirty(false);
|
||||
m_PreviewUtility.camera.Render();
|
||||
Unsupported.SetRenderSettingsUseFogNoDirty(fog);
|
||||
|
||||
Texture texture = m_PreviewUtility.EndPreview();
|
||||
GUI.DrawTexture(r, texture, ScaleMode.StretchToFill, false);
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
previewMaterial = null;
|
||||
previewMesh = null;
|
||||
|
||||
if (m_PreviewUtility != null)
|
||||
{
|
||||
m_PreviewUtility.Cleanup();
|
||||
m_PreviewUtility = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73289ab03e7c85b418a57465a634e813
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe4d6df5f481eb2478ab3cf67d3ac5f8
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,98 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Laplacian smoothens an input unity Mesh providing
|
||||
/// an output one
|
||||
/// </summary>
|
||||
public class LaplaceSmoothEditor : EditorWindow
|
||||
{
|
||||
public int numIterations = 20;
|
||||
public double relaxationFactor = 0.01;
|
||||
public double convergence = 0.0;
|
||||
public double featureAngle = 45.0;
|
||||
public double edgeAngle = 15.0;
|
||||
public bool featureEdgeSmoothing = false;
|
||||
public bool boundarySmoothing = true;
|
||||
public Mesh inputMesh = null;
|
||||
public Mesh outputMesh = null;
|
||||
|
||||
public static void Init(Mesh inputMesh, Mesh outputMesh)
|
||||
{
|
||||
LaplaceSmoothEditor window = GetWindow(typeof(LaplaceSmoothEditor)) as LaplaceSmoothEditor;
|
||||
window.inputMesh = inputMesh;
|
||||
window.outputMesh = outputMesh;
|
||||
window.UpdateEditorResults();
|
||||
window.Show();
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
inputMesh = EditorGUILayout.ObjectField("Input Mesh: ", inputMesh, typeof(Mesh), true) as Mesh;
|
||||
int tNumIterations = EditorGUILayout.IntField("Number Of Smoothing Iterations: ", numIterations);
|
||||
double tRelaxationFactor = EditorGUILayout.DoubleField("Relaxation Factor: ", relaxationFactor);
|
||||
double tConvergence = EditorGUILayout.DoubleField("Convergence: ", convergence);
|
||||
double tFeatureAngle = EditorGUILayout.DoubleField("Feature Angle: ", featureAngle);
|
||||
double tEdgeAngle = EditorGUILayout.DoubleField("Edge Angle: ", edgeAngle);
|
||||
bool tFeatureEdgeSmoothing = EditorGUILayout.Toggle("Use Feature Edge Smoothing: ", featureEdgeSmoothing);
|
||||
bool tBoundarySmoothing = EditorGUILayout.Toggle("Use Boundary Smoothing: ", boundarySmoothing);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(this, "Change of Parameters");
|
||||
numIterations = MathUtil.Max(tNumIterations, 1);
|
||||
relaxationFactor = MathUtil.Max(tRelaxationFactor, 0.0);
|
||||
convergence = MathUtil.Max(tConvergence, 0.0);
|
||||
featureAngle = MathUtil.Max(tFeatureAngle, 0.0);
|
||||
edgeAngle = MathUtil.Max(tEdgeAngle, 0.0);
|
||||
featureEdgeSmoothing = tFeatureEdgeSmoothing;
|
||||
boundarySmoothing = tBoundarySmoothing;
|
||||
|
||||
UpdateEditorResults();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEditorResults()
|
||||
{
|
||||
Imstk.SurfaceMesh surfMesh = inputMesh.ToImstkGeometry() as Imstk.SurfaceMesh;
|
||||
|
||||
Imstk.SurfaceMeshSmoothen smoothen = new Imstk.SurfaceMeshSmoothen();
|
||||
smoothen.setInputMesh(surfMesh);
|
||||
smoothen.setNumberOfIterations(numIterations);
|
||||
smoothen.setRelaxationFactor(relaxationFactor);
|
||||
smoothen.setConvergence(convergence);
|
||||
smoothen.setFeatureAngle(featureAngle);
|
||||
smoothen.setEdgeAngle(edgeAngle);
|
||||
smoothen.setFeatureEdgeSmoothing(featureEdgeSmoothing);
|
||||
smoothen.setBoundarySmoothing(boundarySmoothing);
|
||||
smoothen.update();
|
||||
|
||||
Imstk.SurfaceMesh outputSurfMesh = Imstk.Utils.CastTo<Imstk.SurfaceMesh>(smoothen.getOutput());
|
||||
GeomUtil.CopyMesh(outputSurfMesh.ToMesh(), outputMesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ea044bfac569c644b427c75bffa1bd8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,102 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates a plane mesh for MeshFilter
|
||||
/// </summary>
|
||||
public class LineMeshEditor : EditorWindow
|
||||
{
|
||||
public Vector3 start = Vector3.zero;
|
||||
public Vector3 direction = new Vector3(1.0f, 0.0f, 0.0f);
|
||||
public int divisions = 10;
|
||||
public double length = 1.0;
|
||||
public Mesh outputMesh = null;
|
||||
|
||||
public static void Init(Mesh outputMesh)
|
||||
{
|
||||
LineMeshEditor window = GetWindow(typeof(LineMeshEditor)) as LineMeshEditor;
|
||||
window.outputMesh = outputMesh;
|
||||
window.UpdateEditorResults();
|
||||
window.Show();
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
outputMesh = EditorGUILayout.ObjectField("Input Mesh: ", outputMesh, typeof(Mesh), true) as Mesh;
|
||||
Vector3 tStart = EditorGUILayout.Vector3Field("Start", start);
|
||||
Vector3 tDirection = EditorGUILayout.Vector3Field("Direction", direction);
|
||||
int tDivisions = EditorGUILayout.IntField("Divisions", divisions);
|
||||
double tLength = EditorGUILayout.DoubleField("Length", length);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(this, "Change of Parameters");
|
||||
start = tStart;
|
||||
direction = tDirection;
|
||||
if (direction == Vector3.zero)
|
||||
{
|
||||
direction = new Vector3(1.0f, 0.0f, 0.0f);
|
||||
}
|
||||
divisions = Mathf.Max(tDivisions, 1);
|
||||
length = MathUtil.Max(tLength, 0.0);
|
||||
|
||||
UpdateEditorResults();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEditorResults()
|
||||
{
|
||||
int numVerts = divisions + 1;
|
||||
int numCells = divisions;
|
||||
|
||||
Vector3[] vertices = new Vector3[numVerts];
|
||||
int[] indices = new int[numCells * 2];
|
||||
|
||||
direction = direction.normalized;
|
||||
for (int i = 0; i < numVerts; i++)
|
||||
{
|
||||
float t = (float)i / (numVerts - 1); // 0-1
|
||||
vertices[i] = start + direction * t * (float)length;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numCells; i++)
|
||||
{
|
||||
indices[i * 2] = i;
|
||||
indices[i * 2 + 1] = i + 1;
|
||||
}
|
||||
|
||||
outputMesh.triangles = null;
|
||||
outputMesh.normals = null;
|
||||
outputMesh.tangents = null;
|
||||
|
||||
outputMesh.vertices = vertices;
|
||||
outputMesh.SetIndices(indices, MeshTopology.Lines, 0);
|
||||
|
||||
outputMesh.RecalculateBounds();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33c64bf93157c484abdc881055be248f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,73 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates a plane mesh for MeshFilter
|
||||
/// </summary>
|
||||
public class PlaneMeshEditor : EditorWindow
|
||||
{
|
||||
//public Vector3 size = new Vector3(1.0f, 0.25f, 1.0f);
|
||||
public Vector2Int dim = new Vector2Int(8, 8);
|
||||
//public Vector3 center = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
public Mesh outputMesh = null;
|
||||
|
||||
public static void Init(Mesh outputMesh)
|
||||
{
|
||||
PlaneMeshEditor window = GetWindow(typeof(PlaneMeshEditor)) as PlaneMeshEditor;
|
||||
window.outputMesh = outputMesh;
|
||||
if (outputMesh.name.Length == 0) outputMesh.name = "plane mesh";
|
||||
window.UpdateEditorResults();
|
||||
window.Show();
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
outputMesh = EditorGUILayout.ObjectField("Input Mesh: ", outputMesh, typeof(Mesh), true) as Mesh;
|
||||
name = EditorGUILayout.TextField("Name: ", outputMesh.name);
|
||||
//Vector3 tSize = EditorGUILayout.Vector3Field("Size: ", size);
|
||||
Vector2Int tDim = EditorGUILayout.Vector2IntField("Grid Dimensions: ", dim);
|
||||
//Vector3 tCenter = EditorGUILayout.Vector3Field("Center: ", center);
|
||||
|
||||
// \todo: How to get undo to also call UpdateInputObj?
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(this, "Change of Parameters");
|
||||
//size = tSize.cwiseMax(new Vector3(0.0f, 0.0f, 0.0f));
|
||||
dim = tDim.cwiseMax(new Vector2Int(2, 2));
|
||||
//center = tCenter;
|
||||
outputMesh.name = name;
|
||||
UpdateEditorResults();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEditorResults()
|
||||
{
|
||||
ImstkMesh planeMesh = Utility.GetXYPlane(dim.x, dim.y);
|
||||
GeomUtil.CopyMesh(planeMesh.ToMesh(), outputMesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe3bffa442f54d04ea8dcec7b28e5535
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,86 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
public enum SubdivideMeshType
|
||||
{
|
||||
Linear,
|
||||
Loop,
|
||||
Butterfly
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Laplacian smoothens an input unity Mesh providing
|
||||
/// an output one
|
||||
/// </summary>
|
||||
public class SubdivideMeshEditor : EditorWindow
|
||||
{
|
||||
public int numSubdivisions = 1;
|
||||
public Imstk.SurfaceMeshSubdivide.Type subdivType = Imstk.SurfaceMeshSubdivide.Type.LINEAR;
|
||||
public Mesh inputMesh = null;
|
||||
public Mesh outputMesh = null;
|
||||
|
||||
public static void Init(Mesh inputMesh, Mesh outputMesh)
|
||||
{
|
||||
SubdivideMeshEditor window = GetWindow(typeof(SubdivideMeshEditor)) as SubdivideMeshEditor;
|
||||
window.inputMesh = inputMesh;
|
||||
window.outputMesh = outputMesh;
|
||||
window.UpdateEditorResults();
|
||||
window.Show();
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
inputMesh = EditorGUILayout.ObjectField("Input Mesh: ", inputMesh, typeof(Mesh), true) as Mesh;
|
||||
int tNumSubdivisions = EditorGUILayout.IntField("Number Of Subdivisions: ", numSubdivisions);
|
||||
Imstk.SurfaceMeshSubdivide.Type tSubdivType =
|
||||
(Imstk.SurfaceMeshSubdivide.Type)EditorGUILayout.EnumPopup("Subdivision Type: ", subdivType);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(this, "Change of Parameters");
|
||||
numSubdivisions = MathUtil.Max(tNumSubdivisions, 0);
|
||||
subdivType = tSubdivType;
|
||||
|
||||
UpdateEditorResults();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEditorResults()
|
||||
{
|
||||
Imstk.SurfaceMesh surfMesh = inputMesh.ToImstkGeometry() as Imstk.SurfaceMesh;
|
||||
|
||||
Imstk.SurfaceMeshSubdivide subdiv = new Imstk.SurfaceMeshSubdivide();
|
||||
subdiv.setInputMesh(surfMesh);
|
||||
subdiv.setNumberOfSubdivisions(numSubdivisions);
|
||||
subdiv.setSubdivisionType(subdivType);
|
||||
subdiv.update();
|
||||
|
||||
Imstk.SurfaceMesh outputSurfMesh = Imstk.Utils.CastTo<Imstk.SurfaceMesh>(subdiv.getOutput());
|
||||
GeomUtil.CopyMesh(outputSurfMesh.ToMesh(), outputMesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b8962d5e32621842895493399fea036
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,80 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates a tetrahedral mesh PhysicsGeometry
|
||||
/// </summary>
|
||||
public class TetrahedralGridEditor : EditorWindow
|
||||
{
|
||||
public Vector3 size = new Vector3(1.0f, 0.25f, 1.0f);
|
||||
public Vector3Int dim = new Vector3Int(8, 4, 8);
|
||||
public Vector3 center = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
public Mesh outputSurfMesh = null;
|
||||
public ImstkMesh outputTetMesh = null;
|
||||
|
||||
public static void Init(
|
||||
Mesh outputSurfMesh,
|
||||
ImstkMesh outputTetMesh)
|
||||
{
|
||||
TetrahedralGridEditor window = GetWindow(typeof(TetrahedralGridEditor)) as TetrahedralGridEditor;
|
||||
window.outputSurfMesh = outputSurfMesh;
|
||||
window.outputTetMesh = outputTetMesh;
|
||||
window.UpdateEditorResults();
|
||||
window.Show();
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
outputSurfMesh = EditorGUILayout.ObjectField("Input Surface MeshFilter: ", outputSurfMesh, typeof(Mesh), true) as Mesh;
|
||||
outputTetMesh = EditorGUILayout.ObjectField("Input Tet GeometryFilter: ", outputTetMesh, typeof(ImstkMesh), true) as ImstkMesh;
|
||||
Vector3 tSize = EditorGUILayout.Vector3Field("Size: ", size);
|
||||
Vector3Int tDim = EditorGUILayout.Vector3IntField("Grid Dimensions: ", dim);
|
||||
Vector3 tCenter = EditorGUILayout.Vector3Field("Center: ", center);
|
||||
|
||||
// \todo: How to get undo to also call UpdateInputObj?
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(this, "Change of Parameters");
|
||||
size = tSize.cwiseMax(new Vector3(0.0f, 0.0f, 0.0f));
|
||||
dim = tDim.cwiseMax(new Vector3Int(2, 2, 2));
|
||||
center = tCenter;
|
||||
|
||||
UpdateEditorResults();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEditorResults()
|
||||
{
|
||||
ImstkMesh tetMesh = Utility.GetTetGridMesh(size, dim, center);
|
||||
GeomUtil.CopyMesh(tetMesh, outputTetMesh);
|
||||
|
||||
Imstk.TetrahedralMesh imstkTetMesh = Imstk.Utils.CastTo<Imstk.TetrahedralMesh>(tetMesh.ToImstkGeometry());
|
||||
Imstk.SurfaceMesh surfMesh = imstkTetMesh.extractSurfaceMesh();
|
||||
GeomUtil.CopyMesh(surfMesh.ToMesh(), outputSurfMesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f18b03d2fbaf8448913420009e4e51e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,132 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
public enum UVPlaneOptions
|
||||
{
|
||||
XY,
|
||||
YZ,
|
||||
XZ,
|
||||
Custom
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates UV plane coords
|
||||
/// </summary>
|
||||
public class UVPlaneProjectEditor : EditorWindow
|
||||
{
|
||||
public Vector3 planeNormal = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
public UVPlaneOptions planeOption = UVPlaneOptions.XZ;
|
||||
public Vector2 uvScale = new Vector2(1.0f, 1.0f);
|
||||
public Vector2 uvShift = Vector2.zero;
|
||||
public Mesh inputMesh = null;
|
||||
public Mesh outputMesh = null;
|
||||
|
||||
public static void Init(Mesh inputMesh, Mesh outputMesh)
|
||||
{
|
||||
UVPlaneProjectEditor window = GetWindow(typeof(UVPlaneProjectEditor)) as UVPlaneProjectEditor;
|
||||
window.inputMesh = inputMesh;
|
||||
window.outputMesh = outputMesh;
|
||||
window.UpdateEditorResults();
|
||||
window.Show();
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
inputMesh = EditorGUILayout.ObjectField("Input Mesh: ", inputMesh, typeof(Mesh), true) as Mesh;
|
||||
Vector3 tPlaneNormal = EditorGUILayout.Vector3Field("Plane Normal: ", planeNormal);
|
||||
UVPlaneOptions tPlaneOption = (UVPlaneOptions)EditorGUILayout.EnumPopup("Plane: ", planeOption);
|
||||
Vector2 tUvScale = EditorGUILayout.Vector2Field("UV Scale", uvScale);
|
||||
Vector2 tUvShift = EditorGUILayout.Vector2Field("UV Shift", uvShift);
|
||||
|
||||
// \todo: How to get undo to also call UpdateInputObj?
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(this, "Change of Parameters");
|
||||
|
||||
// IF the plane normal was changed
|
||||
if (tPlaneNormal != planeNormal)
|
||||
{
|
||||
if (tPlaneNormal == new Vector3(0.0f, 1.0f, 0.0f))
|
||||
{
|
||||
tPlaneOption = UVPlaneOptions.XZ;
|
||||
}
|
||||
else if (tPlaneNormal == new Vector3(1.0f, 0.0f, 0.0f))
|
||||
{
|
||||
tPlaneOption = UVPlaneOptions.YZ;
|
||||
}
|
||||
else if (tPlaneNormal == new Vector3(0.0f, 0.0f, 1.0f))
|
||||
{
|
||||
tPlaneOption = UVPlaneOptions.XY;
|
||||
}
|
||||
else
|
||||
{
|
||||
tPlaneOption = UVPlaneOptions.Custom;
|
||||
}
|
||||
}
|
||||
if (tPlaneOption != planeOption)
|
||||
{
|
||||
if (tPlaneOption == UVPlaneOptions.XY)
|
||||
{
|
||||
tPlaneNormal = new Vector3(0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
else if (tPlaneOption == UVPlaneOptions.XZ)
|
||||
{
|
||||
tPlaneNormal = new Vector3(0.0f, 1.0f, 0.0f);
|
||||
}
|
||||
else if (tPlaneOption == UVPlaneOptions.YZ)
|
||||
{
|
||||
tPlaneNormal = new Vector3(1.0f, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
planeNormal = tPlaneNormal;
|
||||
planeOption = tPlaneOption;
|
||||
uvScale = tUvScale;
|
||||
uvShift = tUvShift;
|
||||
|
||||
UpdateEditorResults();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEditorResults()
|
||||
{
|
||||
GeomUtil.CopyMesh(inputMesh, outputMesh);
|
||||
|
||||
Bounds bounds = outputMesh.bounds;
|
||||
Vector3 size = bounds.size;
|
||||
|
||||
Vector3[] vertices = outputMesh.vertices;
|
||||
Vector2[] uvs = new Vector2[vertices.Length];
|
||||
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
uvs[i] = new Vector2(vertices[i].x / size.x, vertices[i].z / size.z) * uvScale + uvShift;
|
||||
}
|
||||
outputMesh.SetUVs(0, uvs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9deef960c4623f0438f908d9a5841cfa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,88 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates UV sphere tcoords via imgui
|
||||
/// </summary>
|
||||
public class UVSphereProjectEditor : EditorWindow
|
||||
{
|
||||
public float radius = 1.0f;
|
||||
public float uvScale = 2.0f;
|
||||
public Vector3 center = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
public Mesh inputMesh = null;
|
||||
public Mesh outputMesh = null;
|
||||
|
||||
public static void Init(Mesh inputMesh, Mesh outputMesh)
|
||||
{
|
||||
UVSphereProjectEditor window = GetWindow(typeof(UVSphereProjectEditor)) as UVSphereProjectEditor;
|
||||
window.inputMesh = inputMesh;
|
||||
window.outputMesh = outputMesh;
|
||||
// Initialize to the bounds of the input mesh
|
||||
window.center = inputMesh.bounds.center;
|
||||
window.radius = inputMesh.bounds.size.magnitude * 0.5f;
|
||||
window.UpdateEditorResults();
|
||||
window.Show();
|
||||
}
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
inputMesh = EditorGUILayout.ObjectField("Input Mesh: ", inputMesh, typeof(Mesh), true) as Mesh;
|
||||
Vector3 tCenter = EditorGUILayout.Vector3Field("Center: ", center);
|
||||
float tRadius = EditorGUILayout.FloatField("Radius: ", radius);
|
||||
float tUvScale = EditorGUILayout.FloatField("UV Scale: ", uvScale);
|
||||
|
||||
// \todo: How to get undo to also call UpdateInputObj?
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(this, "Change of Parameters");
|
||||
radius = Mathf.Max(tRadius, 0.0f);
|
||||
uvScale = tUvScale;
|
||||
center = tCenter;
|
||||
|
||||
UpdateEditorResults();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEditorResults()
|
||||
{
|
||||
GeomUtil.CopyMesh(inputMesh, outputMesh);
|
||||
|
||||
Vector3[] vertices = outputMesh.vertices;
|
||||
Vector2[] uvs = new Vector2[vertices.Length];
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
Vector3 diff = vertices[i] - center;
|
||||
|
||||
// Compute phi and theta on the sphere
|
||||
float theta = Mathf.Asin(diff.x / radius);
|
||||
float phi = Mathf.Atan2(diff.y, diff.z);
|
||||
uvs[i] = new Vector2(phi / (Mathf.PI * 2.0f) + 0.5f, theta / (Mathf.PI * 2.0f) + 0.5f) * uvScale;
|
||||
}
|
||||
outputMesh.SetUVs(0, uvs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 29dbcb8127ce46e40a5aedbf66f68d77
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,317 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to display geometry components in the editor view and inspector
|
||||
/// </summary>
|
||||
[CustomEditor(typeof(GeometryFilter), true)]
|
||||
[InitializeOnLoad]
|
||||
class GeometryFilterEditor : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
OnGeomGUI();
|
||||
|
||||
OnPrimitiveGeomGUI();
|
||||
}
|
||||
|
||||
protected void OnGeomGUI()
|
||||
{
|
||||
GeometryFilter geomFilter = target as GeometryFilter;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
bool showHandles = EditorGUILayout.Toggle("Show Handles", geomFilter.showHandles);
|
||||
GeometryType newType = (GeometryType)EditorGUILayout.EnumPopup("Geom Type", geomFilter.type);
|
||||
UnityEngine.Object abstractMesh = null;
|
||||
|
||||
// If unity mesh, let user slot an asset
|
||||
if (newType == GeometryType.UnityMesh)
|
||||
{
|
||||
// Accepts either a Mesh or MeshFilter. If MeshFilter, then pulls the mesh out and uses that
|
||||
// This is because users
|
||||
UnityEngine.Object obj = EditorGUILayout.ObjectField("Mesh", geomFilter.inputUnityGeom, typeof(UnityEngine.Object), true);
|
||||
if (obj as MeshFilter != null)
|
||||
{
|
||||
abstractMesh = (obj as MeshFilter).sharedMesh;
|
||||
}
|
||||
else if (obj as Mesh != null)
|
||||
{
|
||||
abstractMesh = obj as Mesh;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (abstractMesh != null)
|
||||
{
|
||||
Debug.LogWarning("Tried to set object of type " + abstractMesh.GetType().Name + " on GeometryFilter");
|
||||
}
|
||||
}
|
||||
}
|
||||
// If an imstk mesh, let user slot an asset for it
|
||||
else if (newType == GeometryType.SurfaceMesh ||
|
||||
newType == GeometryType.LineMesh ||
|
||||
newType == GeometryType.TetrahedralMesh ||
|
||||
newType == GeometryType.HexahedralMesh ||
|
||||
newType == GeometryType.PointSet)
|
||||
{
|
||||
abstractMesh = EditorGUILayout.ObjectField("iMSTKMesh", geomFilter.inputImstkGeom, typeof(Geometry), true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(geomFilter, "Change of GeomFilter");
|
||||
|
||||
geomFilter.showHandles = showHandles;
|
||||
|
||||
// If the type changed unslot the geometry from the component
|
||||
if (newType != geomFilter.type)
|
||||
{
|
||||
geomFilter.inputImstkGeom = null;
|
||||
geomFilter.inputUnityGeom = null;
|
||||
geomFilter.type = newType;
|
||||
abstractMesh = null;
|
||||
}
|
||||
|
||||
// If the mesh changed, call the appropriate setter for it
|
||||
if (abstractMesh != null)
|
||||
{
|
||||
if ((abstractMesh as Mesh) != null)
|
||||
geomFilter.SetGeometry(abstractMesh as Mesh);
|
||||
else if ((abstractMesh as Geometry) != null)
|
||||
geomFilter.SetGeometry(abstractMesh as Geometry);
|
||||
}
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
|
||||
if (geomFilter.type == GeometryType.SurfaceMesh ||
|
||||
geomFilter.type == GeometryType.UnityMesh)
|
||||
{
|
||||
if (GUILayout.Button("Write Mesh"))
|
||||
{
|
||||
WriteMesh(geomFilter, ".ply");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnPrimitiveGeomGUI()
|
||||
{
|
||||
GeometryFilter geomFilter = target as GeometryFilter;
|
||||
|
||||
if (geomFilter.type == GeometryType.Capsule)
|
||||
{
|
||||
if (geomFilter.inputImstkGeom == null)
|
||||
{
|
||||
geomFilter.SetGeometry(CreateInstance<Capsule>());
|
||||
}
|
||||
Capsule source = geomFilter.inputImstkGeom as Capsule;
|
||||
Capsule target = CreateInstance<Capsule>();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
target.center = EditorGUILayout.Vector3Field("Center", source.center);
|
||||
target.radius = Mathf.Max(EditorGUILayout.FloatField("Radius", source.radius), float.Epsilon);
|
||||
target.length = Mathf.Max(EditorGUILayout.FloatField("Length", source.length), float.Epsilon);
|
||||
target.orientation = EditorGUILayout.Vector4Field("Orientation", source.orientation.ToVector4()).ToQuat();
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(geomFilter, "Change of GeomFilter Geom");
|
||||
geomFilter.inputImstkGeom = target;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
else if (geomFilter.type == GeometryType.Cylinder)
|
||||
{
|
||||
if (geomFilter.inputImstkGeom == null)
|
||||
{
|
||||
geomFilter.SetGeometry(CreateInstance<Cylinder>());
|
||||
}
|
||||
Cylinder source = geomFilter.inputImstkGeom as Cylinder;
|
||||
Cylinder target = CreateInstance<Cylinder>();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
target.center = EditorGUILayout.Vector3Field("Center", source.center);
|
||||
target.radius = Mathf.Max(EditorGUILayout.FloatField("Radius", source.radius), float.Epsilon);
|
||||
target.length = Mathf.Max(EditorGUILayout.FloatField("Length", source.length), float.Epsilon);
|
||||
target.orientation = EditorGUILayout.Vector4Field("Orientation", source.orientation.ToVector4()).ToQuat();
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(geomFilter, "Change of GeomFilter Geom");
|
||||
geomFilter.inputImstkGeom = target;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
else if (geomFilter.type == GeometryType.OrientedBox)
|
||||
{
|
||||
if (geomFilter.inputImstkGeom == null)
|
||||
{
|
||||
geomFilter.SetGeometry(CreateInstance<OrientedBox>());
|
||||
}
|
||||
OrientedBox source = geomFilter.inputImstkGeom as OrientedBox;
|
||||
OrientedBox target = CreateInstance<OrientedBox>();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
target.center = EditorGUILayout.Vector3Field("Center", source.center);
|
||||
target.extents = EditorGUILayout.Vector3Field("Extents", source.extents).cwiseMax(new Vector3(float.Epsilon, float.Epsilon, float.Epsilon)); ;
|
||||
target.orientation = EditorGUILayout.Vector4Field("Orientation", source.orientation.ToVector4()).ToQuat();
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(geomFilter, "Change of GeomFilter Geom");
|
||||
geomFilter.inputImstkGeom = target;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
else if (geomFilter.type == GeometryType.Plane)
|
||||
{
|
||||
if (geomFilter.inputImstkGeom == null)
|
||||
{
|
||||
geomFilter.SetGeometry(CreateInstance<ImstkUnity.Plane>());
|
||||
}
|
||||
ImstkUnity.Plane source = geomFilter.inputImstkGeom as ImstkUnity.Plane;
|
||||
ImstkUnity.Plane target = CreateInstance<ImstkUnity.Plane>();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
target.center = EditorGUILayout.Vector3Field("Center", source.center);
|
||||
target.normal = EditorGUILayout.Vector3Field("Normal", source.normal);
|
||||
target.visualWidth = Mathf.Max(EditorGUILayout.FloatField("Visual Width", source.visualWidth), float.Epsilon);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(geomFilter, "Change of GeomFilter Geom");
|
||||
geomFilter.inputImstkGeom = target;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
else if (geomFilter.type == GeometryType.Sphere)
|
||||
{
|
||||
if (geomFilter.inputImstkGeom == null)
|
||||
{
|
||||
geomFilter.SetGeometry(CreateInstance<Sphere>());
|
||||
}
|
||||
Sphere source = geomFilter.inputImstkGeom as Sphere;
|
||||
Sphere target = CreateInstance<Sphere>();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
target.center = EditorGUILayout.Vector3Field("Center", source.center);
|
||||
target.radius = Mathf.Max(EditorGUILayout.FloatField("Radius", source.radius), float.Epsilon);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(geomFilter, "Change of GeomFilter Geom");
|
||||
geomFilter.inputImstkGeom = target;
|
||||
SceneView.RepaintAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.InSelectionHierarchy | GizmoType.NotInSelectionHierarchy)]
|
||||
static void DrawHandles(GeometryFilter geomFilter, GizmoType gizmoType)
|
||||
{
|
||||
if (!geomFilter.showHandles) return;
|
||||
if (geomFilter.inputUnityGeom == null && geomFilter.inputImstkGeom == null) return;
|
||||
|
||||
if (geomFilter.type == GeometryType.UnityMesh)
|
||||
{
|
||||
Transform transform = geomFilter.gameObject.GetComponent<Transform>();
|
||||
Mesh mesh = geomFilter.inputUnityGeom;
|
||||
ImstkGizmos.DrawMesh(mesh, transform.position, transform.rotation, transform.lossyScale);
|
||||
}
|
||||
else
|
||||
{
|
||||
Transform transform = geomFilter.gameObject.GetComponent<Transform>();
|
||||
Geometry geom = geomFilter.inputImstkGeom;
|
||||
if (geom.geomType == GeometryType.Capsule)
|
||||
{
|
||||
Capsule capsule = geom as Capsule;
|
||||
|
||||
Mesh displayMesh = capsule.GetMesh();
|
||||
Gizmos.DrawWireMesh(displayMesh, 0, transform.position, transform.rotation, new Vector3(1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
else if (geom.geomType == GeometryType.Cylinder)
|
||||
{
|
||||
Cylinder cylinder = geom as Cylinder;
|
||||
|
||||
Mesh displayMesh = cylinder.GetMesh();
|
||||
Gizmos.DrawWireMesh(displayMesh, 0, transform.position, transform.rotation, new Vector3(1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
else if (geom.geomType == GeometryType.OrientedBox)
|
||||
{
|
||||
OrientedBox orientedBox = geom as OrientedBox;
|
||||
|
||||
Mesh displayMesh = orientedBox.GetMesh();
|
||||
Gizmos.DrawWireMesh(displayMesh, 0, transform.position, transform.rotation, transform.localScale);
|
||||
}
|
||||
else if (geom.geomType == GeometryType.Plane)
|
||||
{
|
||||
// Unity's planes default config for drawing is normal along z. So we rotate from z to normal
|
||||
ImstkUnity.Plane plane = geom as ImstkUnity.Plane;
|
||||
Handles.RectangleHandleCap(0, plane.GetTransformedCenter(transform),
|
||||
Quaternion.FromToRotation(Vector3.forward, plane.GetTransformedNormal(transform)), plane.visualWidth, EventType.Repaint);
|
||||
}
|
||||
else if (geom.geomType == GeometryType.Sphere)
|
||||
{
|
||||
Sphere sphere = geom as Sphere;
|
||||
Mesh displayMesh = sphere.GetMesh();
|
||||
Gizmos.DrawWireMesh(displayMesh, 0, transform.position, transform.rotation, transform.lossyScale);
|
||||
}
|
||||
else if (geom.geomType == GeometryType.PointSet ||
|
||||
geom.geomType == GeometryType.LineMesh ||
|
||||
geom.geomType == GeometryType.SurfaceMesh)
|
||||
{
|
||||
ImstkMesh mesh = geom as ImstkMesh;
|
||||
ImstkGizmos.DrawMesh(mesh.ToMesh(), transform.position, transform.rotation, transform.localScale);
|
||||
}
|
||||
else if (geom.geomType == GeometryType.TetrahedralMesh)
|
||||
{
|
||||
var tetMesh = Imstk.Utils.CastTo<Imstk.TetrahedralMesh>(geomFilter.GetOutputGeometry());
|
||||
Imstk.SurfaceMesh surfMesh = tetMesh.extractSurfaceMesh();
|
||||
Debug.Assert(tetMesh != null);
|
||||
var toWorld = transform.localToWorldMatrix;
|
||||
surfMesh.transform(toWorld.ToMat4d());
|
||||
surfMesh.updatePostTransformData();
|
||||
// Note probably not really performant ...
|
||||
Gizmos.DrawWireMesh(surfMesh.ToMesh());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteMesh(GeometryFilter script, string type)
|
||||
{
|
||||
var components = script.GetComponents<GeometryFilter>();
|
||||
int i = Array.IndexOf(components, script);
|
||||
script.WriteMesh(script.gameObject.name + "_" + i.ToString() + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: beaa834f9e135c04e8538c213b9b5db2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,137 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
/// <summary>
|
||||
/// This class reads in various types of geometry utilized by Imstk
|
||||
/// </summary>
|
||||
[UnityEditor.AssetImporters.ScriptedImporter(1, new string[] { "vtk", "vtu", "vtp", "stl", "ply", "veg", "msh", "mhd" })]
|
||||
public class GeometryImporter : UnityEditor.AssetImporters.ScriptedImporter
|
||||
{
|
||||
/// <summary>
|
||||
/// When on, reverses winding of cells (currently only works for surface meshes)
|
||||
/// </summary>
|
||||
public bool reverseWinding = false;
|
||||
|
||||
// Default is mirror along the X-Axis
|
||||
public Matrix4x4 transform = Matrix4x4.Scale(new Vector3(-1, 1, 1));
|
||||
|
||||
[Tooltip("If true, will center the mesh around the origin")]
|
||||
public bool centerMesh = false;
|
||||
|
||||
public override void OnImportAsset(UnityEditor.AssetImporters.AssetImportContext ctx)
|
||||
{
|
||||
string assetsPath = Application.dataPath;
|
||||
assetsPath = assetsPath.Replace("Assets", "");
|
||||
string filePath = assetsPath + ctx.assetPath;
|
||||
string fileName = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath);
|
||||
|
||||
// Read the geometry using imstk, warning: type not correct use conversion funcs
|
||||
Imstk.PointSet pointSet = Imstk.MeshIO.read(filePath);
|
||||
|
||||
// Create resource to load into
|
||||
// Setup a default cube, remove BoxCollider, replace mesh, add Geometry (Imstk), replace Mesh (Unity)
|
||||
GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
|
||||
DestroyImmediate(obj.GetComponent<BoxCollider>());
|
||||
obj.name = fileName;
|
||||
|
||||
if (centerMesh)
|
||||
{
|
||||
var vertices = pointSet.getVertexPositions();
|
||||
var center = new Imstk.Vec3d(0, 0, 0);
|
||||
for (uint i = 0; i < vertices.size(); ++i)
|
||||
{
|
||||
center += vertices[i];
|
||||
}
|
||||
center = center / vertices.size();
|
||||
pointSet.translate(center*-1.0, Imstk.Geometry.TransformType.ApplyToData);
|
||||
}
|
||||
|
||||
if (pointSet.getTypeName() == Imstk.LineMesh.getStaticTypeName())
|
||||
{
|
||||
Imstk.LineMesh lineMesh = Imstk.Utils.CastTo<Imstk.LineMesh>(pointSet);
|
||||
lineMesh.transform(transform.ToMat4d(), Imstk.Geometry.TransformType.ApplyToData);
|
||||
lineMesh.updatePostTransformData();
|
||||
|
||||
Mesh mesh = lineMesh.ToMesh();
|
||||
foreach (var v in mesh.vertices)
|
||||
{
|
||||
Debug.Log(v);
|
||||
}
|
||||
mesh.name = fileName + "_mesh";
|
||||
obj.GetComponent<MeshFilter>().sharedMesh = mesh;
|
||||
|
||||
ctx.AddObjectToAsset(obj.name, obj);
|
||||
ctx.AddObjectToAsset(mesh.name, mesh); // Add to the load asset
|
||||
}
|
||||
else if (pointSet.getTypeName() == Imstk.SurfaceMesh.getStaticTypeName())
|
||||
{
|
||||
Imstk.SurfaceMesh surfMesh = Imstk.Utils.CastTo<Imstk.SurfaceMesh>(pointSet);
|
||||
surfMesh.transform(transform.ToMat4d(), Imstk.Geometry.TransformType.ApplyToData);
|
||||
surfMesh.updatePostTransformData();
|
||||
|
||||
if (reverseWinding)
|
||||
{
|
||||
surfMesh.flipNormals();
|
||||
}
|
||||
|
||||
Mesh mesh = surfMesh.ToMesh();
|
||||
mesh.name = fileName + "_mesh";
|
||||
obj.GetComponent<MeshFilter>().sharedMesh = mesh;
|
||||
|
||||
ctx.AddObjectToAsset(obj.name, obj);
|
||||
ctx.AddObjectToAsset(mesh.name, mesh); // Add to the load asset
|
||||
}
|
||||
else if (pointSet.getTypeName() == Imstk.TetrahedralMesh.getStaticTypeName())
|
||||
{
|
||||
Imstk.TetrahedralMesh tetMesh = Imstk.Utils.CastTo<Imstk.TetrahedralMesh>(pointSet);
|
||||
if (tetMesh == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
tetMesh.transform(transform.ToMat4d(), Imstk.Geometry.TransformType.ApplyToData);
|
||||
tetMesh.updatePostTransformData();
|
||||
|
||||
Imstk.SurfaceMesh surfMesh = tetMesh.extractSurfaceMesh();
|
||||
|
||||
if (reverseWinding)
|
||||
{
|
||||
surfMesh.flipNormals();
|
||||
}
|
||||
|
||||
Geometry tetGeom = tetMesh.ToImstkMesh();
|
||||
tetGeom.name = fileName + "_mesh";
|
||||
Mesh mesh = surfMesh.ToMesh();
|
||||
mesh.name = fileName + "_mesh_surface";
|
||||
obj.GetComponent<MeshFilter>().sharedMesh = mesh;
|
||||
ctx.AddObjectToAsset(obj.name, obj);
|
||||
ctx.AddObjectToAsset(mesh.name, mesh); // Add to the load asset
|
||||
// \todo: Add a custom thumbnail for the tetrahedral mesh
|
||||
ctx.AddObjectToAsset(tetGeom.name, tetGeom);
|
||||
}
|
||||
|
||||
ctx.SetMainObject(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e43119e965e82b041aac262bc0f72039
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,183 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// For menu'd geometry operations. Could spin off into own GUI as it gets larger.
|
||||
/// GUI for parameters needs to be done up as well for some
|
||||
/// </summary>
|
||||
class GeometryMenuItems
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates UVs per vertex on plane for GameObjects MeshFilter mesh
|
||||
/// </summary>
|
||||
[MenuItem("iMSTK/Geometry/ProjectUVPlane")]
|
||||
private static void ProjectUVPlane()
|
||||
{
|
||||
Vector2 scale = new Vector2(1.0f, 1.0f);
|
||||
|
||||
// \todo: Plane option
|
||||
GameObject inputObj = Selection.activeObject as GameObject;
|
||||
if (inputObj == null)
|
||||
{
|
||||
Debug.LogWarning("ProjectUVPlane failed, no object selected.");
|
||||
return;
|
||||
}
|
||||
MeshFilter meshFilter = inputObj.GetComponentOrCreate<MeshFilter>();
|
||||
Mesh inputMesh = meshFilter.sharedMesh;
|
||||
meshFilter.sharedMesh = new Mesh();
|
||||
meshFilter.sharedMesh.name = inputMesh.name;
|
||||
|
||||
UVPlaneProjectEditor.Init(inputMesh, meshFilter.sharedMesh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates UVs per vertex on sphere for GameObjects MeshFilter mesh
|
||||
/// </summary>
|
||||
[MenuItem("iMSTK/Geometry/ProjectUVSphere")]
|
||||
private static void ProjectUVSphere()
|
||||
{
|
||||
GameObject inputObj = Selection.activeObject as GameObject;
|
||||
if (inputObj == null)
|
||||
{
|
||||
Debug.LogWarning("ProjectUVSphere failed, no object selected.");
|
||||
return;
|
||||
}
|
||||
MeshFilter meshFilter = inputObj.GetComponentOrCreate<MeshFilter>();
|
||||
Mesh inputMesh = meshFilter.sharedMesh;
|
||||
meshFilter.sharedMesh = new Mesh();
|
||||
meshFilter.sharedMesh.name = inputMesh.name;
|
||||
|
||||
UVSphereProjectEditor.Init(inputMesh, meshFilter.sharedMesh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Laplacian smoothens a mesh
|
||||
/// </summary>
|
||||
[MenuItem("iMSTK/Geometry/LaplaceSmoothMesh")]
|
||||
private static void LaplaceSmoothMesh()
|
||||
{
|
||||
GameObject inputObj = Selection.activeObject as GameObject;
|
||||
if (inputObj == null)
|
||||
{
|
||||
Debug.LogWarning("LaplaceSmoothMesh failed, no object selected.");
|
||||
return;
|
||||
}
|
||||
MeshFilter meshFilter = inputObj.GetComponentOrCreate<MeshFilter>();
|
||||
Mesh inputMesh = meshFilter.sharedMesh;
|
||||
meshFilter.sharedMesh = new Mesh();
|
||||
meshFilter.sharedMesh.name = inputMesh.name;
|
||||
|
||||
LaplaceSmoothEditor.Init(inputMesh, meshFilter.sharedMesh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subdivides a triangle mesh
|
||||
/// </summary>
|
||||
[MenuItem("iMSTK/Geometry/SubdivideMesh")]
|
||||
private static void SubdivideMesh()
|
||||
{
|
||||
GameObject inputObj = Selection.activeObject as GameObject;
|
||||
if (inputObj == null)
|
||||
{
|
||||
Debug.LogWarning("LaplaceSmoothMesh failed, no object selected.");
|
||||
return;
|
||||
}
|
||||
MeshFilter meshFilter = inputObj.GetComponentOrCreate<MeshFilter>();
|
||||
Mesh inputMesh = meshFilter.sharedMesh;
|
||||
meshFilter.sharedMesh = new Mesh();
|
||||
meshFilter.sharedMesh.name = inputMesh.name;
|
||||
|
||||
SubdivideMeshEditor.Init(inputMesh, meshFilter.sharedMesh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a tet grid on the currently selected object
|
||||
/// </summary>
|
||||
[MenuItem("iMSTK/Geometry/Generate TetGrid")]
|
||||
private static void GenerateTetGrid()
|
||||
{
|
||||
GameObject inputObj = Selection.activeObject as GameObject;
|
||||
if (inputObj == null)
|
||||
{
|
||||
Debug.LogWarning("TetGrid generation failed, no object selected.");
|
||||
return;
|
||||
}
|
||||
MeshFilter meshFilter = inputObj.GetComponentOrCreate<MeshFilter>();
|
||||
Mesh inputMesh = meshFilter.sharedMesh;
|
||||
meshFilter.sharedMesh = new Mesh();
|
||||
meshFilter.sharedMesh.name = inputMesh.name;
|
||||
|
||||
GeometryFilter tetGridFilter = inputObj.AddComponent<GeometryFilter>();
|
||||
ImstkMesh tetMesh = ScriptableObject.CreateInstance<ImstkMesh>();
|
||||
tetMesh.geomType = GeometryType.TetrahedralMesh;
|
||||
tetGridFilter.SetGeometry(tetMesh);
|
||||
|
||||
// Operates on the whole object as it provides the tetrahedral mesh on a separate geometry
|
||||
TetrahedralGridEditor.Init(meshFilter.sharedMesh, tetGridFilter.inputImstkGeom as ImstkMesh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a plane mesh on the currently selected object
|
||||
/// </summary>
|
||||
[MenuItem("iMSTK/Geometry/Generate Plane")]
|
||||
private static void GeneratePlane()
|
||||
{
|
||||
GameObject inputObj = Selection.activeObject as GameObject;
|
||||
if (inputObj == null)
|
||||
{
|
||||
Debug.LogWarning("Plane generation failed, no object selected.");
|
||||
return;
|
||||
}
|
||||
MeshFilter meshFilter = inputObj.GetComponentOrCreate<MeshFilter>();
|
||||
PlaneMeshEditor.Init(meshFilter.sharedMesh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a line mesh on the currently selected object
|
||||
/// </summary>
|
||||
[MenuItem("iMSTK/Geometry/Generate LineMesh")]
|
||||
private static void GenerateLineMesh()
|
||||
{
|
||||
GameObject inputObj = Selection.activeObject as GameObject;
|
||||
if (inputObj == null)
|
||||
{
|
||||
Debug.LogError("Select an object before opening the LineMesh Editor");
|
||||
return;
|
||||
}
|
||||
MeshFilter meshFilter = inputObj.GetComponentOrCreate<MeshFilter>();
|
||||
inputObj.GetComponentOrCreate<MeshRenderer>();
|
||||
if (meshFilter.sharedMesh == null)
|
||||
{
|
||||
meshFilter.sharedMesh = new Mesh();
|
||||
meshFilter.sharedMesh.name = inputObj.name + "_mesh";
|
||||
} else
|
||||
{
|
||||
Debug.LogWarning("This will overwrite the current mesh.");
|
||||
}
|
||||
LineMeshEditor.Init(meshFilter.sharedMesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8934b7d83f4f03246ae61fe806001275
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,129 @@
|
||||
using ImstkUnity;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
[CustomEditor(typeof(GraspingManager))]
|
||||
public class GraspingManagerEditor : Editor
|
||||
{
|
||||
bool _folded = true;
|
||||
Rigid _rigid;
|
||||
GeometryFilter _graspingGeometry;
|
||||
List<GraspingManager.GraspingData> _graspingData;
|
||||
|
||||
List<DynamicalModel> _allDeformables = new List<DynamicalModel>();
|
||||
|
||||
GUIContent _warning;
|
||||
|
||||
double _deformableGraspingStiffness;
|
||||
double _rigidGraspingStiffness;
|
||||
|
||||
GraspingManagerEditor()
|
||||
{
|
||||
EditorApplication.hierarchyChanged += OnHierarchyChanged;
|
||||
}
|
||||
|
||||
private void OnHierarchyChanged()
|
||||
{
|
||||
_allDeformables = (Resources.FindObjectsOfTypeAll(typeof(DynamicalModel)) as DynamicalModel[]).ToList<DynamicalModel>();
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
if (_allDeformables.Count == 0) OnHierarchyChanged();
|
||||
|
||||
var script = target as GraspingManager;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
_rigid = EditorGUILayout.ObjectField("Grasping Object",
|
||||
script.rigid, typeof(ImstkUnity.Rigid), true) as ImstkUnity.Rigid;
|
||||
if (script.rigid == null)
|
||||
{
|
||||
_warning = EditorGUIUtility.IconContent("Error", "|Grasping Object Can't be null");
|
||||
EditorGUILayout.LabelField(_warning, GUILayout.Width(_warning.image.width));
|
||||
}
|
||||
EditorGUILayout.EndHorizontal();
|
||||
_graspingGeometry = EditorGUILayout.ObjectField("Grasping Geometry (Optional)",
|
||||
script.graspingGeometry, typeof(GeometryFilter), true) as GeometryFilter;
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
|
||||
_deformableGraspingStiffness = EditorGUILayout.DoubleField("Deformable Grasping Stiffness", script.deformableGraspingStiffness);
|
||||
_rigidGraspingStiffness = EditorGUILayout.DoubleField("Rigid Grasping Stiffness", script.rigidGraspingStiffness);
|
||||
|
||||
GUILayout.EndVertical();
|
||||
// Maybe this is something we should do for all imstk components
|
||||
// as we can't edit them during runtime anyway
|
||||
if (_rigid != null && !Application.isPlaying)
|
||||
{
|
||||
// Takes up a lot of resources when playing, just don't execute
|
||||
HandleGraspingData(script);
|
||||
UpdateScript(script);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUI.EndChangeCheck();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateScript(GraspingManager script)
|
||||
{
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(script, "Change of Parameters");
|
||||
script.rigid = _rigid;
|
||||
script.graspingGeometry = _graspingGeometry;
|
||||
script.graspingData = new List<GraspingManager.GraspingData>(_graspingData);
|
||||
script.deformableGraspingStiffness = _deformableGraspingStiffness;
|
||||
script.rigidGraspingStiffness = _rigidGraspingStiffness;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleGraspingData(GraspingManager script)
|
||||
{
|
||||
// if there aren't any items to grasp, make sure ...
|
||||
if (_allDeformables.Count == 0) OnHierarchyChanged();
|
||||
|
||||
_graspingData = new List<GraspingManager.GraspingData>(script.graspingData);
|
||||
|
||||
foreach (var item in _allDeformables)
|
||||
{
|
||||
if (item is StaticModel || item == _rigid) continue;
|
||||
|
||||
if (_graspingData.FindIndex(x => x.target == item) < 0)
|
||||
{
|
||||
GraspingManager.GraspingData graspingData = new GraspingManager.GraspingData();
|
||||
graspingData.enabled = false;
|
||||
graspingData.type = Grasping.GraspType.Cell;
|
||||
graspingData.target = item;
|
||||
_graspingData.Add(graspingData);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove stale Objects
|
||||
_graspingData.RemoveAll(x => !_allDeformables.Contains(x.target));
|
||||
|
||||
_folded = EditorGUILayout.Foldout(_folded, "Graspable Objects");
|
||||
if (_folded)
|
||||
{
|
||||
EditorGUILayout.BeginVertical();
|
||||
for (int i = 0; i < _graspingData.Count; ++i)
|
||||
{
|
||||
var item = _graspingData[i];
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
item.enabled = EditorGUILayout.Toggle(item.enabled, GUILayout.Width(20));
|
||||
EditorGUI.BeginDisabledGroup(!item.enabled);
|
||||
EditorGUILayout.LabelField(item.target.name);
|
||||
item.type = (Grasping.GraspType)EditorGUILayout.EnumPopup(item.type);
|
||||
EditorGUI.EndDisabledGroup();
|
||||
EditorGUILayout.EndHorizontal();
|
||||
_graspingData[i] = item;
|
||||
}
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 90bae2d9e1ecd124b913832a0a5a1abb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,113 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the gui to fill ImstkSettings
|
||||
/// </summary>
|
||||
class ImstkSettingsProvider : SettingsProvider
|
||||
{
|
||||
private ImstkSettings settings;
|
||||
|
||||
public ImstkSettingsProvider(string path, SettingsScope scope = SettingsScope.User) : base(path, scope) { }
|
||||
|
||||
public static bool IsSettingsAvailable() { return File.Exists(ImstkSettings.settingsPath); }
|
||||
|
||||
// Read existing settings or create settings if they don't exist when user clicks them
|
||||
public override void OnActivate(string searchContext, VisualElement rootElement) { settings = ImstkSettings.Instance(); }
|
||||
|
||||
public override void OnGUI(string searchContext)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
bool useOptimalNumberOfThreads = EditorGUILayout.Toggle("Use Optimal # Threads", settings.useOptimalNumberOfThreads);
|
||||
//int numThreads = settings.numThreads;
|
||||
|
||||
//if (!useOptimalNumberOfThreads)
|
||||
// numThreads = EditorGUILayout.IntField("# Threads", numThreads);
|
||||
|
||||
EditorGUILayout.HelpBox(
|
||||
"When developer mode is on you will be prompted to install imstk " +
|
||||
" this can only be done by restarting unity as the editor will may load dll's preventing you from installing imstk" +
|
||||
" while the editor is running.", MessageType.Warning);
|
||||
bool useDevMode = EditorGUILayout.Toggle("Use Developer Mode", settings.useDeveloperMode);
|
||||
|
||||
string installPath = settings.installSourcePath;
|
||||
if (useDevMode)
|
||||
{
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Label("iMSTK Install Directory");
|
||||
installPath = EditorGUILayout.TextField(installPath);
|
||||
|
||||
if (GUILayout.Button("Open Directory"))
|
||||
{
|
||||
installPath = EditorUtility.OpenFolderPanel("iMSTK Install Directory (Development Use)", settings.installSourcePath, "");
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.HelpBox("Force install will attempt to perform an install now. This may not work if " +
|
||||
"any imstk libraries are already loaded.",
|
||||
MessageType.Warning);
|
||||
|
||||
if (GUILayout.Button("Force Install"))
|
||||
{
|
||||
EditorUtils.InstallImstk(installPath);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(settings, "Change of Settings");
|
||||
settings.useDeveloperMode = useDevMode;
|
||||
settings.useOptimalNumberOfThreads = useOptimalNumberOfThreads;
|
||||
//settings.numThreads = numThreads;
|
||||
settings.installSourcePath = installPath;
|
||||
|
||||
if (!System.IO.Directory.Exists(ImstkSettings.settingsDirectory))
|
||||
{
|
||||
System.IO.Directory.CreateDirectory(ImstkSettings.settingsDirectory);
|
||||
}
|
||||
|
||||
EditorUtility.SetDirty(settings);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register the SettingsProvider so it can be found in Editor->Project Settings
|
||||
/// </summary>
|
||||
[SettingsProvider]
|
||||
public static SettingsProvider CreateMyCustomSettingsProvider()
|
||||
{
|
||||
var provider = new ImstkSettingsProvider("Project/iMSTK Settings", SettingsScope.Project);
|
||||
provider.keywords = new HashSet<string>(new string[] { "Debug", "Logger", "Threads", "iMSTK" });
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 195737e5160741b4a8d43f53837040df
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,74 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// This class observes the play mode state to properly pause and step
|
||||
/// Imstk in the Unity editor
|
||||
/// </summary>
|
||||
[InitializeOnLoad]
|
||||
class PlayModeStateObserver
|
||||
{
|
||||
static PlayModeStateObserver()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// Perform imstk install if developer mode is on
|
||||
ImstkSettings settings = ImstkSettings.Instance();
|
||||
if (settings.useDeveloperMode &&
|
||||
EditorUtility.DisplayDialog("Do you want to install imstk",
|
||||
"To install imstk select yes and provide your imstk build/install directory. If you would not " +
|
||||
"like to be prompted again, please turn off developer mode in imstk settings. Note: " +
|
||||
"This prompt will be displayed upon installation again, select no second time.", "Yes", "No"))
|
||||
{
|
||||
settings.installSourcePath =
|
||||
EditorUtility.OpenFolderPanel("iMSTK Install Directory (Development Use)", settings.installSourcePath, "");
|
||||
EditorUtils.InstallImstk(settings.installSourcePath);
|
||||
EditorUtility.SetDirty(settings);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
#endif
|
||||
|
||||
//EditorApplication.playModeStateChanged += playModeStateChanged;
|
||||
EditorApplication.pauseStateChanged += pauseStateChanged;
|
||||
}
|
||||
|
||||
private static void pauseStateChanged(PauseState state)
|
||||
{
|
||||
if (SimulationManager.sceneManager != null)
|
||||
{
|
||||
bool paused = SimulationManager.sceneManager.getPaused();
|
||||
if (paused)
|
||||
{
|
||||
SimulationManager.sceneManager.setPaused(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
SimulationManager.sceneManager.setPaused(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//private static void playModeStateChanged(PlayModeStateChange state) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e6b12b0479820f43b977a10b5399b5b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,196 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
[CustomEditor(typeof(RigidController))]
|
||||
public class RigidControllerEditor : Editor
|
||||
{
|
||||
Vector3 _attachmentPoint;
|
||||
Vector3 _translationalOffset;
|
||||
Vector3 _rotationalOffset;
|
||||
Vector3 _localRotationalOffset;
|
||||
double _translationScaling;
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
RigidController script = target as RigidController;
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
TrackingDevice results = script.device;
|
||||
Object obj = EditorGUILayout.ObjectField("Device", results, typeof(Object), true) as Object;
|
||||
if (obj is TrackingDevice)
|
||||
{
|
||||
results = obj as TrackingDevice;
|
||||
}
|
||||
else if (obj is GameObject)
|
||||
{
|
||||
results = (obj as GameObject).GetComponent<TrackingDevice>();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("Cannot set object on field, expects TrackingDevice or game object with TrackingDevice");
|
||||
}
|
||||
Rigid rigid = EditorGUILayout.ObjectField("Rigid", script.rigid, typeof(Rigid), true) as Rigid;
|
||||
GUILayout.EndVertical();
|
||||
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
bool useCriticalDamping = EditorGUILayout.Toggle("Critical Damping", script.useCriticalDamping);
|
||||
double linearKs = EditorGUILayout.DoubleField("Linear Spring Constant", script.linearKs);
|
||||
double linearKd = script.linearKd;
|
||||
if (!useCriticalDamping)
|
||||
{
|
||||
linearKd = EditorGUILayout.DoubleField("Linear Damping", script.linearKd);
|
||||
}
|
||||
|
||||
double angularKs = EditorGUILayout.DoubleField("Angular Spring Constant", script.angularKs);
|
||||
double angularKd = script.angularKd;
|
||||
if (!useCriticalDamping)
|
||||
{
|
||||
angularKd = EditorGUILayout.DoubleField("Angular Damping", script.angularKd);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
|
||||
script._forceFoldout = EditorGUILayout.Foldout(script._forceFoldout, "Force Settings");
|
||||
double forceScaling = script.forceScale;
|
||||
bool useForceSmoothing = script.useForceSmoothing;
|
||||
int forceSmoothKernelSize = script.forceSmoothingKernelSize;
|
||||
if (script._forceFoldout)
|
||||
{
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
forceScaling = EditorGUILayout.DoubleField("Force Scaling", script.forceScale);
|
||||
useForceSmoothing = EditorGUILayout.Toggle("Use Force Smoothing", script.useForceSmoothing);
|
||||
forceSmoothKernelSize =
|
||||
EditorGUILayout.IntField("Force Smooth Kernel Size", script.forceSmoothingKernelSize);
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
var offsetContent = new GUIContent("Offsets", "Settings that will transform the controlled objects coordinate system in " +
|
||||
"relation to the device coordinate system");
|
||||
script._offsetFoldout = EditorGUILayout.Foldout(script._offsetFoldout, offsetContent);
|
||||
|
||||
// Initialize in case the foldout is closed
|
||||
|
||||
_attachmentPoint = script.attachmentPoint;
|
||||
_translationScaling = script.translationScaling;
|
||||
_translationalOffset = script.translationalOffset;
|
||||
_rotationalOffset = script.rotationalOffset.eulerAngles;
|
||||
_localRotationalOffset = script.localRotationalOffset.eulerAngles;
|
||||
|
||||
if (script._offsetFoldout)
|
||||
{
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
|
||||
_attachmentPoint = EditorGUILayout.Vector3Field("Attachment Point", script.attachmentPoint);
|
||||
|
||||
if (GUILayout.Button("Copy Translational Offset from Transform"))
|
||||
{
|
||||
_translationalOffset = script.transform.position;
|
||||
} else
|
||||
{
|
||||
_translationalOffset =
|
||||
EditorGUILayout.Vector3Field("Translational Offset", script.translationalOffset);
|
||||
}
|
||||
|
||||
_rotationalOffset =
|
||||
EditorGUILayout.Vector3Field("Rotational Offset", script.rotationalOffset.eulerAngles);
|
||||
_localRotationalOffset =
|
||||
EditorGUILayout.Vector3Field("Local Rotational Offset", script.localRotationalOffset.eulerAngles);
|
||||
|
||||
_translationScaling =
|
||||
EditorGUILayout.DoubleField("Translation Scaling", script.translationScaling);
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
script._axisMappingFoldout = EditorGUILayout.Foldout(script._axisMappingFoldout, "Coordinate Transforms");
|
||||
bool invertX = script.invertX;
|
||||
bool invertY = script.invertY;
|
||||
bool invertZ = script.invertZ;
|
||||
bool rotInvertX = script.invertRotX;
|
||||
bool rotInvertY = script.invertRotY;
|
||||
bool rotInvertZ = script.invertRotZ;
|
||||
if (script._axisMappingFoldout)
|
||||
{
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
invertX = EditorGUILayout.Toggle("Invert X", script.invertX);
|
||||
invertY = EditorGUILayout.Toggle("Invert Y", script.invertY);
|
||||
invertZ = EditorGUILayout.Toggle("Invert Z", script.invertZ);
|
||||
rotInvertX = EditorGUILayout.Toggle("Rotation Invert X", script.invertRotX);
|
||||
rotInvertY = EditorGUILayout.Toggle("Rotation Invert Y", script.invertRotY);
|
||||
rotInvertZ = EditorGUILayout.Toggle("Rotation Invert Z", script.invertRotZ);
|
||||
GUILayout.EndVertical();
|
||||
}
|
||||
|
||||
bool debugController = EditorGUILayout.Toggle("Write Controller transform", script.debugController);
|
||||
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(script, "Change of Parameters");
|
||||
script.device = results;
|
||||
script.rigid = rigid;
|
||||
|
||||
script.angularKd = angularKd;
|
||||
script.angularKs = angularKs;
|
||||
script.linearKd = linearKd;
|
||||
script.linearKs = linearKs;
|
||||
|
||||
script.useCriticalDamping = useCriticalDamping;
|
||||
|
||||
script.forceScale = forceScaling;
|
||||
script.useForceSmoothing = useForceSmoothing;
|
||||
script.forceSmoothingKernelSize = forceSmoothKernelSize;
|
||||
|
||||
script.attachmentPoint = _attachmentPoint;
|
||||
script.translationalOffset = _translationalOffset;
|
||||
script.rotationalOffset.eulerAngles = _rotationalOffset;
|
||||
script.localRotationalOffset.eulerAngles = _localRotationalOffset;
|
||||
script.translationScaling = _translationScaling;
|
||||
|
||||
script.invertX = invertX;
|
||||
script.invertY = invertY;
|
||||
script.invertZ = invertZ;
|
||||
script.invertRotX = rotInvertX;
|
||||
script.invertRotY = rotInvertY;
|
||||
script.invertRotZ = rotInvertZ;
|
||||
|
||||
script.debugController = debugController;
|
||||
}
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.InSelectionHierarchy)]
|
||||
static void DrawHandles(RigidController scr, GizmoType gizmoType)
|
||||
{
|
||||
|
||||
var pos = scr.transform.localToWorldMatrix.MultiplyPoint(scr.attachmentPoint);
|
||||
|
||||
// Draw a sphere at the haptic attachment point
|
||||
Gizmos.color = Color.red;
|
||||
Gizmos.DrawSphere(pos, 0.02f);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b142915e0959468428258cc9dc36f4b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,155 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using Imstk;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
[CustomEditor(typeof(Rigid))]
|
||||
class RigidEditor : DynamicalModelEditor
|
||||
{
|
||||
GeometryFilter _physicsGeometryFilter;
|
||||
bool _drawPhysicsGeometry = false;
|
||||
|
||||
GeometryFilter _collisionGeometryFilter;
|
||||
bool _drawCollisionGeometry = false;
|
||||
|
||||
bool _bodyDamping = false;
|
||||
double _linearDampingCoeff = 0.0;
|
||||
double _angularDampingCoeff = 0.0;
|
||||
|
||||
readonly GUIContent _debugContent = new GUIContent("","Draw debug mesh");
|
||||
readonly GUILayoutOption _checkBoxWidth = GUILayout.Width(20);
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
Rigid script = target as Rigid;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
_physicsGeometryFilter = EditorUtils.GeomFilterField("Physics Geometry", script.physicsGeomFilter);
|
||||
_drawPhysicsGeometry = EditorGUILayout.Toggle(_debugContent, script.drawPhysicsGeometry, _checkBoxWidth);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
_collisionGeometryFilter = EditorUtils.GeomFilterField("Collision Geometry", script.collisionGeomFilter);
|
||||
_drawCollisionGeometry = EditorGUILayout.Toggle(_debugContent, script.drawCollisionGeometry, _checkBoxWidth);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
double mass = EditorGUILayout.DoubleField("Mass", script.mass);
|
||||
if (mass < 0.0)
|
||||
{
|
||||
Debug.LogWarning("Mass cannot be negative!");
|
||||
mass = 0.0;
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
GUILayout.Label("Inertia Tensor");
|
||||
Vector3 inertiaRow1 = EditorGUILayout.Vector3Field("", script.inertia[0]);
|
||||
Vector3 inertiaRow2 = EditorGUILayout.Vector3Field("", script.inertia[1]);
|
||||
Vector3 inertiaRow3 = EditorGUILayout.Vector3Field("", script.inertia[2]);
|
||||
GUILayout.EndVertical();
|
||||
|
||||
var ignoreGravity = EditorGUILayout.Toggle("Ignore Gravity", script.ignoreGravity);
|
||||
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
_bodyDamping = EditorGUILayout.Toggle("Use Body Damping", script.useBodyDamping);
|
||||
if (_bodyDamping)
|
||||
{
|
||||
_linearDampingCoeff = EditorGUILayout.Slider("Linear Damping Coeff", (float)script.linearDampingCoeff, 0, 1);
|
||||
_angularDampingCoeff = EditorGUILayout.Slider("Angular Damping Coeff", (float)script.angularDampingCoeff, 0, 1);
|
||||
}
|
||||
GUILayout.EndVertical();
|
||||
|
||||
// Need to update PbdBody class to better support this when accessing it through the wrapper
|
||||
// GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
// Vector3 initVel = EditorGUILayout.Vector3Field("Initial Linear Velocity", script.initVelocity);
|
||||
// Vector3 initAngularVel = EditorGUILayout.Vector3Field("Initial Angular Velocity", script.initAngularVelocity);
|
||||
// GUILayout.EndVertical();
|
||||
//
|
||||
// GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
// Vector3 initForce = EditorGUILayout.Vector3Field("Initial Force", script.initForce);
|
||||
// Vector3 initTorque = EditorGUILayout.Vector3Field("Initial Torque", script.initTorque);
|
||||
// GUILayout.EndVertical();
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(script, "Change of Parameters");
|
||||
|
||||
script.physicsGeomFilter = _physicsGeometryFilter;
|
||||
script.drawPhysicsGeometry = _drawPhysicsGeometry;
|
||||
|
||||
script.collisionGeomFilter = _collisionGeometryFilter;
|
||||
script.drawCollisionGeometry = _drawCollisionGeometry;
|
||||
|
||||
script.mass = mass;
|
||||
script.inertia[0] = inertiaRow1;
|
||||
script.inertia[1] = inertiaRow2;
|
||||
script.inertia[2] = inertiaRow3;
|
||||
|
||||
script.ignoreGravity = ignoreGravity;
|
||||
|
||||
script.useBodyDamping = _bodyDamping;
|
||||
script.linearDampingCoeff = _linearDampingCoeff;
|
||||
script.angularDampingCoeff = _angularDampingCoeff;
|
||||
|
||||
|
||||
// script.initVelocity = initVel;
|
||||
// script.initAngularVelocity = initAngularVel;
|
||||
// script.initForce = initForce;
|
||||
// script.initTorque = initTorque;
|
||||
}
|
||||
|
||||
base.HandleColliders(script);
|
||||
|
||||
}
|
||||
|
||||
[DrawGizmo(GizmoType.Selected | GizmoType.Active)]
|
||||
public static void DrawRigidGizmo(Rigid rigid, GizmoType gizmoType)
|
||||
{
|
||||
var dyn = rigid.GetDynamicObject();
|
||||
var pbdObj = Imstk.Utils.CastTo<PbdObject>(dyn);
|
||||
if (pbdObj != null)
|
||||
{
|
||||
if (rigid.drawCollisionGeometry)
|
||||
{
|
||||
DrawGeometryGizmo(pbdObj.getCollidingGeometry());
|
||||
}
|
||||
if (rigid.drawPhysicsGeometry)
|
||||
{
|
||||
DrawGeometryGizmo(pbdObj.getPhysicsGeometry());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DrawGeometryGizmo(Imstk.Geometry geom)
|
||||
{
|
||||
var pointSet = Imstk.Utils.CastTo<PointSet>(geom);
|
||||
if (pointSet != null)
|
||||
{
|
||||
ImstkGizmos.DrawMesh(pointSet, UnityEngine.Color.red);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68c782406a24eda4d946cef6db6f01cc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,78 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
[CustomEditor(typeof(SimulationManager))]
|
||||
public class SimulationManagerEditor : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
// Define a style for centering text
|
||||
var centeredStyle = GUI.skin.GetStyle("Label");
|
||||
centeredStyle.alignment = TextAnchor.UpperCenter;
|
||||
|
||||
// Begin the script modification!
|
||||
SimulationManager script = target as SimulationManager;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
GUILayout.Label("Scene Settings", centeredStyle);
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
bool writeTaskGraph = EditorGUILayout.Toggle("Write Task Graph", script.writeTaskGraph);
|
||||
EditorGUILayout.HelpBox(
|
||||
"This is the timestep that iMSTK will used to advance the simulation, use the stats" +
|
||||
" display and testing to arrive at a reasonable value for your simulation." ,
|
||||
MessageType.Warning);
|
||||
float fixedTimestep = EditorGUILayout.FloatField("Fixed Timestep", script.fixedTimestep);
|
||||
|
||||
GUILayout.EndVertical();
|
||||
|
||||
GUILayout.Label("Pbd Simulation Settings", centeredStyle);
|
||||
GUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
var c = new PbdModelConfiguration();
|
||||
c.gravity = EditorGUILayout.Vector3Field("Gravity", script.pbdModelConfiguration.gravity);
|
||||
c.iterations = EditorGUILayout.IntField("Max # Iterations", script.pbdModelConfiguration.iterations);
|
||||
c.useRealtime = EditorGUILayout.Toggle("Use Realtime", script.pbdModelConfiguration.useRealtime);
|
||||
if (!script.pbdModelConfiguration.useRealtime)
|
||||
{
|
||||
c.dt = EditorGUILayout.DoubleField("Delta Time", script.pbdModelConfiguration.dt);
|
||||
}
|
||||
c.linearDampingCoeff = EditorGUILayout.DoubleField("Linear Damping Coefficient",
|
||||
script.pbdModelConfiguration.linearDampingCoeff);
|
||||
c.angularDampingCoeff = EditorGUILayout.DoubleField("Angular Damping Coefficient",
|
||||
script.pbdModelConfiguration.angularDampingCoeff);
|
||||
c.doPartitioning = EditorGUILayout.Toggle("Partitioning", script.pbdModelConfiguration.doPartitioning);
|
||||
|
||||
GUILayout.EndVertical();
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(script, "Change of Parameters");
|
||||
script.writeTaskGraph = writeTaskGraph;
|
||||
script.pbdModelConfiguration = c;
|
||||
script.fixedTimestep = fixedTimestep;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22dc68fd2e5f4144295545ee2ff229bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,43 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 ImstkUnity;
|
||||
using UnityEditor;
|
||||
|
||||
namespace ImstkEditor
|
||||
{
|
||||
[CustomEditor(typeof(StaticModel))]
|
||||
class StaticModelEditor : Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
StaticModel script = target as StaticModel;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
GeometryFilter collisionGeomFilter = EditorUtils.GeomFilterField("Collision Geometry", script.collisionGeomFilter);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
Undo.RegisterCompleteObjectUndo(script, "Change of Parameters");
|
||||
script.collisionGeomFilter = collisionGeomFilter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f318b9a7ac342f4c94f8ad8d9b618af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e91f2f601c7c29748857ba2c30b5c510
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
public class Capsule : Geometry
|
||||
{
|
||||
public Vector3 center = Vector3.zero;
|
||||
public float radius = 0.5f;
|
||||
public Quaternion orientation = Quaternion.identity;
|
||||
public float length = 1.0f;
|
||||
|
||||
public Capsule()
|
||||
{
|
||||
geomType = GeometryType.Capsule;
|
||||
}
|
||||
|
||||
public Vector3 GetTransformedCenter(Transform transform)
|
||||
{
|
||||
return transform.TransformPoint(center);
|
||||
}
|
||||
|
||||
public Quaternion GetTransformedOrientation(Transform transform)
|
||||
{
|
||||
return orientation * transform.rotation;
|
||||
}
|
||||
|
||||
public Mesh GetMesh()
|
||||
{
|
||||
Imstk.Capsule geom = this.ToImstkGeometry() as Imstk.Capsule;
|
||||
Imstk.SurfaceMesh surfMesh = Imstk.Utils.toSurfaceMesh(geom);
|
||||
return surfMesh.ToMesh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f81a111151cf2074bb509ea399de47b8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
public class Cylinder : Geometry
|
||||
{
|
||||
public Vector3 center = Vector3.zero;
|
||||
public float radius = 0.5f;
|
||||
public Quaternion orientation = Quaternion.identity;
|
||||
public float length = 1.0f;
|
||||
|
||||
public Cylinder()
|
||||
{
|
||||
geomType = GeometryType.Cylinder;
|
||||
}
|
||||
|
||||
public Vector3 GetTransformedCenter(Transform transform)
|
||||
{
|
||||
return transform.TransformPoint(center);
|
||||
}
|
||||
|
||||
public Quaternion GetTransformedOrientation(Transform transform)
|
||||
{
|
||||
return orientation * transform.rotation;
|
||||
}
|
||||
|
||||
public Mesh GetMesh()
|
||||
{
|
||||
Imstk.Cylinder geom = this.ToImstkGeometry() as Imstk.Cylinder;
|
||||
Imstk.SurfaceMesh surfMesh = Imstk.Utils.toSurfaceMesh(geom);
|
||||
return surfMesh.ToMesh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2f6dc9b9f9eb8c4cba5968e2b98bed2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,488 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 Imstk;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
/// <summary>
|
||||
/// Various geometryic utility functions
|
||||
/// </summary>
|
||||
public static class GeomUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// Map of GeometryType to MeshTopology
|
||||
/// </summary>
|
||||
public static Dictionary<GeometryType, MeshTopology> geomTypeToMeshTopology = new Dictionary<GeometryType, MeshTopology>()
|
||||
{
|
||||
{ GeometryType.PointSet, MeshTopology.Points },
|
||||
{ GeometryType.LineMesh, MeshTopology.Lines },
|
||||
{ GeometryType.SurfaceMesh, MeshTopology.Triangles }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Map of MeshTopology to GeometryType
|
||||
/// </summary>
|
||||
public static Dictionary<MeshTopology, GeometryType> meshTopologyToGeomType = new Dictionary<MeshTopology, GeometryType>()
|
||||
{
|
||||
{ MeshTopology.Points, GeometryType.PointSet },
|
||||
{ MeshTopology.Lines, GeometryType.LineMesh },
|
||||
{ MeshTopology.Triangles, GeometryType.SurfaceMesh }
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Preforms a simple mesh copy (only works with triangles)
|
||||
/// </summary>
|
||||
public static void CopyMesh(Mesh srcMesh, Mesh destMesh)
|
||||
{
|
||||
destMesh.triangles = null;
|
||||
destMesh.vertices = srcMesh.vertices;
|
||||
destMesh.uv = srcMesh.uv;
|
||||
destMesh.normals = srcMesh.normals;
|
||||
destMesh.colors = srcMesh.colors;
|
||||
destMesh.tangents = srcMesh.tangents;
|
||||
|
||||
for (int i = 0; i < srcMesh.subMeshCount; i++)
|
||||
{
|
||||
destMesh.SetIndices(srcMesh.GetIndices(i),
|
||||
srcMesh.GetTopology(i), i);
|
||||
}
|
||||
}
|
||||
|
||||
public static void CopyMesh(ImstkMesh srcMesh, ImstkMesh destMesh)
|
||||
{
|
||||
destMesh.vertices = srcMesh.vertices;
|
||||
destMesh.indices = srcMesh.indices;
|
||||
destMesh.texCoords = srcMesh.texCoords;
|
||||
destMesh.geomType = srcMesh.geomType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Imstk.PointSet to Unity Mesh
|
||||
/// SurfaceMesh
|
||||
/// </summary>
|
||||
public static Mesh ToMesh(this Imstk.PointSet geom)
|
||||
{
|
||||
string typeName = geom.getTypeName();
|
||||
if (typeName != "LineMesh" &&
|
||||
typeName != "SurfaceMesh" &&
|
||||
typeName != "PointSet")
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Imstk.PointSet pointSet = Imstk.Utils.CastTo<Imstk.PointSet>(geom);
|
||||
|
||||
Mesh results = new Mesh();
|
||||
|
||||
Vector3[] vertices = MathUtil.ToVector3Array(pointSet.getVertexPositions());
|
||||
results.SetVertices(vertices);
|
||||
|
||||
if (typeName == "PointSet")
|
||||
{
|
||||
int[] indices = new int[vertices.Length];
|
||||
for (int i = 0; i < indices.Length; i++)
|
||||
{
|
||||
indices[i] = i;
|
||||
}
|
||||
results.SetIndices(indices, MeshTopology.Points, 0);
|
||||
}
|
||||
else if (typeName == "LineMesh")
|
||||
{
|
||||
Imstk.LineMesh lineMesh = Imstk.Utils.CastTo<Imstk.LineMesh>(geom);
|
||||
int[] indices = MathUtil.ToIntArray(lineMesh.getLinesIndices());
|
||||
results.SetIndices(indices, MeshTopology.Lines, 0);
|
||||
}
|
||||
else if (typeName == "SurfaceMesh")
|
||||
{
|
||||
Imstk.SurfaceMesh surfMesh = Imstk.Utils.CastTo<Imstk.SurfaceMesh>(geom);
|
||||
int[] indices = MathUtil.ToIntArray(surfMesh.getTriangleIndices());
|
||||
results.SetIndices(indices, MeshTopology.Triangles, 0);
|
||||
results.RecalculateNormals();
|
||||
}
|
||||
|
||||
if (pointSet.getVertexTCoords() != null)
|
||||
{
|
||||
Vector2[] tCoords = MathUtil.ToVector2Array(pointSet.getVertexTCoords());
|
||||
results.SetUVs(0, tCoords);
|
||||
results.RecalculateNormals();
|
||||
}
|
||||
|
||||
results.RecalculateBounds();
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts ImstkMesh to Unity Mesh
|
||||
/// </summary>
|
||||
public static Mesh ToMesh(this ImstkMesh geom)
|
||||
{
|
||||
if (geom.IsVolume)
|
||||
return null;
|
||||
|
||||
Mesh results = new Mesh();
|
||||
results.name = geom.name;
|
||||
|
||||
results.SetVertices(geom.vertices);
|
||||
results.SetIndices(geom.indices, geomTypeToMeshTopology[geom.geomType], 0);
|
||||
|
||||
if (geom.texCoords.Length > 0)
|
||||
{
|
||||
results.SetUVs(0, geom.texCoords);
|
||||
}
|
||||
|
||||
results.RecalculateBounds();
|
||||
if (results.GetTopology(0) == MeshTopology.Triangles ||
|
||||
results.GetTopology(0) == MeshTopology.Quads)
|
||||
{
|
||||
results.RecalculateNormals();
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Unity Mesh to ImstkUnity Geometry
|
||||
/// </summary>
|
||||
public static ImstkMesh ToImstkMesh(this Mesh mesh)
|
||||
{
|
||||
// A Unity mesh can be made up multiple submeshes we only support 1
|
||||
ImstkMesh geom = ScriptableObject.CreateInstance<ImstkMesh>();
|
||||
geom.name = mesh.name;
|
||||
geom.SetVertices(mesh.vertices);
|
||||
geom.SetIndices(mesh.GetIndices(0));
|
||||
|
||||
geom.texCoords = new Vector2[mesh.uv.Length];
|
||||
mesh.uv.CopyTo(geom.texCoords, 0);
|
||||
geom.geomType = meshTopologyToGeomType[mesh.GetTopology(0)];
|
||||
|
||||
return geom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Unity Mesh to ImstkUnity Geometry with transform applied
|
||||
/// </summary>
|
||||
public static ImstkMesh ToImstkMesh(this Mesh mesh, Matrix4x4 transform)
|
||||
{
|
||||
ImstkMesh geometry = ScriptableObject.CreateInstance<ImstkMesh>();
|
||||
geometry.name = mesh.name;
|
||||
geometry.geomType = meshTopologyToGeomType[mesh.GetTopology(0)];
|
||||
|
||||
geometry.SetVertices(mesh.vertices, transform);
|
||||
|
||||
int[] indices = mesh.GetIndices(0);
|
||||
geometry.indices = new int[indices.Length];
|
||||
mesh.triangles.CopyTo(geometry.indices, 0);
|
||||
|
||||
geometry.texCoords = new Vector2[mesh.uv.Length];
|
||||
mesh.uv.CopyTo(geometry.texCoords, 0);
|
||||
|
||||
return geometry;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts ImstkMesh to Imstk PointSet
|
||||
/// </summary>
|
||||
/// <param name="geometry"></param>
|
||||
/// <returns></returns>
|
||||
public static Imstk.PointSet ToPointSet(this ImstkMesh geometry)
|
||||
{
|
||||
Imstk.VecDataArray3d vertices = MathUtil.ToVecDataArray3d(geometry.vertices);
|
||||
if (geometry.geomType == GeometryType.PointSet)
|
||||
{
|
||||
Imstk.PointSet pointSet = new Imstk.PointSet();
|
||||
pointSet.initialize(vertices);
|
||||
return pointSet;
|
||||
}
|
||||
else if (geometry.geomType == GeometryType.LineMesh)
|
||||
{
|
||||
Imstk.LineMesh mesh = new Imstk.LineMesh();
|
||||
Imstk.VecDataArray2i indices = MathUtil.ToVecDataArray2i(geometry.indices);
|
||||
mesh.initialize(vertices, indices);
|
||||
return mesh;
|
||||
}
|
||||
else if (geometry.geomType == GeometryType.SurfaceMesh)
|
||||
{
|
||||
Imstk.SurfaceMesh mesh = new Imstk.SurfaceMesh();
|
||||
Imstk.VecDataArray3i indices = MathUtil.ToVecDataArray3i(geometry.indices);
|
||||
mesh.initialize(vertices, indices);
|
||||
return mesh;
|
||||
}
|
||||
else if (geometry.geomType == GeometryType.TetrahedralMesh)
|
||||
{
|
||||
Imstk.TetrahedralMesh mesh = new Imstk.TetrahedralMesh();
|
||||
Imstk.VecDataArray4i indices = MathUtil.ToVecDataArray4i(geometry.indices);
|
||||
mesh.initialize(vertices, indices);
|
||||
return mesh;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Geometry to Imstk Geometry
|
||||
/// </summary>
|
||||
public static Imstk.Geometry ToImstkGeometry(this Geometry geom)
|
||||
{
|
||||
if (geom == null)
|
||||
{
|
||||
Debug.LogError("ToImstkgeometry called with null");
|
||||
}
|
||||
if (geom.IsMesh)
|
||||
{
|
||||
return (geom as ImstkMesh).ToPointSet();
|
||||
}
|
||||
else if (geom.geomType == GeometryType.Capsule)
|
||||
{
|
||||
Capsule capsule = geom as Capsule;
|
||||
Imstk.Capsule imstkCapsule = new Imstk.Capsule();
|
||||
imstkCapsule.setPosition(capsule.center.ToImstkVec());
|
||||
imstkCapsule.setRadius(capsule.radius);
|
||||
imstkCapsule.setLength(capsule.length);
|
||||
imstkCapsule.setOrientation(capsule.orientation.ToImstkQuat());
|
||||
imstkCapsule.updatePostTransformData();
|
||||
return imstkCapsule;
|
||||
}
|
||||
else if (geom.geomType == GeometryType.Cylinder)
|
||||
{
|
||||
Cylinder cylinder = geom as Cylinder;
|
||||
Imstk.Cylinder imstkCylinder = new Imstk.Cylinder();
|
||||
imstkCylinder.setPosition(cylinder.center.ToImstkVec());
|
||||
imstkCylinder.setRadius(cylinder.radius);
|
||||
imstkCylinder.setLength(cylinder.length);
|
||||
imstkCylinder.setOrientation(cylinder.orientation.ToImstkQuat());
|
||||
imstkCylinder.updatePostTransformData();
|
||||
return imstkCylinder;
|
||||
}
|
||||
else if (geom.geomType == GeometryType.OrientedBox)
|
||||
{
|
||||
OrientedBox orientedBox = geom as OrientedBox;
|
||||
Imstk.OrientedBox imstkOrientedBox = new Imstk.OrientedBox();
|
||||
imstkOrientedBox.setPosition(orientedBox.center.ToImstkVec());
|
||||
imstkOrientedBox.setOrientation(orientedBox.orientation.ToImstkQuat());
|
||||
imstkOrientedBox.setExtents(orientedBox.extents.ToImstkVec());
|
||||
imstkOrientedBox.updatePostTransformData();
|
||||
return imstkOrientedBox;
|
||||
}
|
||||
else if (geom.geomType == GeometryType.Plane)
|
||||
{
|
||||
Plane plane = geom as Plane;
|
||||
Imstk.Plane imstkPlane = new Imstk.Plane();
|
||||
imstkPlane.setPosition(plane.center.ToImstkVec());
|
||||
imstkPlane.setNormal(plane.normal.ToImstkVec());
|
||||
imstkPlane.updatePostTransformData();
|
||||
return imstkPlane;
|
||||
}
|
||||
else if (geom.geomType == GeometryType.Sphere)
|
||||
{
|
||||
Sphere sphere = geom as Sphere;
|
||||
Imstk.Sphere imstkSphere = new Imstk.Sphere();
|
||||
imstkSphere.setPosition(sphere.center.ToImstkVec());
|
||||
imstkSphere.setRadius(sphere.radius);
|
||||
imstkSphere.updatePostTransformData();
|
||||
return imstkSphere;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Lossy conversion, doesn't support mixed topologies
|
||||
/// </summary>
|
||||
public static Imstk.Geometry ToImstkGeometry(this Mesh mesh)
|
||||
{
|
||||
if (mesh.GetTopology(0) == MeshTopology.Points)
|
||||
{
|
||||
Imstk.PointSet geom = new Imstk.PointSet();
|
||||
geom.initialize(MathUtil.ToVecDataArray3d(mesh.vertices));
|
||||
return geom;
|
||||
}
|
||||
else if (mesh.GetTopology(0) == MeshTopology.Lines)
|
||||
{
|
||||
Imstk.LineMesh geom = new Imstk.LineMesh();
|
||||
geom.initialize(
|
||||
MathUtil.ToVecDataArray3d(mesh.vertices),
|
||||
MathUtil.ToVecDataArray2i(mesh.GetIndices(0)));
|
||||
return geom;
|
||||
}
|
||||
else if (mesh.GetTopology(0) == MeshTopology.Triangles)
|
||||
{
|
||||
Imstk.SurfaceMesh geom = new Imstk.SurfaceMesh();
|
||||
geom.initialize(
|
||||
MathUtil.ToVecDataArray3d(mesh.vertices),
|
||||
MathUtil.ToVecDataArray3i(mesh.GetIndices(0)));
|
||||
return geom;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Imstk PointSet to ImstkMesh
|
||||
/// </summary>
|
||||
public static ImstkMesh ToImstkMesh(this Imstk.PointSet pointSet)
|
||||
{
|
||||
ImstkMesh geom = ScriptableObject.CreateInstance<ImstkMesh>();
|
||||
geom.vertices = MathUtil.ToVector3Array(pointSet.getVertexPositions());
|
||||
string pointSetName = pointSet.getTypeName();
|
||||
if (pointSetName == "PointSet")
|
||||
{
|
||||
geom.geomType = GeometryType.PointSet;
|
||||
geom.indices = new int[geom.vertices.Length];
|
||||
for (int i = 0; i < geom.indices.Length; i++)
|
||||
{
|
||||
geom.indices[i] = i;
|
||||
}
|
||||
}
|
||||
else if (pointSetName == "LineMesh")
|
||||
{
|
||||
geom.geomType = GeometryType.LineMesh;
|
||||
Imstk.LineMesh mesh = Imstk.Utils.CastTo<Imstk.LineMesh>(pointSet);
|
||||
geom.indices = MathUtil.ToIntArray(mesh.getLinesIndices());
|
||||
}
|
||||
else if (pointSetName == "SurfaceMesh")
|
||||
{
|
||||
geom.geomType = GeometryType.SurfaceMesh;
|
||||
Imstk.SurfaceMesh mesh = Imstk.Utils.CastTo<Imstk.SurfaceMesh>(pointSet);
|
||||
geom.indices = MathUtil.ToIntArray(mesh.getTriangleIndices());
|
||||
}
|
||||
else if (pointSetName == "TetrahedralMesh")
|
||||
{
|
||||
geom.geomType = GeometryType.TetrahedralMesh;
|
||||
Imstk.TetrahedralMesh mesh = Imstk.Utils.CastTo<Imstk.TetrahedralMesh>(pointSet);
|
||||
geom.indices = MathUtil.ToIntArray(mesh.getTetrahedraIndices());
|
||||
}
|
||||
return geom;
|
||||
}
|
||||
|
||||
public static Geometry ToGeometry(this Mesh mesh)
|
||||
{
|
||||
return mesh.ToImstkMesh();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts Imstk Geometry to Geometry
|
||||
/// </summary>
|
||||
public static Geometry ToGeometry(Imstk.Geometry geom)
|
||||
{
|
||||
string name = geom.getTypeName();
|
||||
if (name == "PointSet" || name == "LineMesh" ||
|
||||
name == "SurfaceMesh" || name == "TetrahedralMesh")
|
||||
{
|
||||
Imstk.PointSet pointSet = Imstk.Utils.CastTo<Imstk.PointSet>(geom);
|
||||
return pointSet.ToImstkMesh();
|
||||
}
|
||||
else if (name == "Capsule")
|
||||
{
|
||||
Imstk.Capsule imstkCapsule = Imstk.Utils.CastTo<Imstk.Capsule>(geom);
|
||||
Imstk.Vec3d center = imstkCapsule.getCenter();
|
||||
Imstk.Quatd quat = imstkCapsule.getOrientation();
|
||||
|
||||
Capsule capsule = ScriptableObject.CreateInstance<Capsule>();
|
||||
capsule.center = center.ToUnityVec();
|
||||
capsule.radius = (float)imstkCapsule.getRadius();
|
||||
capsule.length = (float)imstkCapsule.getLength();
|
||||
capsule.orientation = quat.ToUnityQuat();
|
||||
return capsule;
|
||||
}
|
||||
else if (name == "Cylinder")
|
||||
{
|
||||
Imstk.Cylinder imstkCapsule = Imstk.Utils.CastTo<Imstk.Cylinder>(geom);
|
||||
Imstk.Vec3d center = imstkCapsule.getCenter();
|
||||
Imstk.Quatd quat = imstkCapsule.getOrientation();
|
||||
|
||||
Cylinder cylinder = ScriptableObject.CreateInstance<Cylinder>();
|
||||
cylinder.center = center.ToUnityVec();
|
||||
cylinder.radius = (float)imstkCapsule.getRadius();
|
||||
cylinder.length = (float)imstkCapsule.getLength();
|
||||
cylinder.orientation = quat.ToUnityQuat();
|
||||
return cylinder;
|
||||
}
|
||||
else if (name == "OrientedBox")
|
||||
{
|
||||
Imstk.OrientedBox imstkOrientedBox = Imstk.Utils.CastTo<Imstk.OrientedBox>(geom);
|
||||
Imstk.Vec3d center = imstkOrientedBox.getCenter();
|
||||
Imstk.Vec3d extents = imstkOrientedBox.getExtents();
|
||||
Imstk.Quatd orientation = imstkOrientedBox.getOrientation();
|
||||
|
||||
OrientedBox orientedBox = ScriptableObject.CreateInstance<OrientedBox>();
|
||||
orientedBox.center = center.ToUnityVec();
|
||||
orientedBox.extents = extents.ToUnityVec();
|
||||
orientedBox.orientation = orientation.ToUnityQuat();
|
||||
return orientedBox;
|
||||
}
|
||||
else if (name == "Plane")
|
||||
{
|
||||
Imstk.Plane imstkPlane = Imstk.Utils.CastTo<Imstk.Plane>(geom);
|
||||
Imstk.Vec3d center = imstkPlane.getCenter();
|
||||
Imstk.Vec3d normal = imstkPlane.getNormal();
|
||||
|
||||
Plane plane = ScriptableObject.CreateInstance<Plane>();
|
||||
plane.center = center.ToUnityVec();
|
||||
plane.normal = normal.ToUnityVec();
|
||||
return plane;
|
||||
}
|
||||
else if (name == "Sphere")
|
||||
{
|
||||
Imstk.Sphere imstkSphere = Imstk.Utils.CastTo<Imstk.Sphere>(geom);
|
||||
Imstk.Vec3d center = imstkSphere.getCenter();
|
||||
|
||||
Sphere sphere = ScriptableObject.CreateInstance<Sphere>();
|
||||
sphere.center = center.ToUnityVec();
|
||||
sphere.radius = (float)imstkSphere.getRadius();
|
||||
return sphere;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>Calculate list of vertices inside of a given mesh contained by unity meshfilter.
|
||||
/// The points sampled need to be in world space as the enclosing mesh will also be transfered
|
||||
/// into world space.</summary>
|
||||
/// <param name="enclosingMesh">Unity.MeshFilter for enclosing mesh</param>
|
||||
/// <param name="sampleMesh">Imstk.PointSet for sample mesh</param>
|
||||
/// <returns>Return list of indices of of the sample mesh that are contained within the enclosing mesh</returns>
|
||||
public static List<uint> PointsInside(MeshFilter enclosingMesh, PointSet sampleMesh)
|
||||
{
|
||||
Debug.Assert(enclosingMesh != null && sampleMesh != null);
|
||||
ImstkMesh imstkEnclosingMesh = enclosingMesh.sharedMesh.ToImstkMesh(enclosingMesh.transform.localToWorldMatrix);
|
||||
return PointsInside(imstkEnclosingMesh.ToImstkGeometry() as Imstk.SurfaceMesh, sampleMesh);
|
||||
}
|
||||
|
||||
public static List<uint> PointsInside(SurfaceMesh enclosingMesh, PointSet sampleMesh)
|
||||
{
|
||||
var result = new List<uint>();
|
||||
// Compute mask of enclosed points
|
||||
Imstk.SelectEnclosedPoints selectEnclosed = new Imstk.SelectEnclosedPoints();
|
||||
selectEnclosed.setInputMesh(enclosingMesh);
|
||||
selectEnclosed.setInputPoints(sampleMesh);
|
||||
selectEnclosed.setUsePruning(false);
|
||||
selectEnclosed.update();
|
||||
|
||||
Imstk.DataArrayuc isInside = selectEnclosed.getIsInsideMask();
|
||||
byte[] isInsideBytes = new byte[isInside.size()];
|
||||
isInside.getValues(isInsideBytes);
|
||||
for (int i = 0; i < isInsideBytes.Length; i++)
|
||||
{
|
||||
if (isInsideBytes[i] == 1)
|
||||
result.Add((uint)i);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20a65b11fe8bd5a499fd46809b237b1c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,60 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
public enum GeometryType
|
||||
{
|
||||
Capsule,
|
||||
Cylinder,
|
||||
HexahedralMesh,
|
||||
ImageData,
|
||||
LineMesh,
|
||||
OrientedBox,
|
||||
Plane,
|
||||
PointSet,
|
||||
Sphere,
|
||||
SurfaceMesh,
|
||||
TetrahedralMesh,
|
||||
UnityMesh
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// We need to reimplement storage for all geometry classes in iMSTK as Unity
|
||||
/// import and transfer from editor to runtime works via serialization
|
||||
/// afaik it would be quite significant undertaking, and very possibly impossible
|
||||
/// to serialize non C# classes, not to mention sensitive to changes. Thus the
|
||||
/// base iMSTK geometry cannot be used for geometry storage
|
||||
/// </summary>
|
||||
public class Geometry : ScriptableObject
|
||||
{
|
||||
public GeometryType geomType = GeometryType.Plane;
|
||||
|
||||
public bool IsMesh { get { return
|
||||
(geomType == GeometryType.PointSet ||
|
||||
geomType == GeometryType.LineMesh ||
|
||||
geomType == GeometryType.SurfaceMesh ||
|
||||
geomType == GeometryType.TetrahedralMesh ||
|
||||
geomType == GeometryType.HexahedralMesh); } }
|
||||
public bool IsVolume { get { return (geomType == GeometryType.TetrahedralMesh || geomType == GeometryType.HexahedralMesh); } }
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ea518f5190165c408289bf14f91f808
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,132 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
/// <summary>
|
||||
/// Similar to a MeshFilter in Unity.It provides an input and output geometry.
|
||||
/// It may take in any iMSTK geometry, as well as a Unity Mesh
|
||||
/// (one can also drag/drop a MeshFilter to it). These are instances of geometries
|
||||
/// used in all of iMSTK unity scripts.Instances of this class fit into
|
||||
/// the ``Visual Geometry``, ``Physics Geometry``, and ``Collision Geometry``
|
||||
/// slots on the model components.
|
||||
/// </summary>
|
||||
[AddComponentMenu("iMSTK/GeometryFilter")]
|
||||
public class GeometryFilter : ImstkBehaviour
|
||||
{
|
||||
// GeometryFilter supports either type
|
||||
public Geometry inputImstkGeom = null;
|
||||
public Mesh inputUnityGeom = null;
|
||||
|
||||
// It can output this type
|
||||
// Note: Imstk.Geometry cannot transition over editor and runtime
|
||||
public Imstk.Geometry outputImstkGeom = null;
|
||||
|
||||
// Used to denote which should be seated, not what is currently
|
||||
public GeometryType type = GeometryType.UnityMesh;
|
||||
|
||||
// Used to toggle drawing of it in the editor, ideally this would not
|
||||
// exist in runtime code, but unity's architecture doesn't allow
|
||||
public bool showHandles = true;
|
||||
|
||||
// Use to write the mesh as seen by iMSTK on creation,
|
||||
// this can help with debugging mesh issues
|
||||
public bool writeMesh = false;
|
||||
|
||||
private bool inGlobalSpace = false;
|
||||
|
||||
/// <summary>
|
||||
/// Moves the geometry to a global transform
|
||||
/// </summary>
|
||||
public void MoveToGlobalSpace()
|
||||
{
|
||||
// Models in Unity are provided in Mesh pre transformed.
|
||||
// We move the entire model to world space for simulation. Meaning the transform
|
||||
// is applied before giving the simulation geometry. Here we store that initial
|
||||
// transform and reset the local transform
|
||||
|
||||
if (inGlobalSpace) return;
|
||||
|
||||
var localToWorld = gameObject.transform.localToWorldMatrix.ToMat4d();
|
||||
var filters = gameObject.GetComponents<GeometryFilter>();
|
||||
foreach (var filter in filters)
|
||||
{
|
||||
if (filter.inGlobalSpace) continue;
|
||||
// World coordinates
|
||||
var geometry = filter.GetOutputGeometry();
|
||||
geometry.transform(localToWorld, Imstk.Geometry.TransformType.ApplyToData);
|
||||
geometry.setTransform(Imstk.Mat4d.Identity());
|
||||
filter.inGlobalSpace = true;
|
||||
}
|
||||
|
||||
gameObject.transform.localPosition = Vector3.zero;
|
||||
gameObject.transform.localScale = Vector3.one;
|
||||
gameObject.transform.localRotation = Quaternion.identity;
|
||||
|
||||
// Re-parent to itself for the period of the simulation run, this avoids having
|
||||
// to recalculate the local transforms when the object is in a hierarchy
|
||||
gameObject.transform.SetParent(null, false);
|
||||
}
|
||||
|
||||
public void SetGeometry(Geometry geom)
|
||||
{
|
||||
inputImstkGeom = geom;
|
||||
type = geom.geomType;
|
||||
}
|
||||
public void SetGeometry(Mesh geom)
|
||||
{
|
||||
inputUnityGeom = geom;
|
||||
type = GeometryType.UnityMesh;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will convert the input to output, allocating in native code
|
||||
/// </summary>
|
||||
public Imstk.Geometry GetOutputGeometry()
|
||||
{
|
||||
if (outputImstkGeom == null)
|
||||
{
|
||||
if (type == GeometryType.UnityMesh)
|
||||
outputImstkGeom = inputUnityGeom.ToImstkGeometry();
|
||||
else
|
||||
outputImstkGeom = inputImstkGeom.ToImstkGeometry();
|
||||
}
|
||||
return outputImstkGeom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write mesh in this filter to file, useful for debugging
|
||||
/// </summary>
|
||||
public void WriteMesh(string filename)
|
||||
{
|
||||
var mesh = Imstk.Utils.CastTo<Imstk.SurfaceMesh>(GetOutputGeometry());
|
||||
if (mesh != null)
|
||||
{
|
||||
//mesh.flipNormals();
|
||||
mesh.correctWindingOrder();
|
||||
mesh.computeVertexNormals();
|
||||
mesh.computeTrianglesNormals();
|
||||
Imstk.MeshIO.write(mesh, filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb7fd5ef0ac0aca4aaccabd7990fcfbf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,81 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
/// <summary>
|
||||
/// Roles all meshes into one class. ie: PointSet, LineMesh, SurfaceMesh,
|
||||
/// TetMesh, HexMesh
|
||||
/// </summary>
|
||||
public class ImstkMesh : Geometry
|
||||
{
|
||||
/// <summary>
|
||||
/// Map of some geometry types to number of cell points
|
||||
/// </summary>
|
||||
public static Dictionary<GeometryType, int> typeToNumPts = new Dictionary<GeometryType, int>()
|
||||
{
|
||||
{ GeometryType.PointSet, 1 },
|
||||
{ GeometryType.LineMesh, 2 },
|
||||
{ GeometryType.SurfaceMesh, 3 },
|
||||
{ GeometryType.TetrahedralMesh, 4 },
|
||||
{ GeometryType.HexahedralMesh, 8 }
|
||||
};
|
||||
|
||||
public int[] indices = new int[0];
|
||||
public Vector3[] vertices = new Vector3[0];
|
||||
public Vector2[] texCoords = new Vector2[0];
|
||||
|
||||
//public void CopyTo(ImstkMesh geometry)
|
||||
//{
|
||||
// geometry.type = type;
|
||||
// geometry.vertices = new Vector3[vertices.Length];
|
||||
// vertices.CopyTo(geometry.vertices, 0);
|
||||
// geometry.texCoords = new Vector2[texCoords.Length];
|
||||
// texCoords.CopyTo(geometry.texCoords, 0);
|
||||
// geometry.indices = new int[indices.Length];
|
||||
// indices.CopyTo(geometry.indices, 0);
|
||||
//}
|
||||
|
||||
public void SetVertices(Vector3[] vertices, Matrix4x4 transform)
|
||||
{
|
||||
this.vertices = new Vector3[vertices.Length];
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
this.vertices[i] = transform.MultiplyPoint(vertices[i]);
|
||||
}
|
||||
}
|
||||
public void SetVertices(Vector3[] vertices) { this.vertices = vertices; }
|
||||
|
||||
public void SetTexCoords(Vector2[] texCoords) { this.texCoords = texCoords; }
|
||||
|
||||
public void SetIndices(int[] indices) { this.indices = indices; }
|
||||
|
||||
public void Transform(Matrix4x4 transform)
|
||||
{
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
vertices[i] = transform.MultiplyPoint(vertices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ff06caabe5106e489465ca1ca18add7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
public class OrientedBox : Geometry
|
||||
{
|
||||
public Vector3 center = Vector3.zero;
|
||||
public Vector3 extents = new Vector3(0.5f, 0.5f, 0.5f);
|
||||
public Quaternion orientation = Quaternion.identity;
|
||||
|
||||
public OrientedBox()
|
||||
{
|
||||
geomType = GeometryType.OrientedBox;
|
||||
}
|
||||
|
||||
public Vector3 GetTransformedCenter(Transform transform)
|
||||
{
|
||||
return transform.TransformPoint(center);
|
||||
}
|
||||
|
||||
public Vector3 GetTransformedExtent(Transform transform)
|
||||
{
|
||||
return Vector3.Scale(extents, transform.localScale);
|
||||
}
|
||||
|
||||
public Quaternion GetTransformedOrientation(Transform transform)
|
||||
{
|
||||
return orientation * transform.rotation;
|
||||
}
|
||||
|
||||
public Mesh GetMesh()
|
||||
{
|
||||
Imstk.OrientedBox geom = this.ToImstkGeometry() as Imstk.OrientedBox;
|
||||
Imstk.SurfaceMesh surfMesh = Imstk.Utils.toSurfaceMesh(geom);
|
||||
return surfMesh.ToMesh();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd37a9e519de4c94e97f0ab4af6c0720
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,46 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
public class Plane : Geometry
|
||||
{
|
||||
public Plane()
|
||||
{
|
||||
geomType = GeometryType.Plane;
|
||||
}
|
||||
|
||||
public Vector3 GetTransformedCenter(Transform transform)
|
||||
{
|
||||
return transform.TransformPoint(center);
|
||||
}
|
||||
|
||||
public Vector3 GetTransformedNormal(Transform transform)
|
||||
{
|
||||
return transform.TransformDirection(normal).normalized;
|
||||
}
|
||||
|
||||
public Vector3 center = Vector3.zero;
|
||||
public Vector3 normal = Vector3.up;
|
||||
public float visualWidth = 1.0f; ///> Purely used for visualization
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11ff5901a1e43f54d931c16a488e306e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 936dbb32eb653d84a9bcbe9caad48547, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
/*=========================================================================
|
||||
|
||||
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 UnityEngine;
|
||||
|
||||
namespace ImstkUnity
|
||||
{
|
||||
public class Sphere : Geometry
|
||||
{
|
||||
public Vector3 center = Vector3.zero;
|
||||
public float radius = 0.5f;
|
||||
|
||||
public Sphere()
|
||||
{
|
||||
geomType = GeometryType.Sphere;
|
||||
}
|
||||
|
||||
public Vector3 GetTransformedCenter(Transform transform)
|
||||
{
|
||||
return transform.TransformPoint(center);
|
||||
}
|
||||
|
||||
public float GetTransformedRadius(Transform transform)
|
||||
{
|
||||
Vector3 localScale = transform.localScale;
|
||||
float max = Mathf.Max(Mathf.Max(localScale.x, localScale.y), localScale.z);
|
||||
return radius * max;
|
||||
}
|
||||
|
||||
public Mesh GetMesh()
|
||||
{
|
||||
Imstk.Sphere geom = this.ToImstkGeometry() as Imstk.Sphere;
|
||||
Imstk.SurfaceMesh surfMesh = Imstk.Utils.toUVSphereSurfaceMesh(geom, 7, 7);
|
||||
return surfMesh.ToMesh();
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user