Вращение вокруг 3d-объекта на ощупь с использованием min3d/Rajawali framework (android)
Я работаю над алгоритмом поворота камеры вокруг трехмерного объекта с использованием платформы Min3d/Rajawali.
В моей реализации вращение вокруг оси X не работает должным образом. Я думаю, что метод setLookAt()
не работает должным образом.
Эта проблема:
Когда я поворачиваю сферу по вертикали, я не вижу ее полностью. Например, поворачивая планету Земля, я не могу полностью увидеть Антарктику, потому что алгоритм сбрасывает камеру вниз.
Можно ли реализовать вращение камеры вокруг объекта без использования метода "setLookAt"?
Я пробовал разные решения, но не смог заставить его работать правильно.
Ниже мой код:
initScene:
scene.camera().position.z = 90;
scene.camera().target = raketeOBJ.position();
onTouchEvent:
public boolean onTouchEvent(MotionEvent me) {
if (me.getAction() == MotionEvent.ACTION_DOWN) {
xpos = me.getX();
ypos = me.getY();
return true;
}
if (me.getAction() == MotionEvent.ACTION_UP) {
xpos = -1;
ypos = -1;
touchTurn = 0;
touchTurnUp = 0;
return true;
}
if (me.getAction() == MotionEvent.ACTION_MOVE) {
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;
xpos = me.getX();
ypos = me.getY();
touchTurn = xd / -200f;
touchTurnUp = yd / -200f;
return true;
}
try {
Thread.sleep(15);
} catch (Exception e) {
}
return super.onTouchEvent(me);
}
UpdateScene:
if (touchTurn != 0) {
scene.camera().position.rotateY(touchTurn);
touchTurn = 0;
}
if (touchTurnUp != 0) {
scene.camera().position.rotateX(touchTurnUp);
touchTurnUp = 0;
}
Number3d target = scene.camera.target;
Number3d cp = scene.camera.position.clone();
// move position like target is (0,0,0)
cp.x -= target.x;
cp.y -= target.y;
cp.z -= target.z;
cp.roateX(angle);
// restore offset
cp.x += target.x;
cp.y += target.y;
cp.z += target.z;
scene.camera.position.setAllFrom(cp);
3 ответа
Немного поздно, но на случай, если у кого-то возникнут проблемы, как у меня.
Раджавали предлагает камеру под названием ArcballCamera, которая делает именно то, что вы / мы пытаемся сделать.
В вашем рендерере добавьте следующее:
ArcballCamera arcball = new ArcballCamera(mContext, ((Activity)mContext).findViewById(R.id.contentView));
arcball.setTarget(mObjectGroup); //your 3D Object
arcball.setPosition(0,0,4); //optional
getCurrentScene().replaceAndSwitchCamera(getCurrentCamera(), arcball);
Теперь вы можете вращать и масштабировать объект без десятка строк кода.
setLookAt() должен вызываться onDrawFrame, если вы хотите, чтобы камера регулярно обновлялась. Но вам нужно больше заботиться о создании "RotateAroundAnimation". Смотрите здесь для получения дополнительной информации: http://www.rozengain.com/blog/2012/03/26/rajawali-tutorial-12-animation-classes/
Вам нужно сделать yourAnimation.setTransformable3D(mCamera), а затем он должен управлять вашей основной камерой. Я часто использую эту методологию, а затем вызываю "yourAnimation.start()" на ощупь или другой внешний стимул.
Это мой способ вращать 3d модель в соответствии с X и Y
в классе рендера
public boolean left, right;
public boolean up, down;
и в onDrawFrame
@Override
public void onDrawFrame(GL10 glUnused) {
super.onDrawFrame(glUnused);
// getCurrentCamera().setRotY(getCurrentCamera().getRotY() + 1);
if (left) {
getCurrentCamera().setRotX(getCurrentCamera().getRotX() - 1);
}
if (right) {
getCurrentCamera().setRotX(getCurrentCamera().getRotX() + 1);
}
if (up) {
getCurrentCamera().setRotY(getCurrentCamera().getRotY() - 1);
}
if (down) {
getCurrentCamera().setRotY(getCurrentCamera().getRotY() + 1);
}
}
и в MainActivity
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
xpos = event.getX();
ypos = event.getY();
}
if (event.getAction() == MotionEvent.ACTION_UP) {
xpos = -1;
ypos = -1;
mRender.left = false;
mRender.right = false;
mRender.up = false;
mRender.down = false;
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
xd = event.getX() - xpos;
yd = event.getY() - ypos;
xpos = event.getX();
ypos = event.getY();
if (xd < 0) {
mRender.up = true;
} else {
mRender.down = true;
}
if (yd < 0) {
mRender.left = true;
} else {
mRender.right = true;
}
}
return super.onTouchEvent(event);
}
таким образом, я могу вращать свою модель:)