Good news is i can see jPCT's box in another JFrame, which take jPCT's canvas as its child.
Bad news is i still can not draw the canvas to the WW's gl.
I adjust the coordinates with some methods, and stick the box before the eye point of WW,
and set the jPCT's camera at the eye point at any time. So i can see the box, no matter where the eye point and camera is.
But when i paint the canvas to a BufferedImage, which will be drawn to WW' gl, NOTHING is drawn into the image.
I guess in jPCT, the world/scence is not drawn into the gl injected directly, but in the buffered canvas.
And the canvas(JOGLCanvas in my debugger) did not paint itself to the given image's Graphics.
I wonder how can i make jPCT draw the scence directly into the gl injected, or how can i "copy" the canvas into the image, which will be drawn into the WW's gl.
A runtime screeshot is in the attachment.
And the code:
package org.aoe.det.ww.d3man.ww;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.lang.reflect.Field;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.Arrays;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.swing.JFrame;
import org.aoe.det.ww.d3man.D3Man;
import org.gbzh.util.log.Log;
import org.gbzh.util.resource.Resource;
import com.jogamp.opengl.util.texture.TextureCoords;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.IRenderer;
import com.threed.jpct.Logger;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.geom.Angle;
import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.geom.Vec4;
import gov.nasa.worldwind.layers.AbstractLayer;
import gov.nasa.worldwind.pick.PickedObject;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.util.Logging;
import gov.nasa.worldwind.util.OGLStackHandler;
/**
* A jPCT based three model layer. In jPCT, positive x goes to the right,
* positive z goes INTO the screen and positive y goes DOWN. In worldwind,
* positive x goes to the right, positive z goes OUT the screen and positive
* goes UP. In worldwind,cartesian coordinates's point(0, 0, radius of the
* earth) has the longi/lati-tude position(0, 0, radius of the earth). longitude
* goes RIGHT to +180 and left to -180, latitude goes UP to +90 and down to -90.
*
* @author berg
*
*/
public class Jpct3DLayer extends AbstractLayer {
/** The world of jPCT. */
private World world;
/***/
private FrameBuffer buffer;
private GL2 lastGL;
private Canvas canvas;
private Object3D box;
private float move = 0.0f;
private double surfaceElevation = 6378137.0;
// in Beijing
// (8830275.0,-8099939.5,4351104.0)
private Vec4 boxLoc = new Vec4(0, 0, 0);
// (8830413.0,-8100067.0,4351172.0)
private Vec4 cameraLoc = new Vec4(0, 0, surfaceElevation);
public Jpct3DLayer() {
this.world = new World();
this.world.setAmbientLight(0, 255, 0);
TextureManager.getInstance().addTexture("box",
new Texture(Resource.getResource("data/POLYSHIP.jpg")));
box = Primitives.getBox(13f, 2f);
box.setTexture("box");
box.setEnvmapped(Object3D.ENVMAP_ENABLED);
box.build();
world.addObject(box);
box.translate(ww2jpct(boxLoc));
this.world.getCamera().setPosition(ww2jpct(cameraLoc));
SimpleVector point = new SimpleVector(0.0, 0.0, 0.0);
this.world.getCamera().lookAt(point);
// this.world.getCamera().setFOV(this.world.getCamera().getMaxFOV());
this.buffer = new FrameBuffer(800, 600,
FrameBuffer.SAMPLINGMODE_NORMAL);
canvas = buffer.enableGLCanvasRenderer();
buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
//add a frame, it can show the canvas of jPCT
JFrame frame = new JFrame("Hello world");
frame.setSize(800, 600);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
frame.add(canvas);
new Thread() {
@Override
public void run() {
while (true) {
move -= 10.0;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
private BufferedImage image;
private WritableRaster raster;
private void drawCanvas2Gl(Canvas canvas, GL2 gl) {
method: do {
//try to draw jPCT's canvas to the image
int w,h;
if(image==null){
Rectangle rect = canvas.getBounds();
raster = Raster.createInterleavedRaster(
DataBuffer.TYPE_BYTE, rect.width, rect.height, 4, null);
ComponentColorModel colorModel = new ComponentColorModel(
ColorSpace.getInstance(ColorSpace.CS_sRGB),
new int[] { 8, 8, 8, 8 }, true, false,
ComponentColorModel.TRANSLUCENT, DataBuffer.TYPE_BYTE);
image = new BufferedImage(colorModel, raster, false,
null);
}
w = image.getWidth();
h = image.getHeight();
Graphics2D g = image.createGraphics();
canvas.paint(g);//NOTHING is draw into the image!
//draw something to check validate method. OK
g.setPaint(Color.RED);
g.setFont(Font.decode("ARIAL-BOLD-50"));
g.drawString(1 + " frames", 10, w / 4);
g.drawString("1 sec", 10, h / 2);
g.drawString(
"Heap:" + Long.toString(Runtime.getRuntime().totalMemory()),
10, 3 * h / 4);
g.dispose();
//draw the image to GL, OK
raster = image.getRaster();
DataBufferByte dukeBuf = (DataBufferByte)raster.getDataBuffer();
byte[] dukeRGBA = dukeBuf.getData();
ByteBuffer buffer = ByteBuffer.wrap(dukeRGBA);
buffer.position(0);
buffer.mark();
gl.glBindTexture(GL.GL_TEXTURE_2D, 13);
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL2.GL_CLAMP);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL2.GL_CLAMP);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl.glTexEnvf(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
gl.glTexImage2D (GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, w, h, 0, GL.GL_RGBA,
GL.GL_UNSIGNED_BYTE, buffer);
gl.glEnable(GL.GL_TEXTURE_2D);
gl.glBindTexture (GL.GL_TEXTURE_2D, 13);
gl.glBegin (GL2.GL_POLYGON);
gl.glTexCoord2d (0, 0);
gl.glVertex2d (0, 0);
gl.glTexCoord2d(1,0);
gl.glVertex2d (w, 0);
gl.glTexCoord2d(1,1);
gl.glVertex2d (w, h);
gl.glTexCoord2d(0,1);
gl.glVertex2d (0, h);
gl.glEnd ();
gl.glFlush();
break method;
} while (false);
}
// puts opengl in the correct state for this layer
protected void beginDraw(DrawContext dc) {
GL2 gl = (GL2) dc.getGL();
gl.glPushAttrib(GL2.GL_TEXTURE_BIT | GL2.GL_ENABLE_BIT
| GL2.GL_CURRENT_BIT | GL2.GL_TRANSFORM_BIT);
if (!dc.isPickingMode()) {
gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
}
gl.glMatrixMode(javax.media.opengl.GL2.GL_MODELVIEW);
gl.glPushMatrix();
// inject gl if neccessary
if (this.lastGL != gl) {
this.injectGL(gl);
this.lastGL = gl;
}
}
// resets opengl state
protected void endDraw(DrawContext dc) {
GL2 gl = (GL2) dc.getGL();
gl.glMatrixMode(javax.media.opengl.GL2.GL_MODELVIEW);
gl.glPopMatrix();
gl.glPopAttrib();
}
private void injectGL(GL gl) {
String[] classes = new String[] { "org.lwjgl.opengl.GL11",
"org.lwjgl.opengl.GL15", "org.lwjgl.opengl.GL20",
"org.lwjgl.opengl.Util", "org.lwjgl.opengl.ARBMultitexture",
"org.lwjgl.opengl.EXTFramebufferObject",
"org.lwjgl.opengl.ARBShaderObjects",
"org.lwjgl.opengl.GLContext" };
Class<?> clazz;
try {
for (int i = 0; i < classes.length; i++) {
clazz = Class.forName(classes[i]);
Field glf = clazz.getDeclaredField("gl");
glf.set(clazz, gl);
}
Log.d("gl injected.");
} catch (Exception e) {
Logger.log("Unable to inject GL context into the facade!",
Logger.ERROR);
}
}
/**
* convert WorldWind's Vec4 to jPCT's SimpleVector.
*
* @param x
* @param y
* @param z
* @return
*/
public static SimpleVector ww2jpct(double x, double y, double z) {
return new SimpleVector((float) x, (float) -y, (float) -z);
}
/**
* convert WorldWind's Vec4 to jPCT's SimpleVector.
*
* @param x
* @param y
* @param z
* @return
*/
public static SimpleVector ww2jpct(Vec4 vec) {
return new SimpleVector((float) vec.x, (float) -vec.y, (float) -vec.z);
}
/**
* move the object to the given position, not delta.
*
* @param obj
* the object to me moved
* @param sv
* the target position
*/
public static void setObject3DPosition(Object3D obj, SimpleVector sv) {
method: do {
if (sv == null || obj == null) {// 检测是否为空,空则退出
Log.e("The input param sv or obj is null.");
break method;
}
SimpleVector cur = obj.getTranslation();
obj.translate(sv.calcSub(cur));
} while (false);
}
public static void setObject3DPosition(Object3D obj, float x, float y,
float z) {
method: do {
if (obj == null) {// 检测是否为空,空则退出
Log.e("The input param obj is null.");
break method;
}
SimpleVector sv = new SimpleVector(x, y, z);
SimpleVector cur = obj.getTranslation();
obj.translate(sv.calcSub(cur));
} while (false);
}
public static Vec4 jpct2wwPoint(float x, float y, float z) {
return new Vec4(x, -y, -z);
}
public static Vec4 jpct2wwPoint(SimpleVector sv) {
Vec4 result = null;
method: do {
if (sv == null) {// 检测是否为空,空则退出
Log.e("The input param sv is null.");
break method;
}
result = new Vec4(sv.x, -sv.y, -sv.z);
} while (false);
return result;
}
public static SimpleVector ww2jpct(Position position) {
SimpleVector result = null;
method: do {
if (position == null) {// 检测是否为空,空则退出
Log.e("The input param position is null.");
break method;
}
Vec4 vec = D3Man.getInstance().position2Point(position);
result = new SimpleVector((float) vec.x, (float) -vec.y,
(float) -vec.z);
} while (false);
return result;
}
public static Position jpct2wwPosition(float x, float y, float z) {
return D3Man.getInstance().point2Position(x, -y, -z);
}
public static Position jpct2wwPosition(SimpleVector sv) {
Position result = null;
method: do {
if (sv == null) {// 检测是否为空,空则退出
Log.e("The input param sv is null.");
break method;
}
result = D3Man.getInstance().point2Position(sv.x, -sv.y, -sv.z);
} while (false);
return result;
}
/**
* Called by WorldWind to refresh this layer.
*/
@Override
protected void doRender(DrawContext dc) {
this.beginDraw(dc);
// GL initialization checks for GL2
GL2 gl = dc.getGL().getGL2();
// get the eye point of WW, to set the camera in jPCT
// so that jpct's camera go with ww's eye point
Vec4 eyeLoc = dc.getView().getEyePoint();
this.world.getCamera().setPosition(ww2jpct(eyeLoc));
Log.d("eye point = camera position = " + eyeLoc);
Position position = dc.getView().getEyePosition();// D3Man.getInstance().point2Position(boxLoc);
Vec4 loc = dc.getGlobe().computePointFromPosition(position);
double size = 5000;// this.computeSize(dc, loc);
// move the box and adjust the camera
setObject3DPosition(box, ww2jpct(new Position(position.latitude,
position.longitude, position.elevation - 50)));
world.getCamera().lookAt(box.getTranslation());
// save current gl settings before change it
dc.getView().pushReferenceCenter(dc, loc);
// adjust current gl settings for jPCT's world
// gl.glTranslated(-cameraLoc.x, -cameraLoc.y, cameraLoc.z);
// gl.glRotated(position.getLongitude().degrees, 0, 1, 0);
// gl.glRotated(-position.getLatitude().degrees, 1, 0, 0);
// gl.glScaled(size, size, size);
// Log.d("size = "+size);
// jPCT draw its world with the given gl
this.repaint();
//draw canvas to gl
this.drawCanvas2Gl(canvas, gl);
// restore last gl settings
dc.getView().popReferenceCenter(dc);
this.endDraw(dc);
}
private double computeSize(DrawContext dc, Vec4 loc) {
if (loc == null) {
System.err.println("Null location when computing size of mode");
return 1;
}
double d = loc.distanceTo3(dc.getView().getEyePoint());
double size = 600 * dc.getView().computePixelSizeAtDistance(d);
if (size < 2)
size = 2;
return size;
}
/**
* force this layer to redraw components inside it.
*/
public void repaint() {
buffer.clear(Color.BLUE);
world.renderScene(buffer);
world.draw(buffer);
buffer.update();
buffer.displayGLOnly();
canvas.repaint();
Log.d("box.translation=" + box.getTranslation() + ", camera.position="
+ world.getCamera().getPosition());
}
public static void main(String[] args) {
JFrame frame = new JFrame("Hello world");
frame.setSize(800, 600);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
Jpct3DLayer layer = new Jpct3DLayer();
frame.add(layer.canvas);
Vec4 cameraLoc = new Vec4(0, 0, layer.surfaceElevation);
Vec4 boxLoc;
while (frame.isShowing()) {
// move the camera and the box
cameraLoc = cameraLoc.add3(0, 0, 10000);
boxLoc = cameraLoc.add3(0, 0, 50);
layer.world.getCamera().setPosition(ww2jpct(cameraLoc));
setObject3DPosition(layer.box, ww2jpct(boxLoc));
layer.box.rotateZ(0.1f);
// look at the box
layer.world.getCamera().lookAt(layer.box.getTranslation());
layer.repaint();
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}