use of org.scijava.java3d.Shape3D in project GDSC-SMLM by aherbert.
the class Shape3DHelper method createShape.
/**
* Creates the shape.
*
* @param rendering the rendering
* @param colorDepth the color depth
* @return the shape
*/
public static Shape3D createShape(Rendering rendering, int colorDepth) {
GeometryArray ga;
final Appearance appearance = new Appearance();
int vertexFormat = GeometryArray.COORDINATES;
if (colorDepth == 3) {
vertexFormat |= GeometryArray.COLOR_3;
} else if (colorDepth == 4) {
vertexFormat |= GeometryArray.COLOR_4;
}
// Support drawing as points ...
if (rendering == Rendering.POINT) {
ga = new PointArray(1, vertexFormat);
final PointAttributes pa = new PointAttributes();
pa.setPointAntialiasingEnable(true);
appearance.setPointAttributes(pa);
} else {
ga = createGeometryArray(rendering, colorDepth);
// // Test using the geometry from a sphere primitive
// switch (r)
// {
// case HIGH_RES_SPHERE:
// ga = ItemGeometryGroup.createSphere(50);
// break;
// case LOW_RES_SPHERE:
// ga = ItemGeometryGroup.createSphere(16);
// break;
// }
final PolygonAttributes pa = new PolygonAttributes();
pa.setPolygonMode(PolygonAttributes.POLYGON_FILL);
if (rendering.is2D()) {
pa.setCullFace(PolygonAttributes.CULL_NONE);
pa.setBackFaceNormalFlip(true);
} else {
pa.setCullFace(PolygonAttributes.CULL_BACK);
pa.setBackFaceNormalFlip(false);
}
appearance.setPolygonAttributes(pa);
final ColoringAttributes ca = new ColoringAttributes();
// if (rendering.isHighResolution() || rendering.is2D())
// // Smooth across vertices. Required to show 2D surfaces smoothly
// ca.setShadeModel(ColoringAttributes.SHADE_GOURAUD);
// else
// // Faster polygon rendering with flat shading
// ca.setShadeModel(ColoringAttributes.SHADE_FLAT);
// For indexed models (with 1 normal per vertex) always use smooth shading
ca.setShadeModel(ColoringAttributes.SHADE_GOURAUD);
appearance.setColoringAttributes(ca);
final Material m = new Material();
m.setShininess(128f);
m.setAmbientColor(0.1f, 0.1f, 0.1f);
if (rendering.isHighResolution()) {
// Allow shiny highlights on balls
m.setSpecularColor(0.1f, 0.1f, 0.1f);
} else {
// For flat appearance
m.setSpecularColor(0, 0, 0);
}
appearance.setMaterial(m);
}
return new Shape3D(ga, appearance);
}
use of org.scijava.java3d.Shape3D in project GDSC-SMLM by aherbert.
the class ImageJ3DResultsViewer method createItemMesh.
private static ItemMesh createItemMesh(final ImageJ3DResultsViewerSettingsOrBuilder settings, LocalList<Point3f> points, final Point3f[] sphereSize, float transparency, float[] alpha) {
final Rendering rendering = Rendering.forNumber(settings.getRendering());
final int colorDepth = (alpha != null) ? 4 : 3;
final Shape3D shape = Shape3DHelper.createShape(rendering, colorDepth);
final GeometryArray ga = (GeometryArray) shape.getGeometry();
final Appearance appearance = shape.getAppearance();
// Estimate the largest array required for the data.
// The mesh is created by reference using an array for coords, normals and colors.
final int singlePointVertexSize = ga.getValidVertexCount();
int singlePointIndexSize = 0;
final int stride = Math.max(3, colorDepth);
if (ga instanceof IndexedGeometryArray) {
// Indexed arrays may have much larger index array than the vertex array
singlePointIndexSize = ((IndexedGeometryArray) ga).getIndexCount();
}
final int singlePointSize = Math.max(singlePointIndexSize, stride * singlePointVertexSize);
final long arraySize = (long) points.size() * singlePointSize;
if (arraySize > CustomContentHelper.MAX_ARRAY_SIZE) {
final double capacity = (double) arraySize / CustomContentHelper.MAX_ARRAY_SIZE;
// @formatter:off
IJ.error(TITLE, TextUtils.wrap(String.format("The results will generate data of %d values. " + "This is amount of data is not supported (%.2fx capacity). " + "Please choose a different dataset with fewer points or " + "different rendering model.", arraySize, capacity), 80));
// @formatter:on
return null;
}
// Support drawing as points ...
if (settings.getRendering() == 0) {
final ItemMesh mesh = new ReferenceItemMesh(points.toArray(new Point3f[0]), ga, appearance, null, null, transparency);
if (alpha != null) {
mesh.setItemAlpha(alpha);
}
mesh.getAppearance().getPointAttributes().setPointSize(sphereSize[0].x);
return mesh;
}
final int triangles = Shape3DHelper.getNumberOfTriangles(rendering);
final long size = (long) points.size() * triangles;
if (size > 10000000L) {
final ExtendedGenericDialog egd = new ExtendedGenericDialog(TITLE);
egd.addMessage("The results will generate a large mesh of " + size + " triangles.\nThis may take a long time to render and may run out of memory.");
egd.setOKLabel("Continue");
egd.showDialog();
if (egd.wasCanceled()) {
return null;
}
}
IJ.showStatus("Creating 3D mesh ...");
final ItemMesh mesh = new ReferenceItemMesh(points.toArray(new Point3f[0]), ga, appearance, sphereSize, null, transparency);
if (alpha != null) {
mesh.setItemAlpha(alpha);
}
return mesh;
}
use of org.scijava.java3d.Shape3D in project GDSC-SMLM by aherbert.
the class ImageJ3DResultsViewer method createShape.
@SuppressWarnings("unused")
private static Shape3D createShape(Builder settings) {
final LocalList<Point3f> points = new LocalList<>(1);
points.push(new Point3f());
// We try and match the geometry and appearance of the standard mesh.
// Do this by creating a mesh with a single point and get the Geometry and Appearance.
GeometryArray ga;
CustomMesh mesh;
final float transparency = getTransparency(settings);
// Support drawing as points ...
if (settings.getRendering() == 0) {
mesh = new TransparentItemPointMesh(points, null, transparency);
((ItemPointMesh) mesh).setPointSize((float) settings.getPixelSize());
updateAppearance(mesh, settings);
// Assume the TransparentItemPointMesh sets COLOR_4
ga = (GeometryArray) mesh.getGeometry();
} else {
final Rendering r = Rendering.forNumber(settings.getRendering());
final List<Point3f> point = Shape3DHelper.createLocalisationObject(r);
final Point3f[] vertices = point.toArray(new Point3f[1]);
// Correct the direction
ItemTriangleMesh.checkFacets(vertices);
final double creaseAngle = (r.isHighResolution()) ? 44 : 0;
mesh = new ItemTriangleMesh(vertices, points.toArray(new Point3f[1]), null, null, transparency, creaseAngle, null);
updateAppearance(mesh, settings);
final int nVertices = vertices.length;
ga = new TriangleArray(nVertices, GeometryArray.COORDINATES | GeometryArray.NORMALS);
// Copy the coords and normals. We don't require the vertex colours.
final float[] coords = new float[nVertices * 3];
final float[] normals = new float[nVertices * 3];
final GeometryArray gaToCopy = (GeometryArray) mesh.getGeometry();
gaToCopy.getCoordinates(0, coords);
gaToCopy.getNormals(0, normals);
ga.setCoordinates(0, coords);
ga.setNormals(0, normals);
ga.setValidVertexCount(nVertices);
}
return new Shape3D(ga, mesh.getAppearance());
}
use of org.scijava.java3d.Shape3D in project GDSC-SMLM by aherbert.
the class ImageJ3DResultsViewer method createItemGroup.
private static ItemGeometryGroup createItemGroup(final ImageJ3DResultsViewerSettings.Builder settings, final Point3f[] sphereSize, final LocalList<Point3f> points, float[] alpha, float transparency, Color3f[] colors) {
final Rendering rendering = Rendering.forNumber(settings.getRendering());
// All objects have colour using the appearance not per vertex colours.
// The exception is points which do not support colour from appearance.
final int colorDepth = (rendering == Rendering.POINT) ? 4 : 0;
final Shape3D shape = Shape3DHelper.createShape(rendering, colorDepth);
// Use max so that points get a value of 1
final int triangles = Math.max(Shape3DHelper.getNumberOfTriangles(rendering), 1);
final GeometryArray ga = (GeometryArray) shape.getGeometry();
final long size = (long) points.size() * triangles;
if (size > 10000000L) {
final String name = (rendering == Rendering.POINT) ? "points" : "triangles";
final ExtendedGenericDialog egd = new ExtendedGenericDialog(TITLE);
egd.addMessage("The results will generate a large dataset of " + size + " " + name + ".\nThis may take a long time to render and may run out of memory.");
egd.setOKLabel("Continue");
egd.showDialog();
if (egd.wasCanceled()) {
return null;
}
}
final Appearance appearance = shape.getAppearance();
final TransparencyAttributes ta = new TransparencyAttributes();
ta.setTransparency(transparency);
ta.setTransparencyMode((transparency == 0) ? TransparencyAttributes.NONE : TransparencyAttributes.FASTEST);
appearance.setTransparencyAttributes(ta);
if (rendering == Rendering.POINT) {
appearance.getPointAttributes().setPointSize(sphereSize[0].x);
}
if (settings.getSupportDynamicTransparency()) {
return new ItemGeometryGroup(points.toArray(new Point3f[0]), ga, appearance, sphereSize, colors, alpha);
}
return new OrderedItemGeometryGroup(points.toArray(new Point3f[0]), ga, appearance, sphereSize, colors, alpha);
}
use of org.scijava.java3d.Shape3D in project GDSC-SMLM by aherbert.
the class ImageJ3DResultsViewerDemo method run.
@Override
public void run(String arg) {
if (ImageJ3DViewerUtils.JAVA_3D_VERSION == null) {
IJ.error(TITLE, "Java 3D is not available");
return;
}
final boolean renderingTest = true;
if (renderingTest) {
// Put all the shapes from rendering on a view and see how they look.
final Image3DUniverse univ = new Image3DUniverse();
univ.showAttribute(DefaultUniverse.ATTRIBUTE_SCALEBAR, false);
univ.show();
final ImageWindow3D w = univ.getWindow();
GUI.center(w);
// Test how many vertices a primitive sphere has
float x = 0;
final float y = 0;
final float space = 2.5f;
for (final Rendering rendering : Rendering.values()) {
final Shape3D shape = Shape3DHelper.createShape(rendering, 3);
final Appearance a = shape.getAppearance();
final ItemMesh mesh = new ReferenceItemMesh(new Point3f[] { new Point3f(x, y, 0) }, (GeometryArray) shape.getGeometry(), a, null, null, 0f);
ImageJUtils.log("R=%s %s Vc=%d V=%d T=%d", rendering, shape.getGeometry().getClass().getSimpleName(), mesh.getVerticesCountPerItem(), mesh.getVerticesPerItem(), Shape3DHelper.getNumberOfTriangles(rendering));
if (rendering == Rendering.POINT) {
a.getPointAttributes().setPointSize(10);
}
univ.addCustomMesh(mesh, x + "," + y);
x += space;
}
return;
}
final boolean sphereTest = true;
if (sphereTest) {
// Sphere test
// Put lots of spheres on a view and see how they look.
// Is it worth supporting an ItemTriangleStripMesh so we can control
// the sphere better than the icosahedron?
final Image3DUniverse univ = new Image3DUniverse();
univ.showAttribute(DefaultUniverse.ATTRIBUTE_SCALEBAR, false);
univ.show();
final ImageWindow3D w = univ.getWindow();
GUI.center(w);
// Test how many vertices a primitive sphere has
float x = 0;
float y = 0;
final float space = 2.5f;
Appearance app = null;
for (int d = 0; d < 4; d++) {
final List<Point3f> points = customnode.MeshMaker.createIcosahedron(d, 1f);
final Pair<Point3f[], int[]> p = CustomContentHelper.createIndexedObject(points);
final int v = points.size();
final int t = v / 3;
ImageJUtils.log("Icosahedron divisions = %d, V=%d, T=%d, Vi=%d (%.2f), i=%d", d, v, t, p.getKey().length, v / (double) p.getKey().length, p.getValue().length);
CustomMesh mesh = new ItemTriangleMesh(points.toArray(new Point3f[0]), new Point3f[] { new Point3f(x, y, 0) }, null, null, 0);
app = mesh.getAppearance();
univ.addCustomMesh(mesh, x + "," + y + "," + t);
final float y2 = y + space;
mesh = new ItemIndexedTriangleMesh(p.getKey(), p.getValue(), new Point3f[] { new Point3f(x, y2, 0) }, null, null, 0);
univ.addCustomMesh(mesh, x + "," + y2 + "," + t);
x += space;
}
// Avoid null pointer warnings
if (app == null) {
throw new NullPointerException();
}
// The T=800 sphere looks about the same as the Icosahedron(div=3) T=1280
// This may be a better super-high resolution option.
x = 0;
y += 2 * space;
app = (Appearance) app.cloneNodeComponent(true);
// a.getColoringAttributes().setColor(0, 1, 0);
app.getMaterial().setDiffuseColor(0, 1, 0);
for (int d = 4; d < 50; d += 4) {
// This is a triangle strip array so is more space efficient
final Sphere s = new Sphere(1, Primitive.GENERATE_NORMALS, d);
final int t = s.getNumTriangles();
ImageJUtils.log("Sphere divisions = %d, V=%d, T=%d", d, s.getNumVertices(), t);
final ItemGeometryGroup g = new ItemGeometryGroup(new Point3f[] { new Point3f(x, y, 0) }, (GeometryArray) s.getShape().getGeometry(), app, null, null, null);
final String name = x + "," + y + "," + t;
final CustomContent content = new CustomContent(name, true);
content.getCurrent().display(new ItemGroupNode(g));
univ.addContent(content);
x += space;
}
return;
}
LocalList<Point3f> pointList;
float scale;
if (MemoryPeakResults.isMemoryEmpty()) {
pointList = new LocalList<>();
int range;
// 9 points
range = 1;
// range = 49; // 99^3 = 970299 points
for (int x = -range; x <= range; x++) {
for (int y = -range; y <= range; y++) {
for (int z = -range; z <= range; z++) {
pointList.add(new Point3f(x, y, z));
}
}
}
scale = 0.25f;
} else {
final ImageJ3DResultsViewerSettings.Builder settings = SettingsManager.readImageJ3DResultsViewerSettings(0).toBuilder();
final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
gd.addMessage("Select a dataset to display");
ResultsManager.addInput(gd, settings.getInputOption(), InputSource.MEMORY);
gd.showDialog();
if (gd.wasCanceled()) {
return;
}
final String name = ResultsManager.getInputSource(gd);
settings.setInputOption(name);
SettingsManager.writeSettings(settings);
final MemoryPeakResults results = ResultsManager.loadInputResults(name, false, null, null);
if (MemoryPeakResults.isEmpty(results)) {
IJ.error(TITLE, "No results could be loaded");
IJ.showStatus("");
return;
}
pointList = ImageJ3DResultsViewer.getPoints(results, settings);
if (pointList == null) {
return;
}
scale = 10f;
}
final Image3DUniverse univ = new Image3DUniverse();
univ.showAttribute(DefaultUniverse.ATTRIBUTE_SCALEBAR, false);
univ.show();
final ImageWindow3D w = univ.getWindow();
GUI.center(w);
final View view = univ.getViewer().getView();
view.setTransparencySortingPolicy(View.TRANSPARENCY_SORT_GEOMETRY);
// I am not sure if this is required if objects are sorted.
// view.setDepthBufferFreezeTransparent(false)
IJ.showStatus("Creating points ...");
final Point3f[] points = pointList.toArray(new Point3f[0]);
final Point3f[] sizes = new Point3f[] { new Point3f(scale, scale, scale) };
final Appearance appearance = new Appearance();
final TransparencyAttributes ta = new TransparencyAttributes();
ta.setTransparency(0.5f);
ta.setTransparencyMode(TransparencyAttributes.FASTEST);
appearance.setTransparencyAttributes(ta);
final ItemGeometryGroup pointGroup = new ItemGeometryGroup(points, null, appearance, sizes, null, null);
// pointGroup = new OrderedItemGeometryGroup(points, null, appearance, sizes, null, null);
// // This supports transparency sorting
// BranchGroup bg = new BranchGroup();
// bg.addChild(pointGroup);
// bg.compile();
// univ.getScene().addChild(bg);
// // This does not since ContentInstant uses an OrderedPath to show:
// // the content; the object bounding box, coordinate system and point list
// final Content c = new Content("Test");
// final ContentInstant content = c.getCurrent();
// content.display(new PointGroupNode(pointGroup));
// univ.addContent(c);
// This does since ItemGeometryNode uses a Group to show the points as individual shapes
// and the CustomContentInstant uses a group not an ordered group so show all the adornments.
IJ.showStatus("Displaying points ...");
final CustomContent c = new CustomContent("Test", false);
final ContentInstant content = c.getCurrent();
content.display(new ItemGroupNode(pointGroup));
univ.addContent(c);
IJ.showStatus("Done");
}
Aggregations