private void buildFrameContent( final SpotCollection spots, final Integer frame, final double radiusRatio, final FeatureColorGenerator<Spot> spotColorGenerator) { final Map<Spot, Point4d> centers = new HashMap<Spot, Point4d>(spots.getNSpots(frame, false)); final Map<Spot, Color4f> colors = new HashMap<Spot, Color4f>(spots.getNSpots(frame, false)); final double[] coords = new double[3]; for (final Iterator<Spot> it = spots.iterator(frame, false); it.hasNext(); ) { final Spot spot = it.next(); TMUtils.localize(spot, coords); final Double radius = spot.getFeature(Spot.RADIUS); final double[] pos = new double[] {coords[0], coords[1], coords[2], radius * radiusRatio}; centers.put(spot, new Point4d(pos)); final Color4f col = new Color4f(spotColorGenerator.color(spot)); col.w = 0f; colors.put(spot, col); } final SpotGroupNode<Spot> blobGroup = new SpotGroupNode<Spot>(centers, colors); final ContentInstant contentThisFrame = new ContentInstant("Spots_frame_" + frame); try { contentThisFrame.display(blobGroup); } catch (final BadTransformException bte) { System.err.println( "Bad content for frame " + frame + ". Generated an exception:\n" + bte.getLocalizedMessage() + "\nContent was:\n" + blobGroup.toString()); } // Set visibility: if (spots.getNSpots(frame, true) > 0) { blobGroup.setVisible(spots.iterable(frame, true)); } contentAllFrames.put(frame, contentThisFrame); blobs.put(frame, blobGroup); }
@Override public void modelChanged(final ModelChangeEvent event) { if (DEBUG) { System.out.println( "[SpotDisplayer3D: modelChanged() called with event ID: " + event.getEventID()); System.out.println(event); } switch (event.getEventID()) { case ModelChangeEvent.SPOTS_COMPUTED: makeSpotContent(); break; case ModelChangeEvent.SPOTS_FILTERED: for (final int frame : blobs.keySet()) { final SpotGroupNode<Spot> frameBlobs = blobs.get(frame); for (final Iterator<Spot> it = model.getSpots().iterator(frame, false); it.hasNext(); ) { final Spot spot = it.next(); final boolean visible = spot.getFeature(SpotCollection.VISIBLITY).compareTo(SpotCollection.ZERO) > 0; frameBlobs.setVisible(spot, visible); } } break; case ModelChangeEvent.TRACKS_COMPUTED: trackContent = makeTrackContent(); universe.removeContent(TRACK_CONTENT_NAME); universe.addContent(trackContent); break; case ModelChangeEvent.TRACKS_VISIBILITY_CHANGED: updateTrackColors(); trackNode.setTrackVisible(model.getTrackModel().trackIDs(true)); break; case ModelChangeEvent.MODEL_MODIFIED: { /* * Deal with spots first. */ // Useful fields. @SuppressWarnings("unchecked") final FeatureColorGenerator<Spot> spotColorGenerator = (FeatureColorGenerator<Spot>) displaySettings.get(KEY_SPOT_COLORING); final double radiusRatio = (Double) displaySettings.get(KEY_SPOT_RADIUS_RATIO); // Iterate each spot of the event. final Set<Spot> spotsModified = event.getSpots(); for (final Spot spot : spotsModified) { final int spotFlag = event.getSpotFlag(spot); final int frame = spot.getFeature(Spot.FRAME).intValue(); final SpotGroupNode<Spot> spotGroupNode = blobs.get(frame); switch (spotFlag) { case ModelChangeEvent.FLAG_SPOT_REMOVED: spotGroupNode.remove(spot); break; case ModelChangeEvent.FLAG_SPOT_ADDED: { // Sphere location and radius final double[] coords = new double[3]; TMUtils.localize(spot, coords); final Double radius = spot.getFeature(Spot.RADIUS); final double[] pos = new double[] {coords[0], coords[1], coords[2], radius * radiusRatio}; final Point4d center = new Point4d(pos); // Sphere color final Color4f color = new Color4f(spotColorGenerator.color(spot)); color.w = 0; // Do we have an empty frame? if (null == spotGroupNode) { /* * We then just give up. I dig really hard on an elegant * way to add a new ContentInstant for a missing frame, * but found no satisfying way. There is no good way to * add spots to an empty frame. The way I found is very * similar to closing the 3D viewer and re-opening it, * therefore I let the user do it. * * So because of this, the SpotDisplayer3D is only a * partial ModelListener. */ System.err.println( "[SpotDisplayer3D] The TrackMate 3D viewer cannot deal with adding a spot to an empty frame."); } else { spotGroupNode.add(spot, center, color); } break; } case ModelChangeEvent.FLAG_SPOT_FRAME_CHANGED: { // Where did it belonged? Integer targetFrame = -1; for (final Integer f : blobs.keySet()) { if (blobs.get(f).centers.containsKey(spot)) { targetFrame = f; break; } } if (targetFrame < 0) { System.err.println( "[SpotDisplayer3D] Could not find the frame spot " + spot + " belongs to."); return; } blobs.get(targetFrame).remove(spot); // Sphere location and radius final double[] coords = new double[3]; TMUtils.localize(spot, coords); final Double radius = spot.getFeature(Spot.RADIUS); final double[] pos = new double[] {coords[0], coords[1], coords[2], radius * radiusRatio}; final Point4d center = new Point4d(pos); // Sphere color final Color4f color = new Color4f(spotColorGenerator.color(spot)); color.w = 0; if (null == spotGroupNode) { /* * We then just give up. See above. */ System.err.println( "[SpotDisplayer3D] The TrackMate 3D viewer cannot deal with moving a spot to an empty frame."); } else { spotGroupNode.add(spot, center, color); } break; } case ModelChangeEvent.FLAG_SPOT_MODIFIED: { if (null != spotGroupNode) { spotGroupNode.remove(spot); // Sphere location and radius final double[] coords = new double[3]; TMUtils.localize(spot, coords); final Double radius = spot.getFeature(Spot.RADIUS); final double[] pos = new double[] {coords[0], coords[1], coords[2], radius * radiusRatio}; final Point4d center = new Point4d(pos); // Sphere color final Color4f color = new Color4f(spotColorGenerator.color(spot)); color.w = 0; spotGroupNode.add(spot, center, color); } break; } default: { System.err.println("[SpotDisplayer3D] Unknown spot flag ID: " + spotFlag); } } } /* * Deal with edges */ for (final DefaultWeightedEdge edge : event.getEdges()) { final int edgeFlag = event.getEdgeFlag(edge); switch (edgeFlag) { case ModelChangeEvent.FLAG_EDGE_ADDED: case ModelChangeEvent.FLAG_EDGE_MODIFIED: case ModelChangeEvent.FLAG_EDGE_REMOVED: { if (null == trackNode) { trackContent = makeTrackContent(); universe.removeContent(TRACK_CONTENT_NAME); universe.addContent(trackContent); } else { trackNode.makeMeshes(); updateTrackColors(); } break; } default: { System.err.println("[SpotDisplayer3D] Unknown edge flag ID: " + edgeFlag); } } } break; } default: { System.err.println("[SpotDisplayer3D] Unknown event ID: " + event.getEventID()); } } }
public void draw(GL2 gl, GLU glu, GLDrawState ds) { final Color4f highColor = new Color4f(0.0f, 1.0f, 0.0f, 1.0f); final Color4f lowColor = new Color4f(1.0f, 1.0f, 1.0f, 1.0f); Color4f[][] trueCols = new Color4f[mapHeight][mapWidth]; // InternalTerrainTile tiles[][] = ds.getGameMap().getTerrainMatrix(); // Update colors for (int j = 0; j < mapHeight; j++) { for (int i = 0; i < mapWidth; i++) { // float fluxAmount = getMapHeight(i, j)/64.f; // System.out.println(flux[j/DENSITY][i/DENSITY] + " " + fluxAmount); // float fluxAmount = (float)tiles[i/DENSITY][j/DENSITY].getFlux(); Color4f tintColor = new Color4f(); Color4f trueColor = new Color4f(); tintColor.interpolate(lowColor, highColor, 0); // System.out.println(actualHeight/maxHeight); trueColor.interpolate(cols[j][i], tintColor, 1.0f); trueColor.w = cols[j][i].w; trueCols[j][i] = trueColor; // If void, see through to the background. /*if(tiles[i/DENSITY][j/DENSITY] == TerrainType.VOID){ trueCols[j][i].w = 0.0f; }*/ } } // System.out.println(map.getTerrainMatrix()[0][0].getFlux() + " " + MAX_FLUX_PER_TILE + " " + // trueCols[0][0].x); int k = 0; for (int j = 0; j < mapHeight; j++) { for (int i = 0; i < mapWidth; i++) { colors[k] = trueCols[j][i].x; colors[k + 1] = trueCols[j][i].y; colors[k + 2] = trueCols[j][i].z; colors[k + 3] = trueCols[j][i].w; float norm = (float) Math.sqrt( trueCols[j][i].x * trueCols[j][i].x + trueCols[j][i].y * trueCols[j][i].y + trueCols[j][i].z * trueCols[j][i].z); float val = (norm < 0.3f) ? 0.0f : 0.9f; colorNorm[k] = val; colorNorm[k + 1] = val; colorNorm[k + 2] = val; colorNorm[k + 3] = 1.0f; k += 4; } } if (tex == null && texturePath != null) { tex = GLGameRenderer.textureCache.getResource(texturePath, texturePath).tex; texturePath = null; } gl.glPushMatrix(); // gl.glTranslatef(1.5f, 0.0f, 1.5f); if (tex != null) { System.out.println("Using texture"); gl.glEnable(GL2.GL_TEXTURE_2D); tex.bind(gl); gl.glBegin(GL2.GL_TRIANGLE_STRIP); for (int i = 0; i < indices.length; i++) { gl.glTexCoord2f(texCoords[indices[i] * 2], texCoords[indices[i] * 2 + 1]); gl.glColor4f( colorNorm[indices[i] * 4], colorNorm[indices[i] * 4 + 1], colorNorm[indices[i] * 4 + 2], colorNorm[indices[i] * 4 + 3]); gl.glNormal3f( normals[indices[i] * 3], normals[indices[i] * 3 + 1], normals[indices[i] * 3 + 2]); gl.glVertex3f( vertices[indices[i] * 3], vertices[indices[i] * 3 + 1], vertices[indices[i] * 3 + 2]); } gl.glEnd(); } else { gl.glEnable(gl.GL_BLEND); gl.glBegin(GL2.GL_TRIANGLE_STRIP); for (int i = 0; i < indices.length; i++) { gl.glColor4f( colors[indices[i] * 4], colors[indices[i] * 4 + 1], colors[indices[i] * 4 + 2], colors[indices[i] * 4 + 3]); gl.glNormal3f( normals[indices[i] * 3], normals[indices[i] * 3 + 1], normals[indices[i] * 3 + 2]); gl.glVertex3f( vertices[indices[i] * 3], vertices[indices[i] * 3 + 1], vertices[indices[i] * 3 + 2]); } gl.glEnd(); gl.glDisable(gl.GL_BLEND); } gl.glPopMatrix(); boolean showGrid = RenderConfiguration.showGridlines(); if (showGrid) { gl.glColor4f(0.5f, 0.5f, 0.5f, 1.0f); gl.glNormal3f(0.0f, 1.0f, 0.0f); gl.glLineWidth(1.0f); // do the horizontal gridlines /* gl.glBegin(GL2.GL_LINES); for (int j = 1; j < map.getHeight(); ++j) { gl.glVertex3f(0.0f, 0.0f, j); gl.glVertex3f(map.getWidth(), 0.0f, j); } gl.glEnd(); */ gl.glBegin(GL2.GL_LINE_STRIP); for (int j = 0; j < mapHeight; j++) { if ((j + 1) % DENSITY != 0) { continue; } if ((j + 1) % (DENSITY * 2) == 0) { for (int i = 0; i < mapWidth; i++) { Vector3f p; Vector3f pOne; Vector3f pTwo; pOne = points[j][i]; p = new Vector3f(0.0f, 0.0f, 0.0f); p.add(pOne); if (j < mapHeight - 1 && i > 0) { pTwo = points[j + 1][i - 1]; p.add(pTwo); p.scale(.5f); } gl.glVertex3f(p.x, p.y + 0.01f, p.z); pOne = points[j][i]; p = new Vector3f(0.0f, 0.0f, 0.0f); p.add(pOne); if (j < mapHeight - 1) { pTwo = points[j + 1][i]; p.add(pTwo); p.scale(.5f); } gl.glVertex3f(p.x, p.y + 0.01f, p.z); } } else { for (int i = mapWidth - 1; i >= 0; i--) { Vector3f p; Vector3f pOne; Vector3f pTwo; pOne = points[j][i]; p = new Vector3f(0.0f, 0.0f, 0.0f); p.add(pOne); if (j < mapHeight - 1) { pTwo = points[j + 1][i]; p.add(pTwo); p.scale(.5f); } gl.glVertex3f(p.x, p.y + 0.01f, p.z); pOne = points[j][i]; p = new Vector3f(0.0f, 0.0f, 0.0f); p.add(pOne); if (j < mapHeight - 1 && i > 0) { pTwo = points[j + 1][i - 1]; p.add(pTwo); p.scale(.5f); } gl.glVertex3f(p.x, p.y + 0.01f, p.z); } } } gl.glEnd(); // do the vertical gridlines /* gl.glBegin(GL2.GL_LINES); for (int j = 1; j < map.getWidth(); ++j) { gl.glVertex3f(j, 0.0f, 0.0f); gl.glVertex3f(j, 0.0f, map.getHeight()); } gl.glEnd(); */ gl.glBegin(GL2.GL_LINE_STRIP); for (int i = 0; i < mapWidth; i++) { if ((i + 1) % DENSITY != 0) { continue; } if ((i + 1) % (DENSITY * 2) == 0) { for (int j = 0; j < mapHeight; j++) { Vector3f p; Vector3f pOne; Vector3f pTwo; pOne = points[j][i]; p = new Vector3f(0.0f, 0.0f, 0.0f); p.add(pOne); if (j > 0 && i < mapWidth - 1) { pTwo = points[j - 1][i + 1]; p.add(pTwo); p.scale(.5f); } gl.glVertex3f(p.x, p.y + 0.01f, p.z); pOne = points[j][i]; p = new Vector3f(0.0f, 0.0f, 0.0f); p.add(pOne); if (i < mapWidth - 1) { pTwo = points[j][i + 1]; p.add(pTwo); p.scale(.5f); } gl.glVertex3f(p.x, p.y + 0.01f, p.z); } } else { for (int j = mapHeight - 1; j >= 0; j--) { Vector3f p; Vector3f pOne; Vector3f pTwo; pOne = points[j][i]; p = new Vector3f(0.0f, 0.0f, 0.0f); p.add(pOne); if (i < mapWidth - 1) { pTwo = points[j][i + 1]; p.add(pTwo); p.scale(.5f); } gl.glVertex3f(p.x, p.y + 0.01f, p.z); pOne = points[j][i]; p = new Vector3f(0.0f, 0.0f, 0.0f); p.add(pOne); if (j > 0 && i < mapWidth - 1) { pTwo = points[j - 1][i + 1]; p.add(pTwo); p.scale(.5f); } gl.glVertex3f(p.x, p.y + 0.01f, p.z); } } } gl.glEnd(); } }