use of customnode.CustomLineMesh in project TrakEM2 by trakem2.
the class Display3D method createMesh.
/**
* Returns a function that returns a Content object.
* Does NOT add the Content to the universe; it merely creates it.
*/
public Callable<Content> createMesh(final ProjectThing pt, final Displayable displ, final int resample) {
// OBSOLETE
final double scale = 1.0;
return new Callable<Content>() {
@Override
public Content call() {
Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
try {
// the list 'triangles' is really a list of Point3f, which define a triangle every 3 consecutive points. (TODO most likely Bene Schmid got it wrong: I don't think there's any need to have the points duplicated if they overlap in space but belong to separate triangles.)
final List<Point3f> triangles;
// boolean no_culling_ = false;
final Class<?> c;
final boolean line_mesh;
final int line_mesh_mode;
if (null == displ) {
c = null;
line_mesh = false;
line_mesh_mode = Integer.MAX_VALUE;
} else {
c = displ.getClass();
line_mesh = Tree.class.isAssignableFrom(c) || Polyline.class == c;
if (Tree.class.isAssignableFrom(c))
line_mesh_mode = CustomLineMesh.PAIRWISE;
else if (Polyline.class == c)
line_mesh_mode = CustomLineMesh.CONTINUOUS;
else
// disabled
line_mesh_mode = Integer.MAX_VALUE;
}
List<Point3f> extra_triangles = null;
List<Color3f> triangle_colors = null, extra_triangle_colors = null;
int rs = resample;
if (displ instanceof AreaContainer) {
if (// will adjust this.resample, and return it (even if it's a default value)
-1 == resample)
// will adjust this.resample, and return it (even if it's a default value)
rs = Display3D.this.resample = adjustResampling();
else
rs = Display3D.this.resample;
}
if (AreaList.class == c) {
triangles = ((AreaList) displ).generateTriangles(scale, rs);
// triangles = removeNonManifold(triangles);
} else if (Ball.class == c) {
final double[][][] globe = Ball.generateGlobe(12, 12);
triangles = ((Ball) displ).generateTriangles(scale, globe);
} else if (displ instanceof Line3D) {
// Pipe and Polyline
// adjustResampling(); // fails horribly, needs first to correct mesh-generation code
triangles = ((Line3D) displ).generateTriangles(scale, 12, 1);
} else if (displ instanceof Tree<?>) {
// A 3D wire skeleton, using CustomLineMesh
final Tree.MeshData skeleton = ((Tree<?>) displ).generateSkeleton(scale, 12, 1);
triangles = skeleton.verts;
triangle_colors = skeleton.colors;
if (displ instanceof Treeline) {
final Tree.MeshData tube = ((Treeline) displ).generateMesh(scale, 12);
extra_triangles = tube.verts;
extra_triangle_colors = tube.colors;
} else if (displ instanceof AreaTree) {
final Tree.MeshData mesh = ((AreaTree) displ).generateMesh(scale, rs);
extra_triangles = mesh.verts;
extra_triangle_colors = mesh.colors;
}
// avoid issues with MultiMesh
if (null != extra_triangles && extra_triangles.isEmpty())
extra_triangles = null;
} else if (Connector.class == c) {
final Tree.MeshData octopus = ((Connector) displ).generateMesh(scale, 12);
triangles = octopus.verts;
triangle_colors = octopus.colors;
} else if (null == displ && pt.getType().equals("profile_list")) {
triangles = Profile.generateTriangles(pt, scale);
// no_culling_ = true;
} else {
Utils.log("Unrecognized type for 3D mesh generation: " + (null != displ ? displ.getClass() : null) + " : " + displ);
triangles = null;
}
// safety checks
if (null == triangles) {
Utils.log("Some error ocurred: can't create triangles for " + displ);
return null;
}
if (0 == triangles.size()) {
Utils.log2("Skipping empty mesh for " + displ.getTitle());
return null;
}
if (!line_mesh && 0 != triangles.size() % 3) {
Utils.log2("Skipping non-multiple-of-3 vertices list generated for " + displ.getTitle());
return null;
}
final Color color;
final float alpha;
final String title;
if (null != displ) {
color = displ.getColor();
alpha = displ.getAlpha();
title = makeTitle(displ);
} else if (pt.getType().equals("profile_list")) {
// for profile_list: get from the first (what a kludge; there should be a ZDisplayable ProfileList object)
final Object obp = ((ProjectThing) pt.getChildren().get(0)).getObject();
if (null == obp)
return null;
final Displayable di = (Displayable) obp;
color = di.getColor();
alpha = di.getAlpha();
title = makeProfileListTitle(pt);
} else {
title = pt.toString() + " #" + pt.getId();
color = null;
alpha = 1.0f;
}
// Why for all? Above no_culling_ is set to true or false, depending upon type. --> Because with transparencies it looks proper and better when no_culling is true.
// for ALL
final boolean no_culling = true;
Content ct = null;
try {
final Color3f c3 = new Color3f(color);
// If it exists, remove and add as new:
universe.removeContent(title);
final CustomMesh cm;
if (line_mesh) {
// ct = universe.createContent(new CustomLineMesh(triangles, line_mesh_mode, c3, 0), title);
cm = new CustomLineMesh(triangles, line_mesh_mode, c3, 0);
} else if (no_culling) {
// create a mesh with the same color and zero transparency (that is, full opacity)
final CustomTriangleMesh mesh = new CustomTriangleMesh(triangles, c3, 0);
// Set mesh properties for double-sided triangles
final PolygonAttributes pa = mesh.getAppearance().getPolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
pa.setBackFaceNormalFlip(true);
mesh.setColor(c3);
// After setting properties, add to the viewer
// ct = universe.createContent(mesh, title);
cm = mesh;
} else {
// ct = universe.createContent(new CustomTriangleMesh(triangles, c3, 0), title);
cm = new CustomTriangleMesh(triangles, c3, 0);
}
if (null != triangle_colors)
cm.setColor(triangle_colors);
if (null == extra_triangles || 0 == extra_triangles.size()) {
ct = universe.createContent(cm, title);
} else {
final CustomTriangleMesh extra = new CustomTriangleMesh(extra_triangles, c3, 0);
if (null != extra_triangle_colors) {
// Set mesh properties for double-sided triangles
final PolygonAttributes pa = extra.getAppearance().getPolygonAttributes();
pa.setCullFace(PolygonAttributes.CULL_NONE);
pa.setBackFaceNormalFlip(true);
extra.setColor(extra_triangle_colors);
}
ct = universe.createContent(new CustomMultiMesh(Arrays.asList(new CustomMesh[] { cm, extra })), title);
}
// Set general content properties
ct.setTransparency(1f - alpha);
// Default is unlocked (editable) transformation; set it to locked:
ct.setLocked(true);
// register mesh title
synchronized (ht_pt_meshes) {
ht_pt_meshes.put(pt, ct.getName());
}
} catch (final Throwable e) {
Utils.logAll("Mesh generation failed for \"" + title + "\" from " + pt);
IJError.print(e);
e.printStackTrace();
}
Utils.log2(pt.toString() + " n points: " + triangles.size());
return ct;
} catch (final Exception e) {
IJError.print(e);
return null;
}
}
};
}
Aggregations