mai*_*rgs 6 java geometry jogl worldwind
我试图弄清楚为什么PointPlacemarkAttributes中的setPitch似乎无法正常工作.
我相信PointPlacemark.java中的这个JOGL代码是出错的地方:
Double heading = getActiveAttributes().getHeading();
Double pitch = getActiveAttributes().getPitch();
// Adjust heading to be relative to globe or screen
if (heading != null)
{
if (AVKey.RELATIVE_TO_GLOBE.equals(this.getActiveAttributes().getHeadingReference()))
heading = dc.getView().getHeading().degrees - heading;
else
heading = -heading;
}
// Apply the heading and pitch if specified.
if (heading != null || pitch != null)
{
gl.glTranslated(xscale / 2, yscale / 2, 0);
if (pitch != null)
gl.glRotated(pitch, 1, 0, 0);
if (heading != null)
gl.glRotated(heading, 0, 0, 1);
gl.glTranslated(-xscale / 2, -yscale / 2, 0);
}
// Scale the unit quad
gl.glScaled(xscale, yscale, 1);
Run Code Online (Sandbox Code Playgroud)
这是一个我用过的简单驱动程序:
public class Placemarks extends ApplicationTemplate {
public static class AppFrame extends ApplicationTemplate.AppFrame {
public AppFrame() {
super(true, true, false);
final RenderableLayer layer = new RenderableLayer();
PointPlacemark pp = new PointPlacemark(Position.fromDegrees(28, -102, 30000));
pp.setLabelText("PointPlacemark");
pp.setLineEnabled(false);
pp.setAltitudeMode(WorldWind.ABSOLUTE);
PointPlacemarkAttributes attrs = new PointPlacemarkAttributes();
attrs.setImageAddress("gov/nasa/worldwindx/examples/images/georss.png");
attrs.setScale(1.0);
attrs.setImageOffset(Offset.CENTER);
attrs.setPitch(45.0);
pp.setAttributes(attrs);
layer.addRenderable(pp);
// Add the layer to the model.
insertBeforeCompass(getWwd(), layer);
}
}
public static void main(String[] args) {
ApplicationTemplate.start("WorldWind Placemarks", AppFrame.class);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我没有设置音高,它看起来很好:
但当我设置45度的音高时,它看起来像这样:
我不明白它与我设定的价值有何关联.我希望它能像指南针在CompassLayer中那样工作:
更新
评论建议迭代音高值以查看其工作原理.我这样做了,我仍然没有看到它应该如何工作.看起来它只是水平地"裁剪"图像,而不是做任何其他事情.这是一些代码:
public class Placemarks extends ApplicationTemplate {
public static class AppFrame extends ApplicationTemplate.AppFrame {
public AppFrame() {
super(true, true, false);
final RenderableLayer layer = new RenderableLayer();
PointPlacemark pp = new PointPlacemark(Position.fromDegrees(28, -102, 30000));
pp.setLabelText("PointPlacemark");
pp.setLineEnabled(false);
pp.setAltitudeMode(WorldWind.ABSOLUTE);
PointPlacemarkAttributes attrs = new PointPlacemarkAttributes();
attrs.setImageAddress("gov/nasa/worldwindx/examples/images/georss.png");
attrs.setScale(1.0);
attrs.setImageOffset(Offset.CENTER);
pp.setAttributes(attrs);
layer.addRenderable(pp);
// Add the layer to the model.
insertBeforeCompass(getWwd(), layer);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
for(double i = 0.0; i<360; i+=.1) {
attrs.setPitch(i);
System.out.println("Pitch is now "+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
AppFrame.this.getWwd().redrawNow();
}
}
});
t.start();
}
}
public static void main(String[] args) {
ApplicationTemplate.start("WorldWind Placemarks", AppFrame.class);
}
}
Run Code Online (Sandbox Code Playgroud)
并且屏幕录制了GIF:
问题在于PointPlacemark.doDrawOrderedRenderable(),在 中,所使用的正交投影矩阵使用从 -1 到 1 的深度值范围。
当音高保持为 0 时,z 坐标也保持为 0,安全地位于该范围的中间(实际上,WorldWind 中对该坐标有一些轻微的捏造,但不要介意)。当它倾斜时,z 坐标当然会改变,直到 90\xc2\xb0 所有 y 坐标都为 0,而 z 将达到图像高度的一半。这就是为什么只有位于 -1,1 范围内的图像切片可见,而其余部分被剪裁的原因。
\n\n该 z 范围由以下代码定义:
\n\n// The image is drawn using a parallel projection.\nosh.pushProjectionIdentity(gl);\ngl.glOrtho(0d, dc.getView().getViewport().width, 0d, dc.getView().getViewport().height, -1d, 1d);\nRun Code Online (Sandbox Code Playgroud)\n\n如果我们检查 中的等效代码CompassLayer,我们可以看到这里它们确实考虑了缩放的图标大小(尽管注释表明也许在某些早期迭代中,对 z 维度的关注较少):
double width = this.getScaledIconWidth();\ndouble height = this.getScaledIconHeight();\n\n// Load a parallel projection with xy dimensions (viewportWidth, viewportHeight)\n// into the GL projection matrix.\njava.awt.Rectangle viewport = dc.getView().getViewport();\nogsh.pushProjectionIdentity(gl);\ndouble maxwh = width > height ? width : height;\nif (maxwh == 0)\n maxwh = 1;\ngl.glOrtho(0d, viewport.width, 0d, viewport.height, -0.6 * maxwh, 0.6 * maxwh);\nRun Code Online (Sandbox Code Playgroud)\n\nz在本例中, ( )的参数\xc2\xb10.6 * maxwh使用 0.6 大概相当于 0.5 加上一些余量。实际的几何图形是一个单位四边形,它按 x/y 方向的半宽度/高度进行平移,并相应地缩放和旋转。
对于PointPlacemark,我们可以以类似的方式计算可渲染的大小。稍微重新排列代码,以便在设置投影之前进行比例计算,并添加maxwh:
// Compute the scale\ndouble xscale;\nDouble scale = this.getActiveAttributes().getScale();\nif (scale != null)\n xscale = scale * this.activeTexture.getWidth(dc);\nelse\n xscale = this.activeTexture.getWidth(dc);\n\ndouble yscale;\nif (scale != null)\n yscale = scale * this.activeTexture.getHeight(dc);\nelse\n yscale = this.activeTexture.getHeight(dc);\ndouble maxwh = Math.max(xscale, yscale);\n\n// The image is drawn using a parallel projection.\nosh.pushProjectionIdentity(gl);\ngl.glOrtho(0d, dc.getView().getViewport().width, 0d, dc.getView().getViewport().height, -0.6 * maxwh, 0.6 * maxwh);\nRun Code Online (Sandbox Code Playgroud)\n\n同样,0.6 允许有一些余量。
\n\n为 z 范围提供硬编码值可能是完全可以的,只要它们对于我们可能想要绘制的任何图像来说足够大,但又不会大到导致数值精度成为问题。相反,我们可以更进一步,考虑三角函数来计算出给定旋转和图像尺寸所需的实际深度,但这样做不会获得太多好处。
\n\n这确实是已报告的 WorldWindJava 的错误,以及此处的修复链接。
\n