LWJGL Камера вращается вокруг точки?
* ЭТО БЫЛО РЕШЕНО Ну, проблема в том, что в LWJGL я сделал базовую FPS-камеру, используя glTranslatef и glRotatef. Сначала он работает так, как должен, но когда я двигаю камеру, она начинает вращаться вокруг оси, с которой изначально была камера! Вот мой код (без импорта и тому подобное):
public class Main {
public static float camera_x,camera_y,camera_z,camera_rot;
public static ArrayList<Block>blocks = new ArrayList<Block>();
public Main(){
try{
Display.setDisplayMode(new DisplayMode(800,600));
Display.setTitle("Voxel");
Display.create();
}catch(LWJGLException e){
e.printStackTrace();
}
//Init
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective((float)45,800f/600f,0.1f,1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
generateWorld();
glTranslatef(0,15,0);
float dt,time,lastTime = 0;
Mouse.setGrabbed(true);
while(!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
time = Sys.getTime();
dt = (time - lastTime)/1000.0f;
lastTime = time;
render();
tick();
Display.update();
Display.sync(60);
}
Display.destroy();
System.exit(0);
}
public void tick(){
camera_x = 0;
camera_y = 0;
camera_z = 0;
camera_rot = 0;
if(Keyboard.isKeyDown(Keyboard.KEY_W)){
camera_z = +1;
}
else if(Keyboard.isKeyDown(Keyboard.KEY_S)){
camera_z = -1;
}
if(Keyboard.isKeyDown(Keyboard.KEY_A)){
camera_x = +1;
}
else if(Keyboard.isKeyDown(Keyboard.KEY_D)){
camera_x = -1;
}
if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)){
camera_y = -1;
}
else if(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)){
camera_y = +1;
}
while(Keyboard.next()){
if(Keyboard.isKeyDown(Keyboard.KEY_R)){
generateWorld();
}
}
//Updating all of the blocks
for(int i=0; i < blocks.size(); i++){
blocks.get(i).tick();
}
camera_rot += Mouse.getDX();
}
public void render(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRotatef(camera_rot, 0f, 1f, 0f);
glTranslatef(camera_x, camera_y, camera_z);
for(int i=0; i < blocks.size(); i++){
blocks.get(i).render();
}
}
public static void main(String[] arguments){
new Main();
}
public void generateWorld(){
blocks.clear();
int heightlevel = 0;
Random r = new Random();
for(int i=0; i < 50; i++){
for(int j=0; j < 50; j++){
if(r.nextBoolean() == false){
heightlevel -= 4;
}
else{
heightlevel += 4;
}
blocks.add(new Block((i*4)-64,-8+ heightlevel,(j*4)-64,4,4,4));
float y = -8+heightlevel;
for(int k = 0; k < 10; k++){
blocks.add(new Block((i*4)-64,y - (k*4),(j*4)-64,4,4,4));
}
}
}
}
}
Также есть класс Block:
public class Block {
public float x,y,z,width,height,depth,shade;
public Random rand;
public Block(float xx,float yy,float zz,float ww,float hh,float dd){
x = xx;
y = yy;
z = zz;
width = ww;
height = hh;
depth = dd;
rand = new Random();
shade = (rand.nextFloat()+0.2f);
}
public void tick(){
}
public void render(){
glBegin(GL_QUADS);
glColor3f(0,shade,0);
//Front
glTexCoord2f(0,0);
glVertex3f(x,y,z);
glTexCoord2f(1,0);
glVertex3f(x+width,y,z);
glTexCoord2f(1,1);
glVertex3f(x+width,y+height,z);
glTexCoord2f(0,1);
glVertex3f(x,y+height,z);
//Back
glVertex3f(x,y,z+depth);
glVertex3f(x+width,y,z+depth);
glVertex3f(x+width,y+height,z+depth);
glVertex3f(x,y+height,z+depth);
//Left
glVertex3f(x,y,z);
glVertex3f(x,y,z+depth);
glVertex3f(x,y+height,z+depth);
glVertex3f(x,y+height,z);
//Right
glVertex3f(x+width,y,z);
glVertex3f(x+width,y,z+depth);
glVertex3f(x+width,y+height,z+depth);
glVertex3f(x+width,y+height,z);
//Top
glVertex3f(x,y,z);
glVertex3f(x+width,y,z);
glVertex3f(x+width,y,z+depth);
glVertex3f(x,y,z+depth);
//Bottom
glVertex3f(x,y+height,z);
glVertex3f(x+width,y+height,z);
glVertex3f(x+width,y+height,z+depth);
glVertex3f(x,y+height,z+depth);
glEnd();
}
}
2 ответа
Это потому, что вам нужно перевернуть звонки. Так это как:
glRotatef(camera_rot, 0f, 1f, 0f);
glTranslatef(camera_x, camera_y, camera_z);
и не так
glTranslatef(camera_x, camera_y, camera_z);
glRotatef(camera_rot, 0f, 1f, 0f);
Причина в том, что вы поворачиваете камеру, а затем переводите камеру. Это дает эффект, который вы видите, так как он вращается с использованием camera_rot
и затем он переводит в соответствии с camera_x, camera_y, camera_z
,
редактировать
Вам нужно изменить это:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRotatef(camera_rot, 0f, 1f, 0f);
glTranslatef(camera_x, camera_y, camera_z);
В это:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(camera_rot, 0f, 1f, 0f);
glTranslatef(camera_x, camera_y, camera_z);
Поэтому, когда вы это сделаете, вы поймете, что положение и вращение ваших камер будут зависать. Это потому, что каждый раз, когда вы звоните tick()
Ты звонишь:
camera_x = 0;
camera_y = 0;
camera_z = 0;
camera_rot = 0;
То, что это делает, сбрасывает положение и вращение, и именно поэтому камера "застревает".
Поэтому вам нужно изменить это так, чтобы значения увеличивались или уменьшались, а не просто оставались на -1, 0 и 1.
Может быть некоторый беспорядок с координатами, так как они также вращаются. Вы можете попробовать повернуть вектор (camera_x, camera_y, camera_z), но я бы порекомендовал вам использовать GLU.gluLookAt(). Он делает всю работу за вас, вам просто нужно сделать простую векторную математику, чтобы оценить точку зрения, опорную точку и вектор вверх по вашим значениям camera_x, camera_y, camera_z и camera_rot.
Вы можете прочитать спецификацию gluLookAt и узнать о Up vector.
UPD: Также я попытался немного возиться с glTranslate* и glRotate*, вот что я получил:
while (!Display.isCloseRequested()) {
//clear:
GL11.glLoadIdentity();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glRotatef(90.0f, -1.0f, 0.0f, 0.0f); //with z axis looking up we get Oxy plane being wrong oriented, it is a little odd for me and I prefer to set z axis vertical ))
//rotate and translate:
GL11.glRotatef(camera_rot, 0.0f, 0.0f, 1.0f); //rotate
GL11.glTranslatef(camera_x, camera_y, camera_z); //translate
/* draw here */
//process input:
float move = 0.0f;
float strife = 0.0f;
if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
strife -= 0.1f;
}
if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
strife += 0.1f;
}
if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
move += 0.1f;
}
if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
move -= 0.1f;
}
//we move relatively to the direction we are looking
camera_x -= strife * Math.cos(Math.toRadians(rotp)) + move * Math.sin(Math.toRadians(rotp));
camera_y -= - strife * Math.sin(Math.toRadians(rotp)) + move * Math.cos(Math.toRadians(rotp));
camera_rot += Mouse.getDX();
//Display stuff
Display.update();
Display.sync(60);
}
Этот код хорошо работает для меня.