Main Menu
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - iamfoolberg

#1
Support / Re: Integrating jPCT in NASA 3D GIS WorldWind
September 16, 2015, 03:15:06 AM
Good news is that i tried to integrate the jReality into WorldWind as a layer, Bad news is the method causes error in jPCT.

I downloaded the jReality's source code and compiled them in Eclipse+maven. Although some .jars are missed, it works.
Then, i look into its Viewer and Render(with the same name JOGLRender as jPCT), and comment some camera and projection gl operations, especially those for sky background.

When i write a WW's layer, called jrealityLayer, as JpctLayer, it has the same problem.
I can see the 3d object, but it will be covered by other layers.
Fortunatly, i find the way:
1. comment the camera's gl matrix operations.
2. comment the projection matrix operation
3. comment the background drawing
4. add a coord matrix as that in the former cube demo
5. add a projection matrix before step 4. --this is the key step, i think.
Now, i can see the 3d object as that in the cube demo.

The following is the jrealityLayer and a simple view for the layer.

package org.aoe.det.ww.d3man.ww;

import gov.nasa.worldwind.geom.Matrix;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.geom.Vec4;
import gov.nasa.worldwind.layers.AbstractLayer;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.util.OGLUtil;

import javax.media.opengl.GL;
import javax.media.opengl.GL2;

import org.aoe.det.ww.d3man.D3Man;

import de.jreality.geometry.Primitives;
import de.jreality.jogl4ww.Jogl4WWViewer;
import de.jreality.math.MatrixBuilder;
import de.jreality.scene.Appearance;
import de.jreality.scene.Camera;
import de.jreality.scene.DirectionalLight;
import de.jreality.scene.IndexedFaceSet;
import de.jreality.scene.Light;
import de.jreality.scene.SceneGraphComponent;
import de.jreality.scene.SceneGraphPath;
import de.jreality.shader.Color;
import de.jreality.shader.CommonAttributes;
import de.jreality.tools.RotateTool;

public class JrealityLayer extends AbstractLayer {
public Jogl4WWViewer viewer;
public SceneGraphComponent rootNode;
public SceneGraphComponent cameraNode;
public SceneGraphComponent lightNode;
public SceneGraphComponent geometryNode;

public JrealityLayer() {
// do nothing
}

// 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);
gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);

// if (!dc.isPickingMode()) {
// gl.glEnable(GL.GL_BLEND);
// gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
// }

if (!dc.isPickingMode()) {
dc.beginStandardLighting();
gl.glEnable(GL.GL_BLEND);
OGLUtil.applyBlending(gl, false);

// Were applying a scale transform on the modelview matrix, so the
// normal vectors must be re-normalized
// before lighting is computed.
gl.glEnable(GL2.GL_NORMALIZE);
}

gl.glMatrixMode(GL2.GL_MODELVIEW);// |GL2.GL_PROJECTION|GL2.GL_TEXTURE);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glMatrixMode(GL2.GL_TEXTURE);
gl.glPushMatrix();
gl.glLoadIdentity();

gl.glMatrixPushEXT(GL2.GL_MODELVIEW);
gl.glMatrixPushEXT(GL2.GL_PROJECTION);
gl.glMatrixPushEXT(GL2.GL_TEXTURE);

// Multiply the modelview matrix by a surface orientation matrix to set
// up a local coordinate system with the
// origin at the cube's center position, the Y axis pointing North, the
// X axis pointing East, and the Z axis
// normal to the globe.

// the local coord O--> WW's (0-latitude, 20-longitude,
// 1000-metersElevation)
Position pos = Position.fromDegrees(0, 20);
double[] matrixArray;
Matrix posMatrix, matrix;

posMatrix = dc.getGlobe().computeSurfaceOrientationAtPosition(// boxPos);
pos.latitude, pos.longitude, -D3Man.surfaceElevation);//

matrix = dc.getView().getProjectionMatrix().multiply(posMatrix);
matrixArray = new double[16];
matrix.toArray(matrixArray, 0, false);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadMatrixd(matrixArray, 0);

matrix = dc.getView().getModelviewMatrix().multiply(posMatrix);
matrixArray = new double[16];
matrix.toArray(matrixArray, 0, false);
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadMatrixd(matrixArray, 0);
}

/**
* Called by WorldWind to refresh this layer.
*/
@Override
protected void doRender(DrawContext dc) {
this.beginDraw(dc);
GL2 gl = dc.getGL().getGL2();
if (this.viewer == null) {
rootNode = new SceneGraphComponent();
cameraNode = new SceneGraphComponent();
geometryNode = new SceneGraphComponent();
lightNode = new SceneGraphComponent();

rootNode.addChild(geometryNode);
rootNode.addChild(cameraNode);
cameraNode.addChild(lightNode);

Light dl = new DirectionalLight();
lightNode.setLight(dl);

Camera camera = new Camera();
cameraNode.setCamera(camera);

IndexedFaceSet ifs = Primitives.icosahedron();
geometryNode.setGeometry(ifs);

RotateTool rotateTool = new RotateTool();
geometryNode.addTool(rotateTool);

MatrixBuilder.euclidean().translate(0, 0, 1).assignTo(cameraNode);
MatrixBuilder.euclidean().translate(0, 0, 0).assignTo(geometryNode);
// MatrixBuilder.euclidean().scale(20.0).assignTo(geometryNode);
// MatrixBuilder.euclidean().rotateZ(20.0).assignTo(geometryNode);

Appearance rootApp = new Appearance();
// rootApp.setAttribute(CommonAttributes.BACKGROUND_COLOR,
// new Color(0f, 1.0f, .1f));
rootApp.setAttribute(CommonAttributes.DIFFUSE_COLOR,
new Color(1f, 1f, 1f));
rootNode.setAppearance(rootApp);

SceneGraphPath camPath = new SceneGraphPath();
camPath.push(rootNode);
camPath.push(cameraNode);
camPath.push(camera);

viewer = new Jogl4WWViewer();
viewer.initialize(gl, camPath, rootNode);
}
viewer.reInitGL(gl, 0, 0, dc.getDrawableWidth(),
dc.getDrawableHeight());

//set camera
// Vec4 eyeLoc = dc.getView().getEyePoint();
// MatrixBuilder.euclidean().translate(eyeLoc.x, eyeLoc.y, eyeLoc.z).assignTo(cameraNode);

viewer.render();
this.endDraw(dc);
}

// resets opengl state
protected void endDraw(DrawContext dc) {
GL2 gl = (GL2) dc.getGL();

gl.glMatrixPopEXT(GL2.GL_TEXTURE);
gl.glMatrixPopEXT(GL2.GL_PROJECTION);
gl.glMatrixPopEXT(GL2.GL_MODELVIEW);

gl.glMatrixMode(GL2.GL_TEXTURE);
gl.glPopMatrix();
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glPopMatrix();
gl.glMatrixMode(GL2.GL_MODELVIEW);// |GL2.GL_PROJECTION|GL2.GL_TEXTURE);
gl.glPopMatrix();

if (!dc.isPickingMode()) {
dc.endStandardLighting();
}
gl.glPopAttrib();
}
}
/**
*
* This file is part of jReality. jReality is open source software, made
* available under a BSD license:
*
* Copyright (c) 2003-2006, jReality Group: Charles Gunn, Tim Hoffmann, Markus
* Schmies, Steffen Weissmann.
*
* 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 jReality nor the names of its contributors nor the
*   names of their associated organizations 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.
*
*/

package de.jreality.jogl4ww;

import java.awt.Dimension;
import java.util.logging.Level;

import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawableFactory;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.opengl.GLCanvas;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;

import de.jreality.jogl.JOGLConfiguration;
import de.jreality.jogl.JOGLRenderer;
import de.jreality.scene.SceneGraphComponent;
import de.jreality.scene.SceneGraphPath;
import de.jreality.util.SceneGraphUtility;

/**
* a viewer for NASA WorldWind, with injected GL2 object.
*
* @author berg
*
*/
public class Jogl4WWViewer implements de.jreality.scene.Viewer {

private SceneGraphComponent sceneRoot;
private SceneGraphComponent auxiliaryRoot;
private SceneGraphPath cameraPath;

private JOGLRenderer renderer;

public static final int CROSS_EYED_STEREO = 0;
public static final int RED_BLUE_STEREO = 1;
public static final int RED_GREEN_STEREO = 2;
public static final int RED_CYAN_STEREO = 3;
public static final int HARDWARE_BUFFER_STEREO = 4;
public static final int STEREO_TYPES = 5;
int stereoType = CROSS_EYED_STEREO;

private GL2 gl;
private int metric;

public Jogl4WWViewer() {
super();
}
/**
* initialize this viewer with given params.
* @param gl
* @param camPath
* @param root
*/
public void initialize(GL2 gl, SceneGraphPath camPath, SceneGraphComponent root) {
this.gl = gl;
setAuxiliaryRoot(SceneGraphUtility
.createFullSceneGraphComponent("AuxiliaryRoot"));

this.setSceneRoot(root);
this.setCameraPath(camPath);
this.renderer = new JOGLRenderer(this);
this.renderer.init(this.gl);
}

public SceneGraphComponent getSceneRoot() {
return sceneRoot;
}

public void setSceneRoot(SceneGraphComponent r) {
if (r == null) {
JOGLConfiguration.getLogger().log(Level.WARNING,
"Null scene root, not setting.");
return;
}
sceneRoot = r;
}

public SceneGraphComponent getAuxiliaryRoot() {
return auxiliaryRoot;
}

public void setAuxiliaryRoot(SceneGraphComponent auxiliaryRoot) {
this.auxiliaryRoot = auxiliaryRoot;
if (renderer != null)
renderer.setAuxiliaryRoot(auxiliaryRoot);
}

public SceneGraphPath getCameraPath() {
return cameraPath;
}

public void setCameraPath(SceneGraphPath p) {
cameraPath = p;
}

public void renderAsync() {
this.render();
}

public boolean hasViewingComponent() {
return false;
}

public Object getViewingComponent() {
return this.gl;
}


public int getMetric() {
return metric;
}

public void setMetric(int metric) {
this.metric = metric;
SceneGraphUtility.setMetric(sceneRoot, metric);

}

/*********** Non-standard set/get ******************/

public void setStereoType(int type) {
renderer.setStereoType(type);
}

// used in JOGLRenderer
public int getStereoType() {
return renderer.getStereoType();
}

// public boolean isFlipped() {
// return renderer.isFlipped();
// }
// public void setFlipped(boolean isFlipped) {
// renderer.setFlipped(isFlipped);
// }
//
public JOGLRenderer getRenderer() {
return renderer;
}

/****** Convenience methods ************/
public void addAuxiliaryComponent(SceneGraphComponent aux) {
if (auxiliaryRoot == null) {
setAuxiliaryRoot(SceneGraphUtility
.createFullSceneGraphComponent("AuxiliaryRoot"));
}
if (!auxiliaryRoot.isDirectAncestor(aux))
auxiliaryRoot.addChild(aux);
}

public void removeAuxiliaryComponent(SceneGraphComponent aux) {
if (auxiliaryRoot == null)
return;
if (!auxiliaryRoot.isDirectAncestor(aux))
return;
auxiliaryRoot.removeChild(aux);
}

private boolean pendingUpdate;

private final Object renderLock = new Object();
boolean autoSwapBuffers = true;

public boolean isRendering() {
synchronized (renderLock) {
return pendingUpdate;
}
}

boolean init = true;

int rot = 0;

private int gl_x;
private int gl_y;
private int gl_right;
private int gl_top;
/**
* re-initialized when the gl or viewport is changed.
* @param gl
* @param x
* @param y
* @param right
* @param top
*/
public void reInitGL(GL2 gl, int x, int y, int right,
int top) {
if (this.gl != gl){
this.renderer.init(gl);
}
if (gl_x != x || gl_y != y
|| gl_right != right || gl_top != top) {
this.gl_x = x;
this.gl_y = y;
this.gl_right = right;
this.gl_top = top;
this.renderer.reshape(this.gl, x, y, right, top);
}
}

public double getAspectRatio() {
return renderer.getAspectRatio();
}

public Dimension getViewingComponentSize() {
return new Dimension(gl_right-gl_x, gl_top-gl_y);
}

public boolean canRenderAsync() {
return true;
}

public void render() {
renderer.display(this.gl);
}
}



the key step is :

Position pos = Position.fromDegrees(0, 20);
double[] matrixArray;
Matrix posMatrix, matrix;

posMatrix = dc.getGlobe().computeSurfaceOrientationAtPosition(// boxPos);
pos.latitude, pos.longitude, -D3Man.surfaceElevation);//

matrix = dc.getView().getProjectionMatrix().multiply(posMatrix);
matrixArray = new double[16];
matrix.toArray(matrixArray, 0, false);
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadMatrixd(matrixArray, 0);

matrix = dc.getView().getModelviewMatrix().multiply(posMatrix);
matrixArray = new double[16];
matrix.toArray(matrixArray, 0, false);
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadMatrixd(matrixArray, 0);

I set the local coord as in cube demo, and adjust the projection/modelview matrix.
The source code JOGLRenderer.java is a bit long, so i list the commented codes:

public void render() {
if (disposed)
return;
Texture2DLoaderJOGL.clearAnimatedTextureTable(globalGL);
if (thePeerRoot == null || theViewer.getSceneRoot() != thePeerRoot
.getOriginalComponent()) {
setSceneRoot(theViewer.getSceneRoot());
thePeerRoot = ConstructPeerGraphVisitor
.constructPeerForSceneGraphComponent(theRoot, null, this);
}
if (auxiliaryRoot != null && thePeerAuxilliaryRoot == null)
thePeerAuxilliaryRoot = ConstructPeerGraphVisitor
.constructPeerForSceneGraphComponent(auxiliaryRoot, null,
this);

renderingState.oneTexture2DPerImage = topAp.isOneTexture2DPerImage();
renderingState.currentPath.clear();
renderingState.context = new Graphics3D(getCameraPath(),
renderingState.currentPath,
CameraUtility.getAspectRatio(theViewer));
//FIXME berg, no reset and background
// globalGL.glMatrixMode(GL2.GL_PROJECTION);
// globalGL.glLoadIdentity();//重置当前指定的矩阵为单位矩阵.
// JOGLRendererHelper.handleBackground(this, width, height,
// theRoot.getAppearance());

frontBanana = true;
renderOnePass();
if (topAp.isRenderSpherical()) {
frontBanana = false;
renderOnePass();
}
if (topAp.isForceResidentTextures())
forceResidentTextures();

}

private void renderOnePass() {
if (theCamera == null)
return;
// double aspectRatio = getAspectRatio();
// System.err.println("aspect ratio = "+aspectRatio);
// for pick mode the aspect ratio has to be set to that of the viewer
// component
//FIXME berg, no reset
// globalGL.glMatrixMode(GL2.GL_PROJECTION);
// globalGL.glLoadIdentity();
// if (topAp.isRenderSpherical()) {
// //把m指定的16个值作为一个矩阵,与当前矩阵相乘,并把结果存储在当前矩阵中,按行主序
// globalGL.glMultTransposeMatrixd(
// frontBanana ? frontZBuffer : backZBuffer, 0);
// // System.err.println("c2ndc = "+Rn.matrixToString(
// // Rn.times(null, frontBanana ? frontZBuffer : backZBuffer,
// // c2ndc)));
// }
// Rectangle2D viewPort = CameraUtility.getViewport(theCamera,
// aspectRatio);
// System.err.println("Camera viewport = "+viewPort.toString());
//FIXME berg, no camera tranform
// double[] c2ndc = CameraUtility.getCameraToNDC(theCamera,
// getAspectRatio(), whichEye);
// // System.err.println("C2ndc = "+Rn.matrixToString(c2ndc));
// globalGL.glMultTransposeMatrixd(c2ndc, 0);

//FIXME berg, no reset
// prepare for rendering the geometry
// globalGL.glMatrixMode(GL2.GL_MODELVIEW);
// globalGL.glLoadIdentity();

// renderingState.cameraToWorld = renderingState.context
// .getCameraToWorld();
// renderingState.worldToCamera = Rn.inverse(null,
// renderingState.cameraToWorld);
//FIXME berg, no reset
// renderingState.cameraToNDC = c2ndc;
// globalGL.glMultTransposeMatrixd(renderingState.worldToCamera, 0);
// if (topAp.getSkyboxCubemap() != null)
// JOGLSkyBox.render(globalGL, renderingState.worldToCamera,
// topAp.getSkyboxCubemap(),
// CameraUtility.getCamera(theViewer));

processLights();

processClippingPlanes();

rhStack.clear();
rhStack.push(RenderingHintsInfo.defaultRHInfo);
RenderingHintsInfo.defaultRHInfo.render(renderingState, null);
renderingState.flipNormals = (Rn
.determinant(renderingState.worldToCamera) < 0.0);
globalGL.glFrontFace(renderingState.flipNormals ? GL.GL_CW : GL.GL_CCW);

texResident = true;
renderPeerRoot();
if (thePeerAuxilliaryRoot != null)
thePeerAuxilliaryRoot.render();
if (topAp.isRenderSpherical() && !frontBanana)
globalGL.glPopMatrix();
//FIXME berg, no reset
// globalGL.glLoadIdentity();
}

The listed two method do the drawing works.
Then, i tried to use the same key step in jPCTLayer, but failed.
The output is:

Loading Texture...from InputStream
Loading file from InputStream
File from InputStream loaded...21824 bytes
Processing new material PolyShip_UnWrap!
Texture named POLYSHBP.JPG added to TextureManager!
Processing new material  -- default --!
Processing object from 3DS-file: SpaceFight
Object 'SpaceFight_jPCT0' created using 500 polygons and 259 vertices.
1DEBUG[[org.aoe.det.rsshell.ScriptShell.getScriptEngine()]: Use language beanshellx
[ Wed Sep 16 08:50:32 CST 2015 ] - WARNING: There's a problem with the object list not being consistent during rendering. This is often caused by concurrent modification of jPCT objects on a thread different from the rendering thread!
[ Wed Sep 16 08:50:32 CST 2015 ] - ERROR: null
九月 16, 2015 8:50:32 上午 gov.nasa.worldwind.AbstractSceneController draw
严重: Exception while rendering layer org.aoe.det.ww.d3man.ww.Jpct3DLayer
java.lang.NullPointerException
at com.threed.jpct.World.draw(World.java:2091)
at com.threed.jpct.World.draw(World.java:2073)
at com.threed.jpct.World.draw(World.java:1613)
at org.aoe.det.ww.d3man.ww.Jpct3DLayer.repaint(Jpct3DLayer.java:352)
at org.aoe.det.ww.d3man.ww.Jpct3DLayer.doRender(Jpct3DLayer.java:204)
at gov.nasa.worldwind.layers.AbstractLayer.render(AbstractLayer.java:232)
at gov.nasa.worldwind.AbstractSceneController.draw(AbstractSceneController.java:864)
at gov.nasa.worldwind.StereoOptionSceneController.draw(StereoOptionSceneController.java:153)
at gov.nasa.worldwind.BasicSceneController.doNormalRepaint(BasicSceneController.java:42)
at gov.nasa.worldwind.BasicSceneController.doRepaint(BasicSceneController.java:28)
at gov.nasa.worldwind.AbstractSceneController.repaint(AbstractSceneController.java:381)
at gov.nasa.worldwind.WorldWindowGLAutoDrawable.doDisplay(WorldWindowGLAutoDrawable.java:472)
at gov.nasa.worldwind.WorldWindowGLAutoDrawable.display(WorldWindowGLAutoDrawable.java:343)
at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:665)
at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:649)
at javax.media.opengl.awt.GLCanvas$10.run(GLCanvas.java:1289)
at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1119)
at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:994)
at javax.media.opengl.awt.GLCanvas$11.run(GLCanvas.java:1300)
at javax.media.opengl.Threading.invoke(Threading.java:193)
at javax.media.opengl.awt.GLCanvas.display(GLCanvas.java:541)
at javax.media.opengl.awt.GLCanvas.paint(GLCanvas.java:595)
at sun.awt.RepaintArea.paintComponent(RepaintArea.java:264)
at sun.awt.RepaintArea.paint(RepaintArea.java:240)
at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:358)
at java.awt.Component.dispatchEventImpl(Component.java:4957)
at java.awt.Component.dispatchEvent(Component.java:4703)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

[ Wed Sep 16 08:50:32 CST 2015 ] - WARNING: There's a problem with the object list not being consistent during rendering. This is often caused by concurrent modification of jPCT objects on a thread different from the rendering thread!
[ Wed Sep 16 08:50:32 CST 2015 ] - ERROR: null
九月 16, 2015 8:50:32 上午 gov.nasa.worldwind.AbstractSceneController draw
严重: Exception while rendering layer org.aoe.det.ww.d3man.ww.Jpct3DLayer
java.lang.NullPointerException
at com.threed.jpct.World.draw(World.java:2091)
at com.threed.jpct.World.draw(World.java:2073)
at com.threed.jpct.World.draw(World.java:1613)
at org.aoe.det.ww.d3man.ww.Jpct3DLayer.repaint(Jpct3DLayer.java:352)
at org.aoe.det.ww.d3man.ww.Jpct3DLayer.doRender(Jpct3DLayer.java:204)
at gov.nasa.worldwind.layers.AbstractLayer.render(AbstractLayer.java:232)
at gov.nasa.worldwind.AbstractSceneController.draw(AbstractSceneController.java:864)
at gov.nasa.worldwind.StereoOptionSceneController.draw(StereoOptionSceneController.java:153)
at gov.nasa.worldwind.BasicSceneController.doNormalRepaint(BasicSceneController.java:42)
at gov.nasa.worldwind.BasicSceneController.doRepaint(BasicSceneController.java:28)
at gov.nasa.worldwind.AbstractSceneController.repaint(AbstractSceneController.java:381)
at gov.nasa.worldwind.WorldWindowGLAutoDrawable.doDisplay(WorldWindowGLAutoDrawable.java:472)
at gov.nasa.worldwind.WorldWindowGLAutoDrawable.display(WorldWindowGLAutoDrawable.java:343)
at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:665)
at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:649)
at javax.media.opengl.awt.GLCanvas$10.run(GLCanvas.java:1289)
at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1119)
at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:994)
at javax.media.opengl.awt.GLCanvas$11.run(GLCanvas.java:1300)
at javax.media.opengl.Threading.invoke(Threading.java:193)
at javax.media.opengl.awt.GLCanvas.display(GLCanvas.java:541)
at javax.media.opengl.awt.GLCanvas.paint(GLCanvas.java:595)
at javax.media.opengl.awt.GLCanvas.update(GLCanvas.java:795)
at sun.awt.RepaintArea.updateComponent(RepaintArea.java:255)
at sun.awt.RepaintArea.paint(RepaintArea.java:232)
at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:358)
at java.awt.Component.dispatchEventImpl(Component.java:4957)
at java.awt.Component.dispatchEvent(Component.java:4703)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

[ Wed Sep 16 08:50:33 CST 2015 ] - WARNING: There's a problem with the object list not being consistent during rendering. This is often caused by concurrent modification of jPCT objects on a thread different from the rendering thread!
[ Wed Sep 16 08:50:33 CST 2015 ] - ERROR: null


Without source code, i do not know what is going on and what goes wrong.
I can only guess that something is not initialized or entitled a wrong value.
#2
Support / Re: Integrating jPCT in NASA 3D GIS WorldWind
September 13, 2015, 01:18:32 PM
Yes, i think you cache the Object3d rendering and other higher level operations, but they must be explained or compiled as gl operations and committed to the openGL engine(JOGL in this case).

And i get the stacktrace when the "protected void doRender(DrawContext dc)" is called.

Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 205 in Jpct3DLayer))
owns: Object  (id=140)
Jpct3DLayer.doRender(DrawContext) line: 205
Jpct3DLayer(AbstractLayer).render(DrawContext) line: 232
StereoOptionSceneController(AbstractSceneController).draw(DrawContext) line: 864
StereoOptionSceneController.draw(DrawContext) line: 153
StereoOptionSceneController(BasicSceneController).doNormalRepaint(DrawContext) line: 42
StereoOptionSceneController(BasicSceneController).doRepaint(DrawContext) line: 28
StereoOptionSceneController(AbstractSceneController).repaint() line: 381
WorldWindowGLAutoDrawable.doDisplay() line: 472
WorldWindowGLAutoDrawable.display(GLAutoDrawable) line: 343
GLDrawableHelper.displayImpl(GLAutoDrawable) line: 665
GLDrawableHelper.display(GLAutoDrawable) line: 649
GLCanvas$10.run() line: 1289
GLDrawableHelper.invokeGLImpl(GLDrawable, GLContext, Runnable, Runnable) line: 1119
GLDrawableHelper.invokeGL(GLDrawable, GLContext, Runnable, Runnable) line: 994
GLCanvas$11.run() line: 1300
Threading.invoke(boolean, Runnable, Object) line: 193
WorldWindowGLCanvas(GLCanvas).display() line: 541
WorldWindowGLCanvas(GLCanvas).paint(Graphics) line: 595
WorldWindowGLCanvas(GLCanvas).update(Graphics) line: 795
RepaintArea.updateComponent(Component, Graphics) line: 255
RepaintArea.paint(Object, boolean) line: 232
WCanvasPeer(WComponentPeer).handleEvent(AWTEvent) line: 358
WorldWindowGLCanvas(Component).dispatchEventImpl(AWTEvent) line: 4957
WorldWindowGLCanvas(Component).dispatchEvent(AWTEvent) line: 4703
EventQueue.dispatchEventImpl(AWTEvent, Object) line: 758
EventQueue.access$500(EventQueue, AWTEvent, Object) line: 97
EventQueue$3.run() line: 709
EventQueue$3.run() line: 703
AccessController.doPrivileged(PrivilegedAction<T>, AccessControlContext) line: not available [native method]
ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext, AccessControlContext) line: 75
ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext) line: 86
EventQueue$4.run() line: 731
EventQueue$4.run() line: 729
AccessController.doPrivileged(PrivilegedAction<T>, AccessControlContext) line: not available [native method]
ProtectionDomain$1.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext, AccessControlContext) line: 75
EventQueue.dispatchEvent(AWTEvent) line: 728
EventDispatchThread.pumpOneEventForFilters(int) line: 201
EventDispatchThread.pumpEventsForFilter(int, Conditional, EventFilter) line: 116
EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component) line: 105
EventDispatchThread.pumpEvents(int, Conditional) line: 101
EventDispatchThread.pumpEvents(Conditional) line: 93
EventDispatchThread.run() line: 82

The stack trace "EventQueue.dispatchEventImpl(AWTEvent, Object) line: 758   " tells the method is called in AWT EDT.
So we can apply gl and GUI operations.

I think WW has the same mechanism as jPCT in rendering: 1) gl operations are wrapped in some objects such as Layer in WW, 2) update is send to EDT by something like event, 3) EDT calls back to the wrapper layer objects to perform the actual gl operations. Most GUI uses the same mechanism to assure the multi-thread safety.

In my opinion, what we need is to called some method that explains/compiles higher level operations and execute the result gl operations directly.
No camera, no light, nor other extra elements. Only the 3d objects and texture, partical system and animations are needed, that is as simple as in the cube demo.

Would you please give some example code for me to insert the IPaintListener and output the information you want?
#3
Support / Re: Integrating jPCT in NASA 3D GIS WorldWind
September 13, 2015, 07:47:41 AM
Hi, EgonOlsen, let's go on:)
I read an example code in WW.
In the following code, a cube(the same as a primitive box in jPCT) is drawn in WW.


/*
* Copyright (C) 2012 United States Government as represented by the Administrator of the
* National Aeronautics and Space Administration.
* All Rights Reserved.
*/

package gov.nasa.worldwindx.examples.tutorial;

import gov.nasa.worldwind.Configuration;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.pick.PickSupport;
import gov.nasa.worldwind.render.*;
import gov.nasa.worldwind.util.OGLUtil;
import gov.nasa.worldwindx.examples.ApplicationTemplate;

import javax.media.opengl.*;
import java.awt.*;

/**
* Example of a custom {@link Renderable} that draws a cube at a geographic
* position. This class shows the simplest possible example of a custom
* Renderable, while still following World Wind best practices. See
* http://goworldwind.org/developers-guide/how-to-build-a-custom-renderable/ for
* a complete description of this example.
*
* @author pabercrombie
* @version $Id: Cube.java 691 2012-07-12 19:17:17Z pabercrombie $
*/
public class Cube extends ApplicationTemplate implements Renderable {
/** Geographic position of the cube. */
protected Position position;
/** Length of each face, in meters. */
protected double size;

/** Support object to help with pick resolution. */
protected PickSupport pickSupport = new PickSupport();

// Determined each frame
protected long frameTimestamp = -1L;
protected OrderedCube currentFramesOrderedCube;

/**
* This class holds the Cube's Cartesian coordinates. An instance of it is
* added to the scene controller's ordered renderable queue during picking
* and rendering.
*/
protected class OrderedCube implements OrderedRenderable {
/**
* Cartesian position of the cube, computed from
* {@link gov.nasa.worldwindx.examples.tutorial.Cube#position}.
*/
protected Vec4 placePoint;
/** Distance from the eye point to the cube. */
protected double eyeDistance;
/**
* The cube's Cartesian bounding extent.
*/
protected Extent extent;

public double getDistanceFromEye() {
return this.eyeDistance;
}

public void pick(DrawContext dc, Point pickPoint) {
// Use same code for rendering and picking.
this.render(dc);
}

public void render(DrawContext dc) {
Cube.this.drawOrderedRenderable(dc, Cube.this.pickSupport);
}
}

public Cube(Position position, double sizeInMeters) {
this.position = position;
this.size = sizeInMeters;
}

public void render(DrawContext dc) {
// Render is called twice, once for picking and once for rendering. In
// both cases an OrderedCube is added to
// the ordered renderable queue.

OrderedCube orderedCube = this.makeOrderedRenderable(dc);

if (orderedCube.extent != null) {
if (!this.intersectsFrustum(dc, orderedCube))
return;

// If the shape is less that a pixel in size, don't render it.
if (dc.isSmall(orderedCube.extent, 1))
return;
}

// Add the cube to the ordered renderable queue. The SceneController
// sorts the ordered renderables by eye
// distance, and then renders them back to front.
dc.addOrderedRenderable(orderedCube);
}

/**
* Determines whether the cube intersects the view frustum.
*
* @param dc
*            the current draw context.
*
* @return true if this cube intersects the frustum, otherwise false.
*/
protected boolean intersectsFrustum(DrawContext dc, OrderedCube orderedCube) {
if (dc.isPickingMode())
return dc.getPickFrustums().intersectsAny(orderedCube.extent);

return dc.getView().getFrustumInModelCoordinates()
.intersects(orderedCube.extent);
}

/**
* Compute per-frame attributes, and add the ordered renderable to the
* ordered renderable list.
*
* @param dc
*            Current draw context.
*/
protected OrderedCube makeOrderedRenderable(DrawContext dc) {
// This method is called twice each frame: once during picking and once
// during rendering. We only need to
// compute the placePoint, eye distance and extent once per frame, so
// check the frame timestamp to see if
// this is a new frame. However, we can't use this optimization for 2D
// continuous globes because the
// Cartesian coordinates of the cube are different for each 2D globe
// drawn during the current frame.

if (dc.getFrameTimeStamp() != this.frameTimestamp
|| dc.isContinuous2DGlobe()) {
OrderedCube orderedCube = new OrderedCube();

// Convert the cube's geographic position to a position in Cartesian
// coordinates. If drawing to a 2D
// globe ignore the shape's altitude.
if (dc.is2DGlobe()) {
orderedCube.placePoint = dc.getGlobe()
.computePointFromPosition(this.position.getLatitude(),
this.position.getLongitude(), 0);
} else {
orderedCube.placePoint = dc.getGlobe()
.computePointFromPosition(this.position);
}

// Compute the distance from the eye to the cube's position.
orderedCube.eyeDistance = dc.getView().getEyePoint()
.distanceTo3(orderedCube.placePoint);

// Compute a sphere that encloses the cube. We'll use this sphere
// for intersection calculations to determine
// if the cube is actually visible.
orderedCube.extent = new Sphere(orderedCube.placePoint,
Math.sqrt(3.0) * this.size / 2.0);

// Keep track of the timestamp we used to compute the ordered
// renderable.
this.frameTimestamp = dc.getFrameTimeStamp();
this.currentFramesOrderedCube = orderedCube;

return orderedCube;
} else {
return this.currentFramesOrderedCube;
}
}

/**
* Set up drawing state, and draw the cube. This method is called when the
* cube is rendered in ordered rendering mode.
*
* @param dc
*            Current draw context.
*/
protected void drawOrderedRenderable(DrawContext dc,
PickSupport pickCandidates) {
this.beginDrawing(dc);
try {
GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2
// compatibility.
if (dc.isPickingMode()) {
Color pickColor = dc.getUniquePickColor();
pickCandidates.addPickableObject(pickColor.getRGB(), this,
this.position);
gl.glColor3ub((byte) pickColor.getRed(),
(byte) pickColor.getGreen(), (byte) pickColor.getBlue());
}

// Render a unit cube and apply a scaling factor to scale the cube
// to the appropriate size.
gl.glScaled(this.size, this.size, this.size);
this.drawUnitCube(dc);
} finally {
this.endDrawing(dc);
}
}

/**
* Setup drawing state in preparation for drawing the cube. State changed by
* this method must be restored in endDrawing.
*
* @param dc
*            Active draw context.
*/
protected void beginDrawing(DrawContext dc) {
GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2
// compatibility.

int attrMask = GL2.GL_CURRENT_BIT | GL2.GL_COLOR_BUFFER_BIT;

gl.glPushAttrib(attrMask);

if (!dc.isPickingMode()) {
dc.beginStandardLighting();
gl.glEnable(GL.GL_BLEND);
OGLUtil.applyBlending(gl, false);

// Were applying a scale transform on the modelview matrix, so the
// normal vectors must be re-normalized
// before lighting is computed.
gl.glEnable(GL2.GL_NORMALIZE);
}

// Multiply the modelview matrix by a surface orientation matrix to set
// up a local coordinate system with the
// origin at the cube's center position, the Y axis pointing North, the
// X axis pointing East, and the Z axis
// normal to the globe.
gl.glMatrixMode(GL2.GL_MODELVIEW);

Matrix matrix = dc.getGlobe().computeSurfaceOrientationAtPosition(
this.position);
matrix = dc.getView().getModelviewMatrix().multiply(matrix);

double[] matrixArray = new double[16];
matrix.toArray(matrixArray, 0, false);
gl.glLoadMatrixd(matrixArray, 0);
}

/**
* Restore drawing state changed in beginDrawing to the default.
*
* @param dc
*            Active draw context.
*/
protected void endDrawing(DrawContext dc) {
GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2
// compatibility.

if (!dc.isPickingMode())
dc.endStandardLighting();

gl.glPopAttrib();
}

/**
* Draw a unit cube, using the active modelview matrix to orient the shape.
*
* @param dc
*            Current draw context.
*/
protected void drawUnitCube(DrawContext dc) {
// Vertices of a unit cube, centered on the origin.
float[][] v = { { -0.5f, 0.5f, -0.5f }, { -0.5f, 0.5f, 0.5f },
{ 0.5f, 0.5f, 0.5f }, { 0.5f, 0.5f, -0.5f },
{ -0.5f, -0.5f, 0.5f }, { 0.5f, -0.5f, 0.5f },
{ 0.5f, -0.5f, -0.5f }, { -0.5f, -0.5f, -0.5f } };

// Array to group vertices into faces
int[][] faces = { { 0, 1, 2, 3 }, { 2, 5, 6, 3 }, { 1, 4, 5, 2 },
{ 0, 7, 4, 1 }, { 0, 7, 6, 3 }, { 4, 7, 6, 5 } };

// Normal vectors for each face
float[][] n = { { 0, 1, 0 }, { 1, 0, 0 }, { 0, 0, 1 }, { -1, 0, 0 },
{ 0, 0, -1 }, { 0, -1, 0 } };

// Note: draw the cube in OpenGL immediate mode for simplicity. Real
// applications should use vertex arrays
// or vertex buffer objects to achieve better performance.
GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2
// compatibility.
gl.glBegin(GL2.GL_QUADS);
try {
for (int i = 0; i < faces.length; i++) {
gl.glNormal3f(n[i][0], n[i][1], n[i][2]);

for (int j = 0; j < faces[0].length; j++) {
gl.glVertex3f(v[faces[i][j]][0], v[faces[i][j]][1],
v[faces[i][j]][2]);
}
}
} finally {
gl.glEnd();
}
}

protected static class AppFrame extends ApplicationTemplate.AppFrame {
public AppFrame() {
super(true, true, false);

RenderableLayer layer = new RenderableLayer();
Cube cube = new Cube(Position.fromDegrees(35.0, -120.0, 3000), 1000);
layer.addRenderable(cube);

getWwd().getModel().getLayers().add(layer);
}
}

public static void main(String[] args) {
Configuration.setValue(AVKey.INITIAL_LATITUDE, 35.0);
Configuration.setValue(AVKey.INITIAL_LONGITUDE, -120.0);
Configuration.setValue(AVKey.INITIAL_ALTITUDE, 15500);
Configuration.setValue(AVKey.INITIAL_PITCH, 45);
Configuration.setValue(AVKey.INITIAL_HEADING, 45);

ApplicationTemplate.start("World Wind Custom Renderable Tutorial",
AppFrame.class);
}
}


The key steps are:
1. create a WW's renderable layer
RenderableLayer layer = new RenderableLayer();

2. create the cube and put it on the layer
Cube cube = new Cube(Position.fromDegrees(35.0, -120.0, 3000), 1000);
layer.addRenderable(cube);

3. insert the layer into WW's layer list.
getWwd().getModel().getLayers().add(layer);

When the WW want to update the scene, it calls the doRender() method in its layers, here is the definition:

protected abstract void doRender(DrawContext dc);   

the gl and other objects are passed in by the parameter dc.

Then, the RenderableLayer holding the cube will call the cube's drawOrderedRenderable method.
The drawOrderedRenderable method do 3 steps:
1. call beginDrawing() to prepare
2. call drawUnitCube() to draw the cube with gl operations
3. call endDrawing() to clean something

The key is that, in beginDrawing, a local coordinate is prepared:

      // Multiply the modelview matrix by a surface orientation matrix to set
      // up a local coordinate system with the
      // origin at the cube's center position, the Y axis pointing North, the
      // X axis pointing East, and the Z axis
      // normal to the globe.
      gl.glMatrixMode(GL2.GL_MODELVIEW);

      Matrix matrix = dc.getGlobe().computeSurfaceOrientationAtPosition(
            this.position);
      matrix = dc.getView().getModelviewMatrix().multiply(matrix);

      double[] matrixArray = new double[16];
      matrix.toArray(matrixArray, 0, false);
      gl.glLoadMatrixd(matrixArray, 0);

These code lines tell both WW's dc and OpenGL's gl to set a new local coord.
Thus the cube will be drawn and translated to the correct position.

In the former post, i do not make such a translation in the jPCT layer.

How to apply this to jPCT layer?
In the former post, the jPCT's origin point is (0,0,0) at the center of the earth.
Now we have two options: 1) keep the origin at (0, 0, 0), 2)move the origin to the surface of the earth and change the box's coord to the new local coord.
Actually, i think the option 1) do not need a new local coord system, for the local's origin is the same as the old, so no matrix are needed.
Then i tried the option 2).
the matrix is:

Matrix matrix = dc.getGlobe()
            .computeSurfaceOrientationAtPosition(boxPos.latitude, boxPos.longitude, oElv);
            
oElv is a variable, so i can change it in my script Frame.

first, 0, the box is gone.
then, 16000, the original elevation of the box, i see it when the WW's eye point is (0, 20, 16020).
then, 17000, i see the box when the WW's eye point is about (0, 20, 16520).

It seems that, the matrix do change the location of the box, but not the way i thought.

If the matrix has the same effect as in cube demo, the box should be at WW's (0, 40, 16000+16000) or (0, 40, 16000+17000).
The result is that it is at (0, 20, 16000) and (0, 20, 165xx).

Now, i begin to guess, for i have no jPCT code.
1. jPCT draw the Object3ds by gl operations as those in cude demo.
2. jPCT do some coord translations. At lease, jPCT translate visible Object3ds to render them in the camera's vision.
3. when i fore jPCT to draw(in the forceDraw method), jPCT may perform the gl operations directly or indirectly (in a double-buffer and copy the result to the canvas).

According to the cube demo, it will be straightfully for us to apply the translating matrix and gl operations to show objects in WW.
So i wonder, how can i force jPCT to commit the gl operations without any of its internal translations or buffer mechanisms?
That will make things simple and straightful.
#4
Support / Re: Integrating jPCT in NASA 3D GIS WorldWind
September 12, 2015, 11:32:46 AM
Well, another bug is:
when the code "this.world.setAmbientLight(255, 255, 255);" is changed to "this.world.setAmbientLight(0, 0, 0);"
the earth will become black.

This means that the light in jPCT affects those in WW.
#5
Support / Integrating jPCT in NASA 3D GIS WorldWind
September 12, 2015, 11:29:56 AM
In order to draw 3d animations in WorldWind, i'm trying to introducing jPCT into it.
The idea is simple: 1.inject WW's GL2 object into jPCT, 2. jPCT draws all of its Object3ds on the GL2, 3. A WW's layer is used to wrap 1 & 2.

Firstly, i write a ww's layer Jpct3DLayer which extends ww's AbstractLayer.

In the method doRender(), which will be called back when the WW is request to update, the following operations are performed:
1. store all WW's GL matrix.
2. inject the WW's GL into jPCT if it is not the same as last injected.
3. set the camera location to WW's eyepoint, the coordinates are adjusted from (x,y,z) to (x,-y,-z).
4. call jPCT to repaint its world.
5. force jPCT  to draw its scene into injected GL.
6. restore all WW's GL matrix.

To test the jPCT layer, i load a .3ds file with a .jpg texture. And rotate the 3d object continously.

The layer looks like:

package org.aoe.det.ww.d3man.ww;

import java.awt.Canvas;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;

import org.aoe.det.ww.d3man.D3Man;
import org.gbzh.util.log.Log;
import org.gbzh.util.resource.Resource;

import com.threed.jpct.FrameBuffer;
import com.threed.jpct.IRenderer;
import com.threed.jpct.Loader;
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.Util;
import com.threed.jpct.World;

import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.geom.Vec4;
import gov.nasa.worldwind.layers.AbstractLayer;
import gov.nasa.worldwind.render.DrawContext;

/**
* 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. */
public World world;
/***/
public FrameBuffer buffer;
public GL2 lastGL;
public Canvas canvas;
public Object3D box;

public Jpct3DLayer() {
this.world = new World();
this.world.setAmbientLight(255, 255, 255);

TextureManager.getInstance().addTexture("box",
new Texture(Resource.getResource("data/red.jpg")));

Object3D[] objs=Loader.load3DS(Resource.getResource("data/spaceship3.3ds"), 1);
    if (objs.length>0) {
    box = Object3D.mergeAll(objs);
    box.scale(0.3f);
    }else{      
    box = Primitives.getBox(13f, 2f);
    }

box.setTexture("box");
box.setEnvmapped(Object3D.ENVMAP_ENABLED);
box.build();
world.addObject(box);
Position boxPos = Position.fromDegrees(0, 20, 16000);
Position camPos = Position.fromDegrees(0, 20, 16000);

setObject3DPosition(box, ww2jpct(boxPos));
this.world.getCamera().setPosition(ww2jpct(camPos));
this.world.getCamera().lookAt(ww2jpct(boxPos));



new Thread(){//rotate the box
@Override
public void run() {
while(true){
box.rotateZ(0.1f);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
/**
* prepare a jPCT FrameBuffer for given width&height.
* @param width
* @param height
*/
private void preparejPCTBuffer(int width, int height) {
method: do {
if(this.buffer!=null){
if(this.buffer.getHeight()!=height || this.buffer.getWidth()!=width){
this.buffer.dispose();
this.buffer = null;
}
}
if(this.buffer == null){
this.buffer = new FrameBuffer(width, height,
FrameBuffer.SAMPLINGMODE_NORMAL);

canvas = buffer.enableGLCanvasRenderer();
buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
}
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);
gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);

// if (!dc.isPickingMode()) {
// gl.glEnable(GL.GL_BLEND);
// gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
// }

gl.glMatrixMode(GL2.GL_MODELVIEW);//|GL2.GL_PROJECTION|GL2.GL_TEXTURE);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glMatrixMode(GL2.GL_TEXTURE);
gl.glPushMatrix();
gl.glLoadIdentity();

gl.glMatrixPushEXT(GL2.GL_MODELVIEW);
gl.glMatrixPushEXT(GL2.GL_PROJECTION);
gl.glMatrixPushEXT(GL2.GL_TEXTURE);
this.preparejPCTBuffer(dc.getDrawableWidth(), dc.getDrawableHeight());
// inject gl if neccessary
if (this.lastGL != gl) {
Util.injectExternalGL(canvas, gl);
this.lastGL = gl;
}
}
/**
* Called by WorldWind to refresh this layer.
*/
@Override
protected void doRender(DrawContext dc) {
this.beginDraw(dc);

// 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));
this.world.getCamera().lookAt(new SimpleVector(0, 0, 0));

// save current gl settings before change it
dc.getView().pushReferenceCenter(dc, eyeLoc);

// jPCT draw its world with the given gl
this.repaint();

// force jPCT to draw on WW's gl.
Util.forceDraw(canvas);

    // restore last gl settings
dc.getView().popReferenceCenter(dc);
this.endDraw(dc);
}

// resets opengl state
protected void endDraw(DrawContext dc) {
GL2 gl = (GL2) dc.getGL();

gl.glMatrixPopEXT(GL2.GL_TEXTURE);
gl.glMatrixPopEXT(GL2.GL_PROJECTION);
gl.glMatrixPopEXT(GL2.GL_MODELVIEW);

gl.glMatrixMode(GL2.GL_TEXTURE);
gl.glPopMatrix();
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glPopMatrix();
gl.glMatrixMode(GL2.GL_MODELVIEW);//|GL2.GL_PROJECTION|GL2.GL_TEXTURE);
gl.glPopMatrix();

gl.glPopAttrib();
}

/**
* 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);
}
/**
* move the object to the given position, not delta.
* x,y,z is jPCT coordinate.
* @param obj
* @param x
* @param y
* @param z
*/
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;
}



/**
* force this layer to redraw components inside it.
*/
public void repaint() {
// buffer.clear(new Color(0.0f,0.0f,0.0f,1.0f));
world.renderScene(buffer);
world.draw(buffer);
buffer.update();
buffer.displayGLOnly();
canvas.repaint();
}
}


As we can see, the Object3d box(.3ds if loaded, or a primitive box) is placed at (0, 20, 16000) with WW's latitude-longitude-elevation coordinate.

To debug the layer, i add a BeanShell script engine so that i can execute script's lively.
When i execute the following script to locate the 3d object, i can not directly see it.
In fact, it is blocked by other layers. Event when i put the jPCTLayer at the top or last of the layers' list, it is blocked.
When i unselect the blocker layer, make it invisible, i can see the jPCT's 3d object, rotating.

import gov.nasa.worldwind.geom.Position;
import java.util.ArrayList;
import java.util.List;
import org.gbzh.jsapi.tts.AudioData;
import org.gbzh.jsapi.tts.SimplePlayer;
import org.gbzh.jsapi.tts.SpeechEngine;
import org.aoe.det.ww.d3man.ww.KMLLayerMan;


wwFunc(){
  //go to given position
  public void GoTo(double latitude, double longitude, double elevation){
    Position position = Position.fromDegrees(latitude, longitude, elevation);
    worldwindow.getView().goTo(position, elevation);
  }
  return this;
}
ww = wwFunc();

ww.GoTo(0.0, 20.0, 16020.0);


I don't know why the jPCT layer is blocked by others.

And the WW dose not function well with jPCT layer.
When the cursor is on the WW's earth globe, it will display the current lat-lon-elev data.
But when the jPCT layer is loaded, it only displays "Off", which means the cursor is not on the globe.
Another problem is the navigator view display nothing but white square.

The following code shows how i force jPCT to draw on WW's GL. Note that, it is in the package com.threed.jpct, where we can access the JOGLCanvas and it's package-level methods.

package com.threed.jpct;

import java.awt.Canvas;

import javax.media.opengl.GL;

public class Util {
public static void forceDraw(Canvas canvas){
JOGLCanvas jc = (JOGLCanvas)canvas;
jc.display(null);
}

public static void injectExternalGL(Canvas canvas, GL gl){
JOGLCanvas jc = (JOGLCanvas)canvas;
jc.injectExternalGL(gl);
}
}



I'm trying to find the reason, but without jPCT's source, its really painful.

I'll go on until succeed or give up.

PS: The missed classes such as Log and Resource is simple. Log outputs log information and Resource fetches files from a given directory.
#6
Bugs / Re: jPCT dose not support jogl 2.1.5
September 12, 2015, 10:43:05 AM
Ok, let's end this thread, since the new version jogl such as 2.1.5 can be used by jPCT as http://www.jpct.net/forum2/index.php/topic,4454.msg30870.html#msg30870 described.

I'd like to open another thread to discuss the integrating of jPCT and WorldWind.

And would you please release the new version supporting higher jogl.
#7
Bugs / Re: jPCT dose not support jogl 2.1.5
September 07, 2015, 04:37:47 PM
I've tried to push all that i can image, but the problem goes on.

When i load a .3ds file with the picture texture, WW's maps can be pasted corectly after the box/model goes out of sight. But i can no longer see the model again. It is covered by the WW's map layer--I do not know the reason now.

Is there some differences between drawing a box and a Primitive box? Some gl coordinate or texture transforms?

Or is it about FBO/VBO? Actually, i have no more idea now.




// 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);
gl.glPushAttrib(GL2.GL_ALL_ATTRIB_BITS);

// if (!dc.isPickingMode()) {
// gl.glEnable(GL.GL_BLEND);
// gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
// }

gl.glMatrixMode(GL2.GL_MODELVIEW);//|GL2.GL_PROJECTION|GL2.GL_TEXTURE);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glMatrixMode(GL2.GL_TEXTURE);
gl.glPushMatrix();
gl.glLoadIdentity();

gl.glMatrixPushEXT(GL2.GL_MODELVIEW);
gl.glMatrixPushEXT(GL2.GL_PROJECTION);
gl.glMatrixPushEXT(GL2.GL_TEXTURE);
// inject gl if neccessary
if (this.lastGL != gl) {
Util.injectExternalGL(canvas, gl);
this.lastGL = gl;
}
}
/**
* Called by WorldWind to refresh this layer.
*/
@Override
protected void doRender(DrawContext dc) {
this.beginDraw(dc);

// 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));
this.world.getCamera().lookAt(new SimpleVector(0, 0, 0));

// save current gl settings before change it
dc.getView().pushReferenceCenter(dc, eyeLoc);

// jPCT draw its world with the given gl
this.repaint();

// force jPCT to draw on WW's gl.
Util.forceDraw(canvas);

    // restore last gl settings
dc.getView().popReferenceCenter(dc);
this.endDraw(dc);
}

// resets opengl state
protected void endDraw(DrawContext dc) {
GL2 gl = (GL2) dc.getGL();

gl.glMatrixPopEXT(GL2.GL_TEXTURE);
gl.glMatrixPopEXT(GL2.GL_PROJECTION);
gl.glMatrixPopEXT(GL2.GL_MODELVIEW);

gl.glMatrixMode(GL2.GL_TEXTURE);
gl.glPopMatrix();
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glPopMatrix();
gl.glMatrixMode(GL2.GL_MODELVIEW);//|GL2.GL_PROJECTION|GL2.GL_TEXTURE);
gl.glPopMatrix();

gl.glPopAttrib();
}
#8
Bugs / Re: jPCT dose not support jogl 2.1.5
September 06, 2015, 11:22:06 AM
I remove the buffer clear operation in the repaint method, now i can see the WW's other layers.
However, the map layer is affected, all map textures are virtically placed, as in attachment.

I think the texture "matrix" is modified and not restored.
So, how can i save the configuration of GL in beginDraw(DrawContext), and restore it in endDraw(DrawContext dc).

Hope this is the last BUG question:)


package org.aoe.det.ww.d3man.ww;

import java.awt.Canvas;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;

import org.aoe.det.ww.d3man.D3Man;
import org.gbzh.util.log.Log;
import org.gbzh.util.resource.Resource;

import com.threed.jpct.FrameBuffer;
import com.threed.jpct.IRenderer;
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.Util;
import com.threed.jpct.World;

import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.geom.Vec4;
import gov.nasa.worldwind.layers.AbstractLayer;
import gov.nasa.worldwind.render.DrawContext;

/**
* 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;

public Jpct3DLayer() {
this.world = new World();
this.world.setAmbientLight(255, 255, 255);

TextureManager.getInstance().addTexture("box",
new Texture(Resource.getResource("data/red.jpg")));

box = Primitives.getBox(13f, 2f);

box.setTexture("box");
box.setEnvmapped(Object3D.ENVMAP_ENABLED);
box.build();
world.addObject(box);
Position boxPos = Position.fromDegrees(0, 0, 13);
Position camPos = Position.fromDegrees(0, 0, 0);

setObject3DPosition(box, ww2jpct(boxPos));
this.world.getCamera().setPosition(ww2jpct(camPos));
this.world.getCamera().lookAt(ww2jpct(boxPos));

this.buffer = new FrameBuffer(800, 600,
FrameBuffer.SAMPLINGMODE_NORMAL);

canvas = buffer.enableGLCanvasRenderer();
buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);

new Thread(){//rotate the box
@Override
public void run() {
while(true){
box.rotateZ(0.1f);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}

// 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) {
Util.injectExternalGL(canvas, 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();
}

/**
* 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);
}
/**
* move the object to the given position, not delta.
* x,y,z is jPCT coordinate.
* @param obj
* @param x
* @param y
* @param z
*/
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);

// 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));
this.world.getCamera().lookAt(new SimpleVector(0, 0, 0));

// save current gl settings before change it
dc.getView().pushReferenceCenter(dc, eyeLoc);

// jPCT draw its world with the given gl
this.repaint();

// force jPCT to draw on WW's gl.
Util.forceDraw(canvas);

    // restore last gl settings
dc.getView().popReferenceCenter(dc);
this.endDraw(dc);
}

/**
* force this layer to redraw components inside it.
*/
public void repaint() {
// buffer.clear(new Color(0.0f,0.0f,0.0f,1.0f));
world.renderScene(buffer);
world.draw(buffer);
buffer.update();
buffer.displayGLOnly();
canvas.repaint();
}
}

#9
Bugs / Re: jPCT dose not support jogl 2.1.5
September 06, 2015, 08:42:39 AM
After change the injectGL method, i think i see the box:)

I add an injectExternalGL method and change the injectGL in JOGLCanvas as following:

private GL externalGL = null;

/**
* inject the external GL
* @param gl null means no external GL
*/
public void injectExternalGL(GL gl){
externalGL = gl;
}

/**the last GL injected.*/
private GL lastGL = null;

private void injectGL() {
GL gl;
if(externalGL!=null){
gl = externalGL;
}else{
gl = GLContext.getCurrent().getGL();
}
if(lastGL==gl){
return;
}
Class<?>[] classes = new Class[] { org.lwjgl.opengl.GL11.class,
org.lwjgl.opengl.GL15.class, org.lwjgl.opengl.GL20.class,
org.lwjgl.opengl.Util.class,
org.lwjgl.opengl.ARBMultitexture.class,
org.lwjgl.opengl.EXTFramebufferObject.class,
org.lwjgl.opengl.ARBShaderObjects.class,
org.lwjgl.opengl.GLContext.class };
for (int i = 0; i < classes.length; i++) {
Class<?> clazz = classes[i];
try {
Field glf = clazz.getDeclaredField("gl");
glf.set(clazz, gl);
} catch (Exception e) {
Logger.log("Unable to inject GL context into the facade!",
Logger.ERROR);
}
}
}


Then, create a Util class in package com.threed.jpct to access the JOGLCanvas:

package com.threed.jpct;

import java.awt.Canvas;

import javax.media.opengl.GL;

public class Util {
public static void forceDraw(Canvas canvas){
JOGLCanvas jc = (JOGLCanvas)canvas;
jc.display(null);
}

public static void injectExternalGL(Canvas canvas, GL gl){
JOGLCanvas jc = (JOGLCanvas)canvas;
jc.injectExternalGL(gl);
}
}


The forceDraw method calls the "public void display(GLAutoDrawable tGLAutoDrawable)" to draw to gl (we injected by injectExternalGL).

Then i can see the box as the picture in attachment shows.

So, next questions are: 1. how can i clear the canvas with transparent color? 2. can i adjust the camera to see as far as possible?
#10
Bugs / Re: jPCT dose not support jogl 2.1.5
September 06, 2015, 02:55:52 AM
Actually, i did not look into WW's painting mechanism.
I think WW also caches the gl operations performed in the callback method doRender.
So the best solution is to push all gl operations into WW's gl queue.
But i can not find where the gl operations are performed in jPCT.
I guess the IThreadBuffer is a thread that caches painting opeartions and draws them to gl when called by the EDT.

WW's layer mechanism is quit straightful: 1)all displayed are layers, 2)WW call the layers' onDraw to gather and cache gl operations. The layer needs to transform the gl (move, rotate, ...) before it perform gl operations and restore the configuration of the gl passed in as a parameter.

I think the coordination is right, as you said (x,-y,-z).

The key is that jPCT's IThreadBuffer do not insert its gl operations into WW's queue before WW commit them to the display card. However the JFrame receives the image later.
So, can i inject the cached gl operations in IThreadBuffer to WW's gl queue by calling JOGLCanvas.display(null) method? Or world you please adjust that and open a direct-call method to do that.
#11
Bugs / Re: jPCT dose not support jogl 2.1.5
September 05, 2015, 04:05:01 PM
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();
}
}
}
}

#12
Bugs / Re: jPCT dose not support jogl 2.1.5
September 01, 2015, 10:04:43 AM
Thanks EgonOlsen again.
I change my program and it runs without the "NoClassDefFoundError".
But my next question is, where is my 3d box:)

As in the following code, i set the box on the surface of the earth, and the camera alittle higher than it.
But i can not find the box in WorldWind.


package org.aoe.det.ww.d3man.ww;

import java.awt.Canvas;
import java.lang.reflect.Field;

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.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.geom.Position;
import gov.nasa.worldwind.geom.Vec4;
import gov.nasa.worldwind.layers.AbstractLayer;
import gov.nasa.worldwind.render.DrawContext;
/**
* 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.
* @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 float surfaceElevation = 6378137.0f;
private SimpleVector boxLoc = new SimpleVector(0, 0, -(surfaceElevation+50000));
private SimpleVector cameraLoc = new SimpleVector(0, 0, -(surfaceElevation+50000+100));
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(boxLoc);
this.world.getCamera().setPosition(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);
}

// 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);
}
}

/**
* Called by WorldWind to refresh this layer.
*/
@Override
protected void doRender(DrawContext dc) {
System.out.println("move="+move);
this.beginDraw(dc);

GL2 gl = (GL2) dc.getGL();
//get the WW position of the box.
Position position = D3Man.getInstance().translatePosition(
boxLoc.x, boxLoc.y, -boxLoc.z);
Vec4 loc = dc.getGlobe().computePointFromPosition(position);
double size = this.computeSize(dc, loc);

//move the box a little
move = move - 1;
box.translate(0, 0, move);

//save current gl settings before change it
dc.getView().pushReferenceCenter(dc, loc);

//adjust current gl settings for jPCT's world
gl.glRotated(position.getLongitude().degrees, 0, 1, 0);
gl.glRotated(-position.getLatitude().degrees, 1, 0, 0);
gl.glScaled(size, size, size);

// jPCT draw its world with the given gl
this.repaint();

//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 = 60 * dc.getView().computePixelSizeAtDistance(d);
if (size < 2)
size = 2;

return size;
}

/**
* force this layer to redraw components inside it.
*/
public void repaint() {
buffer.clear(java.awt.Color.GREEN);
world.renderScene(buffer);
world.draw(buffer);
buffer.update();
buffer.displayGLOnly();
canvas.repaint();
}

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);

float x = 0f;
float y = 0f;
float z = 0f;
while (frame.isShowing()) {
layer.box.rotateY(0.1f);
y += 0.2f;
SimpleVector sv = new SimpleVector(x, y, z);
layer.box.translate(sv);
layer.buffer.clear(java.awt.Color.BLUE);
System.out.println(layer.box.getTranslation());
layer.world.renderScene(layer.buffer);
layer.world.draw(layer.buffer);
layer.buffer.update();
layer.buffer.displayGLOnly();
layer.canvas.repaint();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}


In the posted code, WW calls the doRender method and gives us a DrawContext where we can find the GL2 object.
I inject the GL2 object to jPCT classes.
I think it is a question about coordination transforming, but how can i get the right transformation to let jPCT
draw the box with WW's GL2?

BTW, the code can be run as a simple java app, with its main() method.

PS: Should i open another post to ask this question?
#13
Bugs / Re: jPCT dose not support jogl 2.1.5
August 30, 2015, 03:10:58 PM
Thanks EgonOlsen, but i get another question to draw models in WorldWind with jPCT.

Accroding to WW's docs, i should implement the integration by implementing an interface(i.e. gov.nasa.worldwind.layers.Layer). So i extends an AbstractLayer who implemented the Layer.
And i should draw the models in jPCT to the provided GL2/3/4 object.
The code seems as follows:


package org.aoe.det.ww.d3man.ww;

import java.lang.reflect.Field;

import javax.media.opengl.GL;
import javax.media.opengl.GL2;

import org.gbzh.util.resource.Resource;

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.layers.AbstractLayer;
import gov.nasa.worldwind.render.DrawContext;

public class Jpct3DLayer extends AbstractLayer {
/** The world of jPCT. */
private World world;
/***/
private FrameBuffer buffer;
private GL2 lastGL;

public Jpct3DLayer() {
this.world = new World();
this.world.setAmbientLight(0, 255, 0);

TextureManager.getInstance().addTexture("box", new
Texture(Resource.getResource("data/POLYSHIP.jpg")));

Object3D box = Primitives.getBox(13f, 2f);
box.setTexture("box");
box.setEnvmapped(Object3D.ENVMAP_ENABLED);
box.build();
world.addObject(box);

this.world.getCamera().setPosition(50, -50, -5);
SimpleVector point = new SimpleVector(0.0, 0.0, 0.0);
this.world.getCamera().lookAt(point);// box.getTransformedCenter()

this.buffer = new FrameBuffer(800, 600,
FrameBuffer.SAMPLINGMODE_NORMAL);
this.buffer.disableRenderer(IRenderer.RENDERER_SOFTWARE);
this.buffer.enableRenderer(IRenderer.RENDERER_OPENGL,
IRenderer.MODE_OPENGL);

}

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;
for (int i = 0; i < classes.length; i++) {
try {
clazz = Class.forName(classes[i]);
Field glf = clazz.getDeclaredField("gl");
glf.set(clazz, gl);
} catch (Exception e) {
Logger.log("Unable to inject GL context into the facade!",
Logger.ERROR);
}
}
}

@Override
protected void doRender(DrawContext dc) {
GL2 gl = (GL2) dc.getGL();
if (this.lastGL != gl) {
this.injectGL(gl);
this.lastGL = gl;
}

// jPCT should draw its world with the given gl
this.repaint();
}

/**
* force this layer to redraw components inside it.
*/
public void repaint() {
world.renderScene(buffer);
world.draw(buffer);
buffer.update();
buffer.displayGLOnly();
}
}



I excluded the lwjgl.jars, but get the following error(the same as that in my last reply) when adding this layer to WW.

[ Sun Aug 30 21:01:13 CST 2015 ] - WARNING: Unsupported Texture width (260)...resizing to a width of 256 pixels!
Java version is: 1.8.0_45
-> support for BufferedImage
Version helper for 1.5+ initialized!
-> using BufferedImage
Software renderer (OpenGL mode) initialized
Software renderer disposed
Exception in thread "main" java.lang.NoClassDefFoundError: org/lwjgl/opengl/Display
   at com.threed.jpct.GLHelper.findMode(GLHelper.java:67)
   at com.threed.jpct.GLHelper.findMode(GLHelper.java:62)
   at com.threed.jpct.GLHelper.init(GLHelper.java:160)
   at com.threed.jpct.GLRenderer.init(GLRenderer.java:24)
   at com.threed.jpct.FrameBuffer.enableRenderer(FrameBuffer.java:1134)
   at com.threed.jpct.FrameBuffer.enableRenderer(FrameBuffer.java:753)
   at org.aoe.det.ww.d3man.ww.Jpct3DLayer.<init>(Jpct3DLayer.java:51)
   at org.aoe.det.ww.d3man.D3ManDemoApp$DemoAppFrame.<init>(D3ManDemoApp.java:68)
   at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
   at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
   at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
   at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
   at java.lang.Class.newInstance(Class.java:442)
   at gov.nasa.worldwindx.examples.ApplicationTemplate.start(ApplicationTemplate.java:294)
   at org.aoe.det.ww.d3man.D3ManDemoApp.main(D3ManDemoApp.java:79)
Caused by: java.lang.ClassNotFoundException: org.lwjgl.opengl.Display
   at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
   at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

That is to say, jPCT uses the class org.lwjgl.opengl.Display in somewhere.
How can i remove the dependency and use the pure jogl class?
#14
Bugs / Re: jPCT dose not support jogl 2.1.5
August 27, 2015, 03:20:50 PM
After modifying about ten lines, the new glfacade seems to be working.
I run the HelloWorldAWTGL without lwjgl jars, it works(and tell me the jogl is injected).

But the HelloWorldOGL can not run, the errors are:

Loading Texture...from InputStream
Java version is: 1.8.0_45
-> support for BufferedImage
Version helper for 1.5+ initialized!
-> using BufferedImage
Software renderer (OpenGL mode) initialized
Software renderer disposed
Exception in thread "main" java.lang.NoClassDefFoundError: org/lwjgl/opengl/Display
   at com.threed.jpct.GLHelper.findMode(GLHelper.java:67)
   at com.threed.jpct.GLHelper.findMode(GLHelper.java:62)
   at com.threed.jpct.GLHelper.init(GLHelper.java:160)
   at com.threed.jpct.GLRenderer.init(GLRenderer.java:24)
   at com.threed.jpct.FrameBuffer.enableRenderer(FrameBuffer.java:1134)
   at com.threed.jpct.FrameBuffer.enableRenderer(FrameBuffer.java:753)
   at com.threed.jpct.FrameBuffer.enableRenderer(FrameBuffer.java:700)
   at helloworld.HelloWorldOGL.loop(HelloWorldOGL.java:41)
   at helloworld.HelloWorldOGL.main(HelloWorldOGL.java:19)
Caused by: java.lang.ClassNotFoundException: org.lwjgl.opengl.Display
   at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
   at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
   ... 9 more

the org.lwjgl.opengl.Display can not be found in glfacade, it is in lwjgl.jar, but how can we find it when that jar excluded.
i comment the lines in the HelloWorldOGL to make it runnable.

All files are in attachment.

I manage them in maven-Eclipse.
Don't forget to replace the JOGLCanvas and JOGLRenderer in the jPCT project.

I really hope that the main jPCT project can be open sourced.
#15
Bugs / Re: jPCT dose not support jogl 2.1.5
August 27, 2015, 01:13:39 PM
I want to integrate some 3d engine into NASA WorldWind, so that i can load 3d models and animations.
Now, WW uses jogl 2.1.5 in my configuration.
And i think jPCT is a nice work for that purpose.

I'll try your suggestions and post my result.

thx.