Hi,
I am trying to create Font3D for a Text3D. However, I get the following error.
I think the location of creating Font3D is not supposed to be where it is now. But, I do not know why.
I will post the code, and the error messages.
thanks
/*
- Copyright © 2003-2006 jMonkeyEngine All rights reserved. Redistribution and
- use in source and binary forms, with or without modification, are permitted
- provided that the following conditions are met: * Redistributions of source
- code must retain the above copyright notice, this list of conditions and the
- following disclaimer. * Redistributions in binary form must reproduce the
- above copyright notice, this list of conditions and the following disclaimer
- in the documentation and/or other materials provided with the distribution. *
- Neither the name of 'jMonkeyEngine' nor the names of its contributors may be
- used to endorse or promote products derived from this software without
- specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
- HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
- OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Point;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.concurrent.Callable;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Geometry;
import com.jme.scene.Node;
import com.jme.scene.SceneElement;
import com.jme.scene.Text;
import com.jme.scene.state.RenderState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.util.GameTaskQueue;
import com.jme.util.GameTaskQueueManager;
import com.jmex.awt.JMECanvas;
import com.jmex.awt.SimpleCanvasImpl;
import com.jmex.font3d.Font3D;
import com.jmex.font3d.Text3D;
import com.jmex.font3d.TextFactory;
public class Test extends JFrame {
int width = 640, height = 480;
MyImplementor impl;
private CameraHandler camhand;
private Canvas glCanvas;
private Node root;
private Geometry grid;
public static void main(String[] args) {
new Test();
}
public Test() {
try {
init();
setLocationRelativeTo(null);
setVisible(true);
new Thread() {
{
setDaemon(true);
}
public void run() {
try {
while (true) {
if (isVisible())
glCanvas.repaint();
Thread.sleep(2);
}
} catch (InterruptedException e) {
}
}
}.start();
} catch (Exception ex) {
}
}
private void init() throws Exception {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setFont(new Font("Arial", 0, 12));
JPanel canvasPanel = new JPanel();
canvasPanel.setLayout(new BorderLayout());
canvasPanel.add(getGlCanvas(), BorderLayout.CENTER);
getContentPane().add(canvasPanel, BorderLayout.CENTER);
setSize(new Dimension(1024, 768));
}
private Color makeColor(ColorRGBA rgba, boolean useAlpha) {
return new Color(rgba.r, rgba.g, rgba.b, (useAlpha ? rgba.a : 1f));
}
private ColorRGBA makeColorRGBA(Color color) {
return new ColorRGBA(color.getRed() / 255f, color.getGreen() / 255f,
color.getBlue() / 255f, color.getAlpha() / 255f);
}
protected Canvas getGlCanvas() {
if (glCanvas == null) {
glCanvas = DisplaySystem.getDisplaySystem().createCanvas(width, height);
glCanvas.setMinimumSize(new Dimension(100, 100));
glCanvas.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent ce) {
doResize();
}
});
camhand = new CameraHandler();
glCanvas.addMouseWheelListener(camhand);
glCanvas.addMouseListener(camhand);
glCanvas.addMouseMotionListener(camhand);
// Important! Here is where we add the guts to the canvas:
impl = new MyImplementor(width, height);
((JMECanvas) glCanvas).setImplementor(impl);
Callable<?> exe = new Callable() {
public Object call() {
forceUpdateToSize();
return null;
}
};
GameTaskQueueManager.getManager().getQueue(GameTaskQueue.RENDER).enqueue(exe);
}
return glCanvas;
}
public void forceUpdateToSize() {
// force a resize to ensure proper canvas size.
glCanvas.setSize(glCanvas.getWidth(), glCanvas.getHeight() + 1);
glCanvas.setSize(glCanvas.getWidth(), glCanvas.getHeight() - 1);
}
class CameraHandler extends MouseAdapter implements MouseMotionListener,
MouseWheelListener {
Point last = new Point(0, 0);
Vector3f focus = new Vector3f();
private Vector3f vector = new Vector3f();
private Quaternion rot = new Quaternion();
public void mouseDragged(final MouseEvent arg0) {
Callable<?> exe = new Callable() {
public Object call() {
int difX = last.x - arg0.getX();
int difY = last.y - arg0.getY();
int mult = arg0.isShiftDown() ? 10 : 1;
last.x = arg0.getX();
last.y = arg0.getY();
int mods = arg0.getModifiers();
if ((mods & InputEvent.BUTTON1_MASK) != 0) {
rotateCamera(Vector3f.UNIT_Y, difX * 0.0025f);
rotateCamera(impl.getRenderer().getCamera().getLeft(),
-difY * 0.0025f);
}
if ((mods & InputEvent.BUTTON2_MASK) != 0 && difY != 0) {
zoomCamera(difY * mult);
}
if ((mods & InputEvent.BUTTON3_MASK) != 0) {
panCamera(-difX, -difY);
}
return null;
}
};
GameTaskQueueManager.getManager().getQueue(GameTaskQueue.RENDER)
.enqueue(exe);
}
public void mouseMoved(MouseEvent arg0) {
}
public void mousePressed(MouseEvent arg0) {
last.x = arg0.getX();
last.y = arg0.getY();
}
public void mouseWheelMoved(final MouseWheelEvent arg0) {
Callable<?> exe = new Callable() {
public Object call() {
zoomCamera(arg0.getWheelRotation()
* (arg0.isShiftDown() ? -100 : -20));
return null;
}
};
GameTaskQueueManager.getManager().getQueue(GameTaskQueue.RENDER)
.enqueue(exe);
}
public void recenterCamera() {
Callable<?> exe = new Callable() {
public Object call() {
Camera cam = impl.getRenderer().getCamera();
Vector3f.ZERO.subtract(focus, vector);
cam.getLocation().addLocal(vector);
focus.addLocal(vector);
cam.onFrameChange();
return null;
}
};
GameTaskQueueManager.getManager().getQueue(GameTaskQueue.RENDER)
.enqueue(exe);
}
private void rotateCamera(Vector3f axis, float amount) {
Camera cam = impl.getRenderer().getCamera();
if (axis.equals(cam.getLeft())) {
float elevation = -FastMath.asin(cam.getDirection().y);
amount = Math.min(Math.max(elevation + amount,
-FastMath.HALF_PI), FastMath.HALF_PI)
- elevation;
}
rot.fromAngleAxis(amount, axis);
cam.getLocation().subtract(focus, vector);
rot.mult(vector, vector);
focus.add(vector, cam.getLocation());
rot.mult(cam.getLeft(), cam.getLeft());
rot.mult(cam.getUp(), cam.getUp());
rot.mult(cam.getDirection(), cam.getDirection());
cam.normalize();
cam.onFrameChange();
}
private void panCamera(float left, float up) {
Camera cam = impl.getRenderer().getCamera();
cam.getLeft().mult(left, vector);
vector.scaleAdd(up, cam.getUp(), vector);
cam.getLocation().addLocal(vector);
focus.addLocal(vector);
cam.onFrameChange();
}
private void zoomCamera(float amount) {
Camera cam = impl.getRenderer().getCamera();
float dist = cam.getLocation().distance(focus);
amount = dist - Math.max(0f, dist - amount);
cam.getLocation().scaleAdd(amount, cam.getDirection(),
cam.getLocation());
cam.onFrameChange();
}
}
protected void doResize() {
if (impl != null) {
impl.resizeCanvas(glCanvas.getWidth(), glCanvas.getHeight());
if (impl.getCamera() != null) {
Callable<?> exe = new Callable() {
public Object call() {
impl.getCamera().setFrustum(-10, 100, -10f, 10f, -10f, 10f);
return null;
}
};
GameTaskQueueManager.getManager()
.getQueue(GameTaskQueue.RENDER).enqueue(exe);
}
}
}
class MyImplementor extends SimpleCanvasImpl {
private static final int GRID_LINES = 51;
private static final float GRID_SPACING = 100f;
/
* The root node of our text.
*/
protected Node fpsNode;
/
* Displays all the lovely information at the bottom.
*/
protected Text fps;
/
* This is used to recieve getStatistics calls.
*/
protected StringBuffer tempBuffer = new StringBuffer();
/
* This is used to display print text.
/
protected StringBuffer updateBuffer = new StringBuffer(30);
public MyImplementor(int width, int height) {
super(width, height);
}
public void simpleSetup() {
renderer.setBackgroundColor(makeColorRGBA(new Color(0, 0, 0)));
cam.setParallelProjection(true);
cam.setFrustum(-10, 100, -10f, 10f, -10f, 10f);
Vector3f loc = new Vector3f(0, 0, 20);
Vector3f left = new Vector3f(-1, 0, 0);
Vector3f up = new Vector3f(0, 1, 0);
Vector3f look = new Vector3f(0, 0, -1);
cam.setFrame(loc, left, up, look);
root = rootNode;
// Then our font Text object.
/* This is what will actually have the text at the bottom. /
fps = Text.createDefaultTextLabel("FPS label");
fps.setCullMode(SceneElement.CULL_NEVER);
fps.setTextureCombineMode(TextureState.REPLACE);
// Finally, a stand alone node (not attached to root on purpose)
fpsNode = new Node("FPS node");
fpsNode.setRenderState(fps.getRenderState(RenderState.RS_ALPHA));
fpsNode.setRenderState(fps.getRenderState(RenderState.RS_TEXTURE));
fpsNode.attachChild(fps);
fpsNode.setCullMode(SceneElement.CULL_NEVER);
renderer.enableStatistics(true);
root.attachChild(grid = createGrid());
grid.updateRenderState();
ZBufferState zbuf = renderer.createZBufferState();
zbuf.setWritable(false);
zbuf.setEnabled(true);
zbuf.setFunction(ZBufferState.CF_LEQUAL);
fpsNode.updateGeometricState(0, true);
fpsNode.updateRenderState();
/***********************************************************/
/ Here !!! /
/ I get error. /
/ I get the text displayed, but get error message, too. */
/*********************************************************/
Font3D font = new Font3D(new Font("Arial", 1, Font.PLAIN), 1, true, true, true);
Text3D text = font.createText("Hi", 10f, 0);
root.attachChild(text);
}
public void simpleUpdate() {
updateBuffer.setLength(0);
updateBuffer.append("FPS: ").append((int) timer.getFrameRate())
.append(" - ");
updateBuffer.append(renderer.getStatistics(tempBuffer));
/ Send the fps to our fps bar at the bottom. */
fps.print(updateBuffer);
}
@Override
public void simpleRender() {
fpsNode.draw(renderer);
renderer.clearStatistics();
}
private Geometry createGrid() {
Vector3f[] vertices = new Vector3f[GRID_LINES * 2 * 2];
float edge = GRID_LINES / 2 * GRID_SPACING;
for (int ii = 0, idx = 0; ii < GRID_LINES; ii++) {
float coord = (ii - GRID_LINES / 2) * GRID_SPACING;
vertices[idx++] = new Vector3f(-edge, 0f, coord);
vertices[idx++] = new Vector3f(+edge, 0f, coord);
vertices[idx++] = new Vector3f(coord, 0f, -edge);
vertices[idx++] = new Vector3f(coord, 0f, +edge);
}
Geometry grid = new com.jme.scene.Line("grid", vertices, null,
null, null);
grid.getBatch(0).getDefaultColor().set(ColorRGBA.darkGray.clone());
return grid;
}
}
}
WARNING: Error in char: (213:
It seems that the current implementation of Text3D does not allow for compound symbols, like the O with " you want to draw.
O with " ? What do you mean?
I am intending to draw the word "Hi".
Perhaps you are referring to the error message's first line. I do not know why the error message is like that...
Thanks.
You should have a look at this line:
at com.certusoft.gui.threed.test.Test$MyImplementor.simpleSetup(Test.java:359) and try to trace it.
These are known errors, which happen when using Text3D.
There are a few posts in the forum about this, and i get those errors also when running jmetest.text.Test3DText.
I guess there is not much you can do.
OK,
I guess I will have to ignore the errors since the error does not stop the application.
Does anyone know how to color these texts, though? I tried several different ways including setSolidColor and using MaterialState. Nothing worked so far.
Thanks.
I got the color shown on the texts by applying Font3DGradient to the font.
Thanks.
JME people,
Please fix this known error, if it is a known issue.