2013-12-17 5 views
0

Предположим, что у меня есть путь от точки А до точки В (не обязательно должна быть прямая линия). Для удобства пользователей я хотел бы визуализировать направление, чтобы пользователи знали, куда им идти.Перемещение в OpenGL - Подходы

Поскольку я только начал изучать OpenGL, я ищу простые решения для решения этой проблемы.

Я мог легко нарисовать линию между всеми точками через GL_LINE_STRIP. Но это без какой-либо анимации. Для анимации я думал об использовании разных цветов для каждой вершины (аналогичной, но не такой), чтобы я мог интерполировать эти цвета между точками. Тогда я мог бы изменить цвет вершин, чтобы каждый вызов имел немного отличающуюся анимацию.

Является ли это хорошим подходом или вы сделаете что-то еще? Должен ли я придерживаться строк или я должен реализовать «Line-Class», сделанный из треугольников?

Насколько сложно визуализировать движущуюся стрелку вдоль пути (или, может быть, весь путь из стрелок, движущихся)?

+0

Ваш вопрос немного широк, и вы задаете вопрос, в первую очередь, вопрос, основанный на мнениях, который не очень подходит для переполнения стека. Вы должны выбрать стиль анимации, который вы хотите, а затем задать конкретные вопросы о том, как реализовать это (сначала попробовав его). – user1118321

+0

треугольники вместе с линиями выглядели бы лучше всего визуально и были бы самыми очевидными, на мой взгляд, это было бы не так уж сложно сделать, я полагаю, вы делаете это в 2D? –

+0

хорошо здание 3dimensional, но пути будут визуализированы в 2d;) – Frame91

ответ

1

Я создал следующий класс анимации:

public class PathAnimation { 
public static final int INFINITY = -1; 
private static final float epsilon = 0.1f; 

private Vector3D currentPosition; 
private int nextVector = 1; 
private Vector3D nextPathElement; 
private List<Vector3D> pointsOnPath; 

private long currentTime; 
private float timeToFinish; 
private float pathLength; 

private boolean isFinished = false; 
private boolean isRunnning = false; 

private int repeatCount = 1; 
private int currentRepeatCount = 0; 

public PathAnimation(List<Vector3D> pointsOnPath, float timeToFinish, 
     int repeatCount) { 
    this.pointsOnPath = pointsOnPath; 
    this.timeToFinish = timeToFinish; 
    this.repeatCount = repeatCount; 
    this.nextVector = 0; 
    this.currentPosition = pointsOnPath.get(nextVector++); 
    this.nextPathElement = pointsOnPath.get(nextVector); 
    this.currentTime = new Date().getTime(); 
    calculatePathLength(); 
} 

private void calculatePathLength() { 
    float distance = 0.0f; 
    for (int i = 0; i < pointsOnPath.size() - 1; i++) { 
     distance += Vector3D.getDistance(pointsOnPath.get(i), 
       pointsOnPath.get(i + 1)); 
    } 
    this.pathLength = distance; 
} 

/** 
* @return float[](yaw,pitch,x,y,z) 
*/ 
public float[] animate() { 
    if (isRunnning) { 
     long timeNow = new Date().getTime(); 
     long delta = timeNow - currentTime; 
     currentTime = timeNow; 

     if (!isFinished) { 
      double dX = nextPathElement.getX() - currentPosition.getX(); 
      double dY = nextPathElement.getY() - currentPosition.getY(); 
      double dZ = nextPathElement.getZ() - currentPosition.getZ(); 

      float yaw = (float) Math.atan2(dY, dX); 
      float pitch = (float) (Math.atan2(Math.sqrt(dX * dX + dY * dY), 
        dZ) + Math.PI); 

      float pathToWalk = pathLength/timeToFinish * delta; 
      float distanceToNextPathElement = Vector3D.getDistance(
        currentPosition, nextPathElement); 
      while (pathToWalk > distanceToNextPathElement - epsilon) { 
       currentPosition = nextPathElement; 
       pathToWalk -= distanceToNextPathElement; 
       nextVector++; 
       if (nextVector >= pointsOnPath.size()) { 
        isFinished(); 
        return null; 
       } 
       nextPathElement = pointsOnPath.get(nextVector); 
       distanceToNextPathElement = Vector3D.getDistance(
         currentPosition, nextPathElement); 
      } 

      float percentageToWalk = pathToWalk/distanceToNextPathElement; 
      float newX = (nextPathElement.getX() - currentPosition.getX()) 
        * percentageToWalk; 
      float newY = (nextPathElement.getY() - currentPosition.getY()) 
        * percentageToWalk; 
      float newZ = (nextPathElement.getZ() - currentPosition.getZ()) 
        * percentageToWalk; 
      Vector3D difference = new Vector3D(newX, newY, newZ); 
      currentPosition = new Vector3D(currentPosition); 
      currentPosition.add(difference); 
      pathToWalk = 0; 

      return new float[] { (float) Math.toDegrees(yaw), 
        (float) Math.toDegrees(pitch), currentPosition.getX(), 
        currentPosition.getY(), currentPosition.getZ() }; 
     } 
    } 
    return null; 
} 

private void isFinished() { 
    currentRepeatCount++; 
    if (repeatCount == INFINITY || currentRepeatCount < repeatCount) { 
     reset(); 
    } else { 
     isFinished = true; 
    } 
} 

public void start() { 
    this.currentTime = new Date().getTime(); 
    isRunnning = true; 
} 

public void pause() { 
    isRunnning = false; 
} 

public void reset() { 
    this.isFinished = false; 
    this.nextVector = 0; 
    this.currentPosition = pointsOnPath.get(nextVector++); 
    this.nextPathElement = pointsOnPath.get(nextVector); 
    this.currentTime = new Date().getTime(); 
} 
} 

Что вы думаете? Теперь я могу инициализировать класс и называть его в классе стрелок, чтобы получить самый новый перевод и поворот :)

Редактировать: Проблема в том, что у меня есть только один элемент Path-Element в одно и то же время ... Если я хочу чтобы иметь более одного элемента, эта структура, вероятно, слишком тяжелая ... Или кто-то знает, как изменить этот класс, чтобы иметь анимацию, например, смещение (например, значение расстояния). ?

+0

Бадди, вы не просто выполняете всю свою работу. Это не значит, что Stack Overflow должен работать. – Vallentin

+0

Я ответил на свой вопрос ... – Frame91

+0

Ой, извините, не видел этого. Просто проснулся, так что я немного ушел. – Vallentin

1

Рисование линии или дорожки, выполненной из сегментов линии, тривиально и то, что вы предложили, будет работать. Однако вместо (меняющихся) цветов я бы использовал 1D текстуру, содержащую некоторый узор, а затем плавно продвигаю координаты текстуры вдоль линии, чтобы создать впечатление движения.

Когда дело доходит до рисования стрелок, вы должны указывать стрелки в направлении пути. Направление линии, изогнутой или прямой, задается частными производными (= градиентом) описывающей ее параметрической функции. Скажите, что ваша линия описана функцией

l(t) = a + (b-a)·t 

, которая описывает прямую линию от a до b. Применение производных урожайности

∂_x,y,z/∂_t l(t) 

= ∂_x,y,z/∂_t (a + (b-a)·t) 

= ∂_x,y,z/∂_t a + ∂/∂_x,y,z (b-a)·t 

= ∂_x,y,z/∂_t v · t ; where v = b - a 

= v_x,y,z  

Для криволинейной траектории это его получить немного Tricker, но вы можете использовать численное приближение. После того, как у вас есть направление, вы можете использовать это, чтобы построить свой локальный фрейм, в котором нужно нарисовать стрелку. В https://github.com/datenwolf/codesamples/blob/master/samples/OpenGL/frustum/frustum.c вы можете найти функцию draw_arrow, которая рисует выровненную по экрану стрелку из точек a в b в пространстве, преобразованную в пространство просмотров текущей моделью (да, это фиксированная функция).

Смежные вопросы