use of maspack.geometry.io.WavefrontReader in project artisynth_core by artisynth.
the class MultiViewerTesterBase method loadStanfordBunny.
protected static PolygonalMesh loadStanfordBunny() {
// read Standford bunny directly
String bunnyURL = "http://graphics.stanford.edu/~mdfisher/Data/Meshes/bunny.obj";
// bunny
File bunnyFile = new File("tmp/data/stanford_bunny.obj");
PolygonalMesh bunny = null;
try {
if (!bunnyFile.exists()) {
bunnyFile.getParentFile().mkdirs();
// read file directly from remote
FileCacher cacher = new FileCacher();
cacher.initialize();
cacher.cache(new URIx(bunnyURL), bunnyFile);
cacher.release();
}
WavefrontReader reader = new WavefrontReader(bunnyFile);
bunny = new PolygonalMesh();
reader.readMesh(bunny);
// bunny.computeVertexNormals();
// normalize bunny
double r = bunny.computeRadius();
Vector3d c = new Vector3d();
bunny.computeCentroid(c);
c.negate();
bunny.scale(1.0 / r);
c.z -= 0.5;
bunny.transform(new RigidTransform3d(c, new AxisAngle(1, 0, 0, Math.PI / 2)));
reader.close();
} catch (IOException e1) {
e1.printStackTrace();
System.out.println("Unable to load stanford bunny... requires internet connection");
bunny = null;
}
return bunny;
}
use of maspack.geometry.io.WavefrontReader in project artisynth_core by artisynth.
the class TextureHeartTest method addContent.
@Override
protected void addContent(MultiViewer mv) {
JFrame frame = new JFrame();
JPanel controls = new JPanel();
frame.add(controls);
String heartObjFilename = PathFinder.findSourceDir(this) + "/data/heart/HumanHeart.obj";
WavefrontReader reader = null;
try {
reader = new WavefrontReader(new File(heartObjFilename));
PolygonalMesh mesh = reader.readMesh();
RenderProps rprops = mesh.getRenderProps();
if (rprops == null) {
rprops = new RenderProps();
}
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.getBumpMap().setScaling(0.5f);
rprops.setShininess(128);
// mesh.setRenderProps(rprops);
// FixedMeshBody fm = new FixedMeshBody (mesh);
// fm.setRenderProps (mesh.getRenderProps ());
// RenderProps rprops = mesh.getRenderProps();
LabeledComponentBase base = PropertyWidget.create("Map", rprops.getColorMap(), "enabled");
controls.add(base);
base = PropertyWidget.create("Bump map", rprops.getBumpMap(), "enabled");
controls.add(base);
base = PropertyWidget.create("Lighting", rprops, "shading");
controls.add(base);
base = PropertyWidget.create("Specular", rprops.getColorMap(), "specularColoring");
controls.add(base);
base = PropertyWidget.create("Bump map scale", rprops.getBumpMap(), "scaling");
controls.add(base);
mv.addRenderable(mesh);
} catch (IOException e) {
e.printStackTrace();
}
if (reader != null) {
reader.close();
}
mv.autoFitViewers();
frame.pack();
frame.setVisible(true);
}
use of maspack.geometry.io.WavefrontReader 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 maspack.geometry.io.WavefrontReader in project artisynth_core by artisynth.
the class PolygonalMesh method read.
/**
* Reads the contents of this mesh from a ReaderTokenizer. The input is
* assumed to be supplied in Alias Wavefront obj format, as described for
* the method {@link #write(PrintWriter,NumberFormat,boolean)}.
*
* @param rtok
* tokenizer supplying the input description of the mesh
* @param zeroIndexed
* if true, the index numbering for mesh vertices starts at 0. Otherwise,
* numbering starts at 1.
*/
public void read(ReaderTokenizer rtok, boolean zeroIndexed) throws IOException {
clear();
WavefrontReader wfr = new WavefrontReader(rtok);
if (zeroIndexed) {
wfr.setZeroIndexed(true);
}
wfr.readMesh(this);
}
use of maspack.geometry.io.WavefrontReader in project artisynth_core by artisynth.
the class NURBSSurface method read.
/**
* Reads this surface from a text description supplied by a reader. The
* allowed format is a subset of the Alias Wavefront OBJ format for surfaces,
* and consists of a set of statements, one per line (lines can be continued,
* if necessary, using the line continuation character <code>\</code>).
*
* <p>
* The allowed statements are:
* <ul>
* <li>Vertex definition of the form <blockquote> v <i>x</i> <i>y</i> <i>z</i> [<i>w</i>]
* </blockquote> each giving the x, y, and z values for a control point (with
* an optional weighting value w which defaults to 1 if omitted).
* <li>Degree statement of the form <blockquote> deg <i>du</i> <i>dv</i>
* </blockquote> where du and dv are degree of the surface in the u and v
* directions. A degree statement must precede a surface statement (described
* below).
*
* <li>Surface statement of the form <blockquote> surf <i>ustart</i>
* <i>uend</i> <i>vstart</i> <i>vend</i> <i>i0</i> <i>i1</i> ...
* </blockquote> where ustart, uend, vstart, and vend give the minimum and
* maximum values for the u and v surface parameters, and i0, i1, etc. give
* the indices of the control points defined by the vertex statements.
* Control points are indexed, starting at 1, by their order of occurance. If
* the index value is negative, then it gives the relative location of a
* control point with respect to the surface statement, where -1 is the
* closest preceding, -2 is the next closest preceding, etc. There should be
* numcu*numcv control points in all, where numcu and numcv are described in
* {@link #set(int,int,double[],int,int,double[],Vector4d[]) set}, and the
* points should be ordered so that the first set of v points comes first,
* followed by the second set, etc.
*
* <li>A u parameter statement of the form <blockquote> parm u [closed]
* <i>k0</i> <i>k1</i> ... </blockquote> where <code>closed</code> is an
* optional keyword indicating that the surface is closed in u direction, and
* k0, k1, etc. are the u direction knot values. The u parameter statement
* must follow the surface statement and precede the end statement (described
* below).
*
* <li>A v parameter statement of the form <blockquote> parm v [closed]
* <i>k0</i> <i>k1</i> ... </blockquote> which is analogous to the u
* parameter statement.
*
* <li>An end statement of the form <blockquote> end </blockquote> This must
* be placed after the curve and parameter statements.
* </ul>
* The total number of control points and knots must match as described in
* the documentation for
* {@link #set(int,int,double[],int,int,double[],Vector4d[]) set}. Explicit
* knot values may be omitted for either u or v, in which case an appropriate
* number of uniformly-spaced knots is created with start and end values
* corresponding to 0 and 1.
*
* <p>
* As an example, here are the statements that define a simple bezier surface
* patch:
* <pre>
* v -10.0 0.0 10.0 1.0
* v -5.0 5.0 10.0 1.0
* v 5.0 5.0 10.0 1.0
* v 10.0 0.0 10.0 1.0
* v -10.0 0.0 5.0 1.0
* v -5.0 5.0 5.0 1.0
* v 5.0 5.0 5.0 1.0
* v 10.0 0.0 5.0 1.0
* v -10.0 0.0 -5.0 1.0
* v -5.0 5.0 -5.0 1.0
* v 5.0 5.0 -5.0 1.0
* v 10.0 0.0 -5.0 1.0
* v -10.0 0.0 -10.0 1.0
* v -5.0 5.0 -10.0 1.0
* v 5.0 5.0 -10.0 1.0
* v 10.0 0.0 -10.0 1.0
* deg 3 3
* surf 0.0 1.0 0.0 1.0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
* parm u 0.0 0.0 0.0 1.0 1.0 1.0
* parm v 0.0 0.0 0.0 1.0 1.0 1.0
* end
* </pre>
*
* @param reader
* providing the text input
* @throws IOException
* if an I/O or format error occurs
*/
public void read(Reader reader) throws IOException {
WavefrontReader wfr = new WavefrontReader(reader);
wfr.parse();
ArrayList<WavefrontReader.Surface> surfList = wfr.getSurfaceList();
WavefrontReader.Surface surface = surfList.get(surfList.size() - 1);
if (surface == null) {
throw new IOException("no surface specified in input");
}
try {
set(surface, wfr.getHomogeneousPoints());
} catch (IllegalArgumentException e) {
throw new IOException(e.getMessage());
}
}
Aggregations