Java OpenGL - 计算等距视图的正交平截头体
Java OpenGL - Calculating orthographic frustum for isometric view
我想弄清楚如何在正交投影下正确计算我的 openGL 场景的截锥体边界。我使用的代码如下:
public void setFrustum(GL gl, GLU glu){
double[] forwardAxis = properties.getForwardAxis();
double[] leftAxis = VecMath.normalVector(properties.getUpDir(), forwardAxis);
double[] upAxis = VecMath.normalVector(forwardAxis, leftAxis);
double[] v = bounds.getWidthVector();
double width = VecMath.magnitude(VecMath.project(v, leftAxis));
double height = VecMath.magnitude(VecMath.project(v, upAxis));
double modelRatio = width / height;
double canvasRatio = properties.getAspectRatio();
// -- height bigger than width --
if (modelRatio < canvasRatio){
// -- update width --
width = height * canvasRatio;
} else{
// -- update height --
height = width / canvasRatio;
}
double l = width / 2. * 1.15;
double b = height / 2. * 1.15;
double n = properties.getNear();
double f = properties.getFar();
gl.glOrtho(-l, l, -b, b, n, f);
}
所以你可以看到我得到了我的轴和我的宽度向量:
widthVector = (xWidth, yWidth, zWidth)
然后通过将这个宽度向量沿leftAxis和upAxis投影得到gl场景的宽度和高度。然后我将 aspectRatio 与我正在显示此场景的 canvas 的 aspectRatio 相匹配,并使用宽度和高度来计算正交平截头体的边界(使用 1.15 比例因子添加填充)。
这对除等轴测视图之外的所有视图都非常有效。以下是工作中的一些屏幕截图:
如您所见,底视图、左视图和前视图都很好。但是,等距视图被截断了(不,我在截屏时没有剪错!)。我必须将我使用的填充比例因子增加到 1.5 而不是 1.15,但我一定是在这里做错了什么。
如有任何帮助,我们将不胜感激。谢谢!
这是我的fitAllIn
简化
public void fitAllIn(float[] boundingMinMaxWorldSpace) {
Vec4 centerWorldSpace = new Vec4((boundingMinMaxWorldSpace[0] + boundingMinMaxWorldSpace[1]) / 2,
(boundingMinMaxWorldSpace[2] + boundingMinMaxWorldSpace[3]) / 2,
(boundingMinMaxWorldSpace[4] + boundingMinMaxWorldSpace[5]) / 2, 1f);
Vec3 min = new Vec3(boundingMinMaxWorldSpace[0], boundingMinMaxWorldSpace[2], boundingMinMaxWorldSpace[4]);
Vec3 max = new Vec3(boundingMinMaxWorldSpace[1], boundingMinMaxWorldSpace[3], boundingMinMaxWorldSpace[5]);
float diameter = (float) Math.sqrt(
(max.x - min.x) * (max.x - min.x)
+ (max.y - min.y) * (max.y - min.y)
+ (max.z - min.z) * (max.z - min.z));
if (getCurrView().orthographicProj) {
if (glViewer.getAspect() > 1) {
// projection * scale = y
getCurrView().scale = diameter / 2 / projectionSide;
} else {
// projection * aspect * scale = x
getCurrView().scale = diameter / 2 / (projectionSide * glViewer.getAspect());
}
getCurrView().scale = viewScale.clampScale(projectionSide, getCurrView().scale);
}
getCurrView().targetPos = new Vec3(centerWorldSpace);
glViewer.refresh();
基本上我通过了世界中的边界框 space,我计算了我的相机将瞄准的中心,我计算了最小点(minX、minY、minZ)和最大点。我得到直径,然后得到一个简单的方程来检索比例。
scale
和projectionSide
后面会用到我的正交矩阵
float x = projectionSide * glViewer.getAspect() * getCurrView().scale;
float y = projectionSide * getCurrView().scale;
float z = projectionSide;
return Jglm.orthographic(-x, x, -y, y, -z, z);
感谢 elect 的建议,这是我更新的 setFrustum 例程:
public void setFrustum(GL gl, GLU glu) {
double[] widthVec = bounds.getWidthVector();
double diameter = VecMath.magnitude(widthVec);
double canvasRatio = properties.getAspectRatio();
double scale = canvasRatio > 1 ? diameter / 2 : diameter / 2 / canvasRatio;
double x = canvasRatio * scale;
double y = scale;
double n = properties.getNear();
double f = properties.getFar();
gl.glOrtho(-x, x, -y, y, n, f);
}
完美运行。感谢 Elect!
我想弄清楚如何在正交投影下正确计算我的 openGL 场景的截锥体边界。我使用的代码如下:
public void setFrustum(GL gl, GLU glu){
double[] forwardAxis = properties.getForwardAxis();
double[] leftAxis = VecMath.normalVector(properties.getUpDir(), forwardAxis);
double[] upAxis = VecMath.normalVector(forwardAxis, leftAxis);
double[] v = bounds.getWidthVector();
double width = VecMath.magnitude(VecMath.project(v, leftAxis));
double height = VecMath.magnitude(VecMath.project(v, upAxis));
double modelRatio = width / height;
double canvasRatio = properties.getAspectRatio();
// -- height bigger than width --
if (modelRatio < canvasRatio){
// -- update width --
width = height * canvasRatio;
} else{
// -- update height --
height = width / canvasRatio;
}
double l = width / 2. * 1.15;
double b = height / 2. * 1.15;
double n = properties.getNear();
double f = properties.getFar();
gl.glOrtho(-l, l, -b, b, n, f);
}
所以你可以看到我得到了我的轴和我的宽度向量:
widthVector = (xWidth, yWidth, zWidth)
然后通过将这个宽度向量沿leftAxis和upAxis投影得到gl场景的宽度和高度。然后我将 aspectRatio 与我正在显示此场景的 canvas 的 aspectRatio 相匹配,并使用宽度和高度来计算正交平截头体的边界(使用 1.15 比例因子添加填充)。
这对除等轴测视图之外的所有视图都非常有效。以下是工作中的一些屏幕截图:
如您所见,底视图、左视图和前视图都很好。但是,等距视图被截断了(不,我在截屏时没有剪错!)。我必须将我使用的填充比例因子增加到 1.5 而不是 1.15,但我一定是在这里做错了什么。
如有任何帮助,我们将不胜感激。谢谢!
这是我的fitAllIn
简化
public void fitAllIn(float[] boundingMinMaxWorldSpace) {
Vec4 centerWorldSpace = new Vec4((boundingMinMaxWorldSpace[0] + boundingMinMaxWorldSpace[1]) / 2,
(boundingMinMaxWorldSpace[2] + boundingMinMaxWorldSpace[3]) / 2,
(boundingMinMaxWorldSpace[4] + boundingMinMaxWorldSpace[5]) / 2, 1f);
Vec3 min = new Vec3(boundingMinMaxWorldSpace[0], boundingMinMaxWorldSpace[2], boundingMinMaxWorldSpace[4]);
Vec3 max = new Vec3(boundingMinMaxWorldSpace[1], boundingMinMaxWorldSpace[3], boundingMinMaxWorldSpace[5]);
float diameter = (float) Math.sqrt(
(max.x - min.x) * (max.x - min.x)
+ (max.y - min.y) * (max.y - min.y)
+ (max.z - min.z) * (max.z - min.z));
if (getCurrView().orthographicProj) {
if (glViewer.getAspect() > 1) {
// projection * scale = y
getCurrView().scale = diameter / 2 / projectionSide;
} else {
// projection * aspect * scale = x
getCurrView().scale = diameter / 2 / (projectionSide * glViewer.getAspect());
}
getCurrView().scale = viewScale.clampScale(projectionSide, getCurrView().scale);
}
getCurrView().targetPos = new Vec3(centerWorldSpace);
glViewer.refresh();
基本上我通过了世界中的边界框 space,我计算了我的相机将瞄准的中心,我计算了最小点(minX、minY、minZ)和最大点。我得到直径,然后得到一个简单的方程来检索比例。
scale
和projectionSide
后面会用到我的正交矩阵
float x = projectionSide * glViewer.getAspect() * getCurrView().scale;
float y = projectionSide * getCurrView().scale;
float z = projectionSide;
return Jglm.orthographic(-x, x, -y, y, -z, z);
感谢 elect 的建议,这是我更新的 setFrustum 例程:
public void setFrustum(GL gl, GLU glu) {
double[] widthVec = bounds.getWidthVector();
double diameter = VecMath.magnitude(widthVec);
double canvasRatio = properties.getAspectRatio();
double scale = canvasRatio > 1 ? diameter / 2 : diameter / 2 / canvasRatio;
double x = canvasRatio * scale;
double y = scale;
double n = properties.getNear();
double f = properties.getFar();
gl.glOrtho(-x, x, -y, y, n, f);
}
完美运行。感谢 Elect!