Oclusion of AWTText



I have a graph, where the nodes and the arches have labels.
These labels are never covered by other nodes or arches that are more nearby. In the figure of the example, one sees that the label "b" should be totally covered by the sphere of the node "Name" and the label "addr" to should be covered partially by the sphere of the node " Name", but this does not happen (mistake marked with a red circle). How can I do in order that these texts are covered by the spheres?

The spheres are Spatial and the labels are AWTText (extends Text implements JmeText).

The solution must be related to render.
I copy the classes entrusted to generate the label and how it is called.



Tengo un grafo, donde los nodos y los arcos tienen rótulos.
Esos rótulos nunca son tapados por otros nodos o arcos que están más cerca. En la figura del ejemplo, se ve que el rótulo “b” debería estar totalmente tapado por la esfera del nodo “Name” y el rótulo “addr” debería estar tapado parcialmente por la esfera del nodo “Name”, pero esto no ocurre (error marcado con un círculo rojo). ¿Cómo puedo hacer para que esos textos sean tapados por las esferas?

Las esferas son Spatial y los rótulos son AWTText (extends Text implements JmeText).

La solución debe estar relacionada con el renderizado.
Copio las clases encargadas de generar el rótulo y cómo es llamada.

[java]protected void crearLabel (String label, ColorRGBA color, float size) {
AWTTextFactory textFactory;
textFactory = new AWTTextFactory(font);
label= (AWTText)textFactory.createText (label, size, Font.BOLD);
label.setTextColor (color);
label.setModelBound (new BoundingBox());
label.updateModelBound ();
label.setRenderQueueMode (Renderer.QUEUE_ORTHO);
}[/java]

[java]
package com.elementosGrafoJME;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.jme.image.Image;
import com.jme.image.Texture;
import com.jme.scene.state.lwjgl.LWJGLTextureState;
import com.jme.util.TextureManager;
import com.jmex.font3d.JmeText;
import com.jmex.font3d.TextFactory;

public class AWTTextFactory implements TextFactory {

private static final int CHARACTER_COUNT = 16;//16;
private static final int MIN_CHAR_CODE = 32;
private static final int MAX_CHAR_CODE = 287; // 32 + 255
private static final Logger loggerText = Logger.getLogger(LWJGLTextureState.class.getName());

private Font font;
private Texture fontTexture;

public AWTTextFactory(Font f){
font = f;
loggerText.setLevel(Level.OFF);
}

public Font getFont() {
return font;
}

public JmeText createText (String text, float size, int flags) {
// TODO if texture manager would cache generated textures, they could be reused
// generate the texture
if ((fontTexture == null) || (fontTexture.getImage().getWidth() / CHARACTER_COUNT < size)){
fontTexture = new Texture();//Texture.MM_NEAREST_NEAREST);

//fontTexture.setMipmapState(Texture.MM_NEAREST_NEAREST);
fontTexture.setImage(generateImage(size, flags));
}

// create the text object
//System.out.println(text + " *** " + size);
AWTText awtText = new AWTText(this, text, size);
return awtText;
}

public Texture getFontTexture() {
return fontTexture;
}

private Image generateImage(float size, int flags) {
// create a temporary image: grab graphics -> grab font metrics (awt is such a mess)
BufferedImage bufferedImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = bufferedImage.createGraphics();
graphics.setFont(font.deriveFont(flags, size));
FontMetrics metrics = graphics.getFontMetrics();
Rectangle2D r = metrics.getMaxCharBounds(graphics);
// TODO try to avoid image rescaling
int charSize = metrics.getHeight();

// create the real image

//int sizeBu = sizeBufferReturn(charSize * CHARACTER_COUNT);
//System.out.println("@@--> TAMAÑO TEXTO: " + sizeBu);
bufferedImage = new BufferedImage(charSize * CHARACTER_COUNT,
charSize * CHARACTER_COUNT, BufferedImage.TYPE_INT_ARGB);

//bufferedImage = new BufferedImage(sizeBu,sizeBu, BufferedImage.TYPE_INT_ARGB);
graphics = bufferedImage.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
//graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
//graphics.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT);

graphics.setFont(font.deriveFont(flags, size));
graphics.setColor(new Color(1f, 1f, 1, 1f));
graphics.setBackground(new Color(0f, 0f, 0f, 0f));
metrics = graphics.getFontMetrics();

// display lists could be generated here to support non-monospaced fonts
float xPosition, yPosition;
for (int i = 0; i <= MAX_CHAR_CODE; ++i) {
xPosition = i % CHARACTER_COUNT * charSize + charSize / 2
- metrics.charWidth(MIN_CHAR_CODE + i) / 2;
yPosition = i / CHARACTER_COUNT * charSize + metrics.getAscent();
graphics.drawString(String.valueOf(Character.toChars(MIN_CHAR_CODE + i)),
xPosition, yPosition);
}

// it would be nice if the texture could be cached by TextureManager
// this kind of conversion also belongs to ImageUtils
return TextureManager.loadImage(bufferedImage, true);
}

}
[/java]

[java]
package com.elementosGrafoJME;

import com.jme.scene.Text;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jmex.font3d.JmeText;
import com.jmex.font3d.TextFactory;

public class AWTText extends Text implements JmeText {

private static final long serialVersionUID = 1L;
private static final float CHARACTER_COUNT = 16;

private static AlphaState sharedAlpha = null;
private AWTTextFactory textFactory;
int sizeReal= 30;

public AWTText (AWTTextFactory factory, String text, float size) {
super(null, text);
textFactory = factory;
configure();
setLocalScale(size / CHARACTER_COUNT);
}

protected void configure() {
if (DisplaySystem.getDisplaySystem().getRenderer()!=null) {
TextureState textureState = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
textureState.setTexture (textFactory.getFontTexture());
textureState.setEnabled (true);
setRenderState (textureState);

if (sharedAlpha == null) {
sharedAlpha = DisplaySystem.getDisplaySystem().getRenderer().createAlphaState();
}
sharedAlpha.setSrcFunction (AlphaState.SB_SRC_ALPHA_SATURATE);
sharedAlpha.setDstFunction (AlphaState.DB_ONE_MINUS_SRC_ALPHA);
sharedAlpha.setBlendEnabled (true);
setRenderState (sharedAlpha);

setLocalScale(textFactory.getFont().getSize2D());
}
}

public TextFactory getFactory() {
return textFactory;
}

public int getFlags() {
return 0; // what's the purpose of this method?
}


public void appendText(String text) {
print(getText() + text);
}

public void setText(String text) {
print(text);
}



public float getSize() {
// i wonder what size should mean
return getHeight();
}

public void setSize(float size) {
// attempt to scale the font to the specified height
setLocalScale(2 * size / CHARACTER_COUNT);
// warn
// LoggingSystem.getLogger().warning("Scaling bitmap fonts is discouraged.");
}

public void setSizeReal(int size) {
sizeReal= size;
}

public int getSizeReal() {
return sizeReal;
}

public void setFactory(AWTTextFactory factory) {
textFactory = factory;
configure();
}

public void setTextSizePerspectiva (float distanciaCamara) {
this.setSize(6000 / distanciaCamara);
}

}[/java]