因此,我的计算机已有7年的历史,我的硬件上装有OpenGL 3.30(使用ATI Radeon HD 4300/4500),我真的很想使用OpenGL制作自己的3D游戏引擎。长话短说,着色器对我来说很坏(详细信息在底部)。因此,我说要拧螺丝,我要制作自己的3D渲染器。我完成了渲染,但是需要旋转方面的帮助。
好吧,事实是我开始制造自己的引擎,因为我的笔记本电脑太旧了,无法按照本教程进行操作,所以我开始使用具有很酷的视差系统的2D引擎工作,然后它就打了我。我之所以说我的计算机已经过时,是因为那是我真正开始考虑从另一个层面进行旋转的时候。
这是问题开始的地方:
x = (float) ((x * Math.cos(Math.toRadians(main.cameraRot)) - z * Math.sin(Math.toRadians(main.cameraRot))));
z = (float) (z * Math.sin(Math.toRadians(main.cameraRot)) - x * Math.cos(Math.toRadians(main.cameraRot)));
我想我看到了问题,我想我需要将zsin(cameraRot)添加到xcos(cameraRot)
我什至已经弄清楚了正弦和余弦函数是如何工作的,主要是因为我当时还在研究水的效果,我想:“我应该能够使用罪过(并且只有罪过)旋转。 ”我错了(很明显)。我还使用了图形计算器(1999年开始的TI-83 +,而不是2011年)来绘制这些函数的图形(它们有些不同,是的,我使用了可以同时输入X和Y值的图形模式)。我现在正在尝试一些东西,我想我看到了主要问题。 Z旋转使用X旋转,但是X旋转使用Z坐标(如果比较复杂,我将其分解:我们需要使用原始X值来计算Z值的旋转,但是我们改用更改为旋转的X后的X值,将会有很大的不同。)
它根本不起作用。 cameraRot(旋转)不断增加,但是没有效果。 这是渲染代码:
g.drawRect((int) (x / (z - main.camZ) - 256 / (z - main.camZ) / 2),(int) (0 - 256 / (z - main.camZ) / 2),(int) (256 / (z - main.camZ)),(int) (256 / (z - main.camZ)));
但是它搞砸了渲染。是的,我知道我正在绘制一个正方形,但是我在笔记本电脑上制作的上一个更加完整,但是使用相同的渲染算法并在尝试添加旋转数时中断了,每个对象看上去都为0, 0.1。
有关如何解决此问题的任何建议? 是来自渲染还是方程式? (我将为您省去麻烦,并告诉您其旋转方程。
仅需注意一点,我不小心做了该渲染算法。
我尝试对VertexShaders使用制服,但它们仅与Fragment Shaders一起使用。我遵循的教程使用的是“ #version 330”(和我一样),但是它们使用的是OpenGL版本4.3(并且使用的是Java),而我使用的版本是3.30(使用的是Java)。
答案 0 :(得分:0)
好吧,所以我只是愚蠢。
x = (float) ((x * Math.cos(Math.toRadians(main.cameraRot)) - z * Math.sin(Math.toRadians(main.cameraRot))));
z = (float) (z * Math.sin(Math.toRadians(main.cameraRot)) - x * Math.cos(Math.toRadians(main.cameraRot)));
我愚蠢的原因是因为你会做的是(简化,使用 double
s):
double tempX = x;
x = tempX * Math.cos(theta) - z * Math.sin(theta);
z = tempX * Math.sin(theta) + z * Math.cos(theta);
两年后,这个等式我已经写了很多次了,它真的会永远困扰着我。即使在我死后。
现在来看看我说的:
<块引用>我想我看到了问题,我想我需要将 zsin(cameraRot) 添加到 xcos(cameraRot)
甚至不接近。整个问题我对 z
方程的 x
和 z
的顺序是错误的,并且在执行之前我没有将 x
存储在临时变量中操作。如果不这样做,它就不会在 z
轴上正确旋转。
我不妨为这个实际上很容易弄清楚的晦涩问题添加一些注释。如果您有 200
对象,每个对象都调用 Math.sin()
和 Math.cos()
两次,这是非常低效的。您至少可以做的是将结果 Math.sin()
和 Math.cos()
值存储在它们自己的变量中,但这只是皮毛。
不是让每个对象单独计算正弦和余弦,而是创建一个 Camera 类来保存相机的所有位置和旋转数据,以及屏幕尺寸。这是为了使大小为 1.0 x 1.0
的矩形与屏幕成比例。在非方形纵横比(例如 16:9、4:3)中,您可以看到一些拉伸正在进行。解决此问题的简单方法是为 screenWidth
和 screenHeight
传递屏幕的宽度或高度。更难的方法是让您使用任何 FoV,但那是另一天。
public class Camera {
// Position variables, X is horizontal, Y is vertical, Z is fordical (forward and backward)
private double x, y, z;
private double rot;
private double cos;
private double sin;
// Variables pertaining to the screen
private int screenWidth;
private int screenHeight;
public Camera(double x, double y, double z, double rot, int screenWidth, int screenHeight) {
setScreenDimensions(screenWidth, screenHeight);
setPosition(x, y, z);
setRotation(rot);
}
public void setScreenDimensions(int screenWidth, int screenHeight) {
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
}
public int getScreenWidth() {...}
public int getScreenHeight() {...}
public void setPosition(double x, double y, double z) {...}
public void setRotation(double rot) {
// Update the rotation variable
this.rot = rot;
// Update the trig values
cos = Math.cos(rot);
sin = Math.sin(rot);
}
// Position Getters
public double getX() {...}
public double getY() {...}
public double getZ() {...}
// Position Setters
public void setX(double x) {...}
public void setY(double y) {...}
public void setZ(double z) {...}
public double getRotation() { return rot; }
public double getCos() { return cos; }
public double getSin() { return sin; }
}
然后当您从 world-space
(3D) 转换为 screen-space
(2D) 时,您会这样做(使用 Java Swing 因为这是我在问这个问题时使用的):< /p>
// somewhere in a class, probably the base GameObject class. If it's in an util class, make it "public static", and if it's in the Camera class, it would be "public".
protected Point transform(Camera camera, double x, double y, double z) {
double transX = x - camera.getX();
double transY = y - camera.getY();
double transZ = z - camera.getZ();
double rotX = transX * camera.getCos() - transZ * camera.getSin();
double rotZ = transX * camera.getSin() + transZ * camera.getCos();
int pointX = (transX * camera.getScreenWidth() ) / transZ;
int pointY = (y * camera.getScreenHeight()) / transZ;
return new Point(pointX, pointY);
}
Bam 现在我们已经优化了渲染例程。至少,就一个理智的人而言。如果你真的很喜欢优化(就像我有时那样),你可能会做一些疯狂的事情。当您使用 C++ 并使用指针时,真正疯狂的事情就会发生,但这超出了这个 Java 问题的范围。见鬼,即使进入优化部分也有点超出问题的范围,但这是我的问题,我认为我保留按我认为合适的方式回答它的权利,只要它对任何阅读我的答案的人都有好处。
注意:我是在深夜写的,所以对于任何错误,我深表歉意,早上会修复!
旁注:反正没人会读这个:)