use of artisynth.core.femmodels.FemMuscleModel in project artisynth_core by artisynth.
the class FemMuscleDemo method createMusclePanel.
public void createMusclePanel() {
ControlPanel myControlPanel = new ControlPanel("options", "LiveUpdate");
FemControlPanel.addMuscleControls(myControlPanel, tissue, myModel);
myControlPanel.addWidget(tissue, "profile");
ComponentList<MuscleBundle> muscles = ((FemMuscleModel) tissue).getMuscleBundles();
for (int i = 0; i < muscles.size(); ++i) {
DoubleFieldSlider slider = (DoubleFieldSlider) myControlPanel.addWidget("activation [N per Muscle]", this, "models/FemBeam/models/fem/bundles/" + i + ":excitation", 0, 1);
slider.setRoundingTolerance(0.00001);
slider.getLabel().setForeground(getMuscleColor(i));
BooleanSelector checkBox = (BooleanSelector) PropertyWidget.create("", muscles.get(i), "renderProps.visible");
checkBox.addValueChangeListener(new ValueChangeListener() {
public void valueChange(ValueChangeEvent e) {
rerender();
}
});
slider.add(checkBox);
}
for (int i = 0; i < muscles.size(); ++i) {
BooleanSelector selector = (BooleanSelector) myControlPanel.addWidget("fibres active", this, "models/FemBeam/models/fem/bundles/" + i + ":fibresActive");
selector.getLabel().setForeground(getMuscleColor(i));
BooleanSelector checkBox = (BooleanSelector) PropertyWidget.create("", muscles.get(i).getFibres(), "renderProps.visible");
checkBox.addValueChangeListener(new ValueChangeListener() {
public void valueChange(ValueChangeEvent e) {
rerender();
}
});
selector.add(checkBox);
}
addControlPanel(myControlPanel);
}
use of artisynth.core.femmodels.FemMuscleModel in project artisynth_core by artisynth.
the class FemMuscleDemo method initializeModel.
protected void initializeModel(int xn) throws IOException {
double widthX = 0.09;
double widthY = 0.03;
double widthZ = 0.03;
int numX = xn * 9;
int numY = xn * 3;
int numZ = xn * 3;
tissue = new FemMuscleModel("fem");
FemFactory.createHexGrid(tissue, widthX, widthY, widthZ, numX, numY, numZ);
tissue.setBounds(new Point3d(-widthX, 0, 0), new Point3d(widthX, 0, 0));
// XXX fix the leftmost nodes
double EPS = 1e-9;
double xmin = Double.POSITIVE_INFINITY;
for (FemNode3d n : tissue.getNodes()) {
if (n.getPosition().x < xmin) {
xmin = n.getPosition().x;
}
}
for (FemNode3d n : tissue.getNodes()) {
if (Math.abs(n.getPosition().x - xmin) < 1e-10) {
n.setDynamic(false);
}
}
LinkedList<FemElement3d> topElems = new LinkedList<FemElement3d>();
LinkedList<FemElement3d> midElems = new LinkedList<FemElement3d>();
LinkedList<FemElement3d> botElems = new LinkedList<FemElement3d>();
for (FemElement3d e : tissue.getElements()) {
if (defaultMidElements == ALL) {
midElems.add(e);
}
for (FemNode3d n : e.getNodes()) {
if (Math.abs(n.getPosition().z - widthZ / 2) < EPS) {
topElems.add(e);
break;
} else if (Math.abs(n.getPosition().z + widthZ / 2) < EPS) {
botElems.add(e);
break;
} else if (defaultMidElements == MIDDLE && Math.abs(n.getPosition().z - widthZ / (2 * numZ)) < EPS) {
midElems.add(e);
break;
}
}
}
RenderProps.setLineWidth(tissue, 2);
RenderProps.setLineColor(tissue, Color.PINK);
RenderProps.setPointStyle(tissue, Renderer.PointStyle.SPHERE);
RenderProps.setPointRadius(tissue, 0.03);
RenderProps.setPointColor(tissue, Color.PINK);
RenderProps.setFaceColor(tissue, Color.PINK.darker());
GenericMuscle mm = new GenericMuscle();
mm.setMaxStress(5000);
BlemkerMuscle bm = new BlemkerMuscle();
// bm.setMaxStress (5000);
tissue.setMuscleMaterial(bm);
MuscleBundle top, mid, bot;
top = createBundle("top", topElems);
mid = createBundle("mid", midElems);
bot = createBundle("bot", botElems);
int k = 0;
setBundleRenderProps(top, getMuscleColor(k++));
if (addMidMuscle) {
setBundleRenderProps(mid, getMuscleColor(k++));
}
setBundleRenderProps(bot, getMuscleColor(k));
tissue.addMuscleBundle(top);
if (addMidMuscle) {
tissue.addMuscleBundle(mid);
}
tissue.addMuscleBundle(bot);
double qt = midQuadTerm;
addStrand(top, -0.035, -0.005, 0.015, 0.035, -0.005, 0.015, 0, 8);
addStrand(top, -0.035, 0.005, 0.015, 0.035, 0.005, 0.015, 0, 8);
if (addMidMuscle) {
addStrand(mid, -0.035, -0.005, 0.000, 0.035, -0.005, 0.000, qt, 8);
addStrand(mid, -0.035, 0.005, 0.000, 0.035, 0.005, 0.000, qt, 8);
}
addStrand(bot, -0.035, -0.005, -0.015, 0.035, -0.005, -0.015, 0, 8);
addStrand(bot, -0.035, 0.005, -0.015, 0.035, 0.005, -0.015, 0, 8);
if (addMidMuscle) {
if (addMidElementsWithin > 0) {
mid.addElementsNearFibres(addMidElementsWithin);
}
if (autoComputeMidDirections) {
mid.computeElementDirections();
}
}
tissue.setDirectionRenderLen(0.5);
RenderProps.setPointRadius(tissue, 0.001);
tissue.setGravity(0, 0, 0);
tissue.setDensity(1000);
tissue.setMaterial(new MooneyRivlinMaterial(1037, 0, 0, 486, 0, 10000));
// tissue.setPoissonsRatio (0.499);
// tissue.setYoungsModulus (6912);
tissue.setParticleDamping(6.22);
// more stable with 0 stiffness damping ...
tissue.setStiffnessDamping(0.01);
// tissue.setMaxStepSize(100*TimeBase.USEC);
tissue.setMaxStepSize(0.01);
tissue.setIntegrator(Integrator.ConstrainedBackwardEuler);
myModel.addModel(tissue);
addModel(myModel);
for (MuscleBundle b : tissue.getMuscleBundles()) {
RenderProps.setVisible(b.getFibres(), false);
}
for (FemMarker m : tissue.markers()) {
RenderProps.setVisible(m, false);
}
addProbes(tissue);
createMusclePanel();
// int numWays = 20;
// double res = 0.1;
// for (int i = 0; i < numWays; i++) {
// addWayPoint (new WayPoint (TimeBase.secondsToTicks ((i + 1) * res)));
// }
}
use of artisynth.core.femmodels.FemMuscleModel in project artisynth_core by artisynth.
the class FemMuscleHeart method build.
// Model builder
@Override
public void build(String[] args) throws IOException {
super.build(args);
setMaxStepSize(0.005);
// Root mechanical model
MechModel mech = new MechModel("mech");
mech.setGravity(0, 0, -9.8);
addModel(mech);
// -------------------------------------------------------------
// HEART LOAD / ADD GEOMETRY
// -------------------------------------------------------------
// Heart surface mesh, with texture
String heartFile = ArtisynthPath.getSrcRelativePath(this, "data/HumanHeart.obj");
WavefrontReader wfr = new WavefrontReader(new File(heartFile));
PolygonalMesh heartMesh = new PolygonalMesh();
wfr.readMesh(heartMesh);
// triangulate for interaction
heartMesh.triangulate();
// FEM heart:
// - FEM mesh of heart convex hull
// - embedded heart surface geometry
FemMuscleModel heart = new FemMuscleModel("heart");
TetGenReader.read(heart, ArtisynthPath.getSrcRelativePath(this, "data/HumanHeartHull.node"), ArtisynthPath.getSrcRelativePath(this, "data/HumanHeartHull.ele"));
// add real-looking mesh
FemMeshComp embeddedHeart = heart.addMesh(heartMesh);
embeddedHeart.setName("embedded");
// Allow inverted elements (poor quality mesh)
heart.setWarnOnInvertedElements(false);
heart.setAbortOnInvertedElements(false);
// Convert unites to metres (original was cm)
heart.scaleDistance(0.01);
heart.setGravity(0, 0, -9.8);
heart.setStiffnessDamping(0.02);
// Set material properties
heart.setDensity(1000);
FemMaterial femMat = new LinearMaterial(2500, 0.33, true);
// simple muscle
MuscleMaterial muscleMat = new SimpleForceMuscle(500.0);
heart.setMaterial(femMat);
// Add heart to model
mech.addModel(heart);
// -------------------------------------------------------------
// MUSCLE BUNDLES
// -------------------------------------------------------------
// One "long" direction muscle bundle
// One "radial" muscle bundle
// LONG BUNDLE
// Compute the "long" direction of the heart
PolygonalMesh hull = heart.getSurfaceMesh();
RigidTransform3d trans = hull.computePrincipalAxes();
Vector3d longAxis = new Vector3d();
// first column of rotation
trans.R.getColumn(0, longAxis);
// Create the long axis muscle bundle
MuscleBundle longBundle = new MuscleBundle("long");
for (FemElement3d elem : heart.getElements()) {
longBundle.addElement(elem, longAxis);
}
longBundle.setMuscleMaterial(muscleMat);
heart.addMuscleBundle(longBundle);
// RADIAL BUNDLE
// Compute a plane through centre of heart
Plane plane = new Plane(longAxis, new Point3d(trans.p));
Point3d centroid = new Point3d();
Vector3d radialDir = new Vector3d();
// Create the radial muscle bundle
MuscleBundle radialBundle = new MuscleBundle("radial");
for (FemElement3d elem : heart.getElements()) {
elem.computeCentroid(centroid);
// project to plane and compute radial direction
plane.project(centroid, centroid);
radialDir.sub(centroid, trans.p);
radialDir.normalize();
radialBundle.addElement(elem, radialDir);
}
radialBundle.setMuscleMaterial(muscleMat);
heart.addMuscleBundle(radialBundle);
// -------------------------------------------------------------
// RIGID TABLE AND COLLISION
// -------------------------------------------------------------
// Create a rigid box for the heart to fall on
RigidBody box = RigidBody.createBox("box", 0.2, 0.2, 0.02, 0, /*addnormals*/
true);
box.setPose(new RigidTransform3d(new Vector3d(0, 0, -0.2), AxisAngle.IDENTITY));
box.setDynamic(false);
mech.addRigidBody(box);
// Enable collisions between the heart and table
mech.setCollisionBehavior(heart, box, true);
// -------------------------------------------------------------
// RENDER PROPERTIES
// -------------------------------------------------------------
// Hide elements and nodes
RenderProps.setVisible(heart.getElements(), false);
RenderProps.setVisible(heart.getNodes(), false);
RenderProps.setLineColor(radialBundle, Color.BLUE);
RenderProps.setLineColor(longBundle, Color.RED);
radialBundle.setDirectionRenderLen(0.1);
longBundle.setDirectionRenderLen(0.1);
RenderProps.setVisible(radialBundle, false);
RenderProps.setVisible(longBundle, false);
RenderProps.setVisible(heart.getSurfaceMeshComp(), false);
// adjust table render properties
RenderProps.setShading(box, Shading.METAL);
RenderProps.setSpecular(box, new Color(0.8f, 0.8f, 0.8f));
// adjust heart mesh render properties
RenderProps rprops = embeddedHeart.getRenderProps();
rprops.getBumpMap().setScaling(0.01f);
// don't modify specular
rprops.getColorMap().setSpecularColoring(false);
rprops.setShading(Shading.SMOOTH);
rprops.setFaceColor(new Color(0.8f, 0.8f, 0.8f));
rprops.getColorMap().setColorMixing(ColorMixing.MODULATE);
rprops.setSpecular(new Color(0.4f, 0.4f, 0.4f));
rprops.setShininess(128);
// -------------------------------------------------------------
// INPUT PROBES
// -------------------------------------------------------------
// Add heart probe
addHeartProbe(longBundle, radialBundle);
}
use of artisynth.core.femmodels.FemMuscleModel in project artisynth_core by artisynth.
the class FemSurfaceTargetDemo method build.
@Override
public void build(String[] args) throws IOException {
super.build(args);
mech = new MechModel("mech");
mech.setGravity(Vector3d.ZERO);
addModel(mech);
fem = new FemMuscleModel("fem");
fem.setStiffnessDamping(0.1);
mech.addModel(fem);
// boundary conditions
FemFactory.createHexGrid(fem, l, w, w, nl, nw, nw);
for (FemNode n : fem.getNodes()) {
if (n.getPosition().x > l / 2 - eps) {
n.setDynamic(false);
}
}
// muscles
addMuscle("vert", Color.RED, Vector3d.Z_UNIT);
addMuscle("trans", Color.BLUE, Vector3d.Y_UNIT);
body = new RigidBody("plate");
body.setMesh(MeshFactory.createBox(l, l, l / 10));
body.setPose(new RigidTransform3d(-1.2 * w - l / 20, 0, 0, 0, 1, 0, Math.PI / 2));
body.setDynamic(false);
mech.addRigidBody(body);
mech.setCollisionBehavior(body, fem, true);
addTrackingController();
setupRenderProps();
}
Aggregations