예제 #1
0
  /**
   * Create the array of branch choices and set the mode which forces the user to select from among
   * the branch choices.
   *
   * @param iBranchParent int Index which identifies the parent branch.
   * @param iBranchPoint int Index which identifies the point along the branch path where the
   *     branching occurs for the choices.
   */
  private void setupBranchChoices(int iBranchParent, int iBranchPoint) {

    // Get list of possible sub-branches for the parent.
    int[] aiBranchChildIndex = m_kFlyPathGraph.getBranchPointBranches(iBranchParent, iBranchPoint);

    // Get the information for the parent branch.
    BranchState kBranchStateParent = m_akBranchState[iBranchParent];

    // Build the list of possible branches.
    // First branch choice is the parent branch, current direction
    // Last branch choice is the parent branch, reverse direction
    // Reset all of the sub-branches to their start state.
    m_akBranchChoice = new BranchState[2 + aiBranchChildIndex.length];
    m_akBranchChoice[0] = kBranchStateParent.createCopy();
    m_akBranchChoice[m_akBranchChoice.length - 1] = kBranchStateParent.createReverseCopy();

    for (int i = 0; i < aiBranchChildIndex.length; i++) {
      int iBranchChild = aiBranchChildIndex[i];

      m_akBranchState[iBranchChild].start();
      m_akBranchChoice[i + 1] = m_akBranchState[iBranchChild].createCopy();
    }

    m_bChooseBranch = true;
    m_iBranchChoiceIndex = -1;
  }
예제 #2
0
    /**
     * Create a copy of this instance which has the same information except that the state of the
     * moving forward is inverted.
     *
     * @return BranchState New instance which is a copy of this instance except that the moving
     *     forward flag is inverted.
     */
    public BranchState createReverseCopy() {
      BranchState kCopy = createCopy();

      kCopy.m_bMoveForward = !kCopy.m_bMoveForward;

      return kCopy;
    }
예제 #3
0
  /**
   * Update the camera position along the path based on the specified distance from the beginning.
   *
   * @param fNormalizedDist normalized distance from the beginning of the path for the location of
   *     the camera for viewing
   */
  private void setPathDist(float fNormalizedDist) {

    // Make sure the distance is in the [0,1] range.
    fNormalizedDist = clampNormalizedPathDistance(fNormalizedDist);

    // Compute the actual distance along the curve.
    float fDist = fNormalizedDist * getPathLength();

    // Save the current distance.
    m_kBranchState.m_fNormalizedPathDist = fNormalizedDist;

    // Get the path point (position and tangent) based on distance.
    // It needs to be double precision for the view to use.
    Curve3f kCurve = m_kBranchState.m_kBranchCurve;
    float fTime = kCurve.GetTime(fDist, 100, 1e-02f);
    Vector3f kViewPoint = kCurve.GetPosition(fTime);

    // If the gaze distance is zero, then use the tangent vector
    // to the curve.
    // If the path is being followed in the reverse direction,
    // then the direction of looking down the path needs to
    // be reversed (negated).
    Vector3f kLookatVector = new Vector3f();
    boolean bLookatVectorUseTangent = true;

    if (m_fGazeDist > 0.0f) {
      float fTimeGazeDist = m_kBranchState.getForwardNormalizedTime(m_fGazeDist);

      if (fTime != fTimeGazeDist) {
        Vector3f kVec = kCurve.GetPosition(fTimeGazeDist);
        kLookatVector.Sub(kVec, kViewPoint);
        kLookatVector.Normalize();
        bLookatVectorUseTangent = false;
      }
    }

    if (bLookatVectorUseTangent) {
      kLookatVector = kCurve.GetTangent(fTime);

      if (!m_kBranchState.m_bMoveForward) {
        kLookatVector.Neg();
      }
    }

    // Update the view given the view position, view direction,
    // and a hint for the view up vector.
    setView(kViewPoint, kLookatVector);

    // Notify listener that we are updated.
    notifyCallback(EVENT_CHANGE_POSITION);
  }
예제 #4
0
  /**
   * Loop through all of the possible branch choices and select the one that is the closest to the
   * current view direction vector. Take a vector from the current view point to a point along each
   * choice branch. Compute the dot-product between the current view direction vector and each of
   * these branch direction vectors and take the one with the largest positive value, i.e., most in
   * alignment.
   */
  private void setClosestChoiceBranch() {
    // Retrieve the current combined viewing direction vector.
    // Note that the sign of the view direction vector is negated
    // for the reasons described in the setView method.
    // Matrix4f kMatrixView = parentScene.getWVMatrix();
    // Vector3f kViewDirection = new Vector3f(-kMatrixView.M02, -kMatrixView.M12, -kMatrixView.M22);
    Vector3f kViewDirection = new Vector3f(parentScene.getCameraDirection());

    // Record the current view position and combined view orientation.
    // Vector3f kP0 = new Vector3f(kMatrixView.M03, kMatrixView.M13, kMatrixView.M23);
    Vector3f kP0 = new Vector3f(getViewPoint());

    // Check point down path which is maximum of the step distance
    // and the gaze distance.
    float fPointDist = Math.max(m_fGazeDist, m_fPathStep);
    float fBestAlign = -1.0f;
    int iBestAlignBranchChoiceIndex = -1;

    for (int iBranch = 0; iBranch < m_akBranchChoice.length; iBranch++) {

      // Get vector from current view point to point down branch path.
      BranchState kBranch = m_akBranchChoice[iBranch];
      Vector3f kV = new Vector3f();

      kV.Sub(kBranch.getForwardNormalizedPosition(fPointDist), kP0);
      kV.Normalize();

      // Only accept the best aligned branches we can supposedly see.
      float fAlign = kV.Dot(kViewDirection);

      if ((fAlign > 0.0f) && (fAlign > fBestAlign)) {
        fBestAlign = fAlign;
        iBestAlignBranchChoiceIndex = iBranch;
      }
    }

    // Select the "nearest" branch.
    if (iBestAlignBranchChoiceIndex >= 0) {

      // Select the new branch.
      m_iBranchChoiceIndex = iBestAlignBranchChoiceIndex;
      m_bChooseBranch = false;
      setBranch(m_akBranchChoice[m_iBranchChoiceIndex]);
    } else {
      beep();
    }
  }
예제 #5
0
  /**
   * Set the annotation point along the path.
   *
   * @param iItem int
   */
  private void setCurvePathAnnotateItem(int iItem) {

    // Select the curve and the position along the curve.
    // First set the sign of the path step to reflect
    // whether the movement down the path was forward or backward
    // when the annotation point was captured.
    FlyPathAnnotateList_WM.Item kItem = m_kAnnotateList.getItem(iItem);

    m_kBranchState.m_bMoveForward = kItem.isPathMoveForward();
    setBranch(kItem.getBranchIndex());

    m_kViewPoint.Copy(kItem.getCameraLocation());
    m_kViewDirection.Copy(kItem.getCameraDirection());
    m_kViewUp.Copy(kItem.getCameraUp());

    notifyCallback(EVENT_CHANGE_POSITION);
  }
예제 #6
0
  /**
   * Take the specified number of steps along the current path using the current path step size. If
   * the number of steps is negative, then the steps are taken in reverse.
   *
   * @param iNumSteps int Number of steps to take along the current path.
   */
  private void doPathStep(int iNumSteps) {

    // If we make a step and there were branch choices defined,
    // then replace the current state for the branch with the
    // variation selected.
    boolean bFirstSelectedBranchStep = false;

    if (null != m_akBranchChoice) {
      m_akBranchState[m_kBranchState.m_iBranchIndex] = m_kBranchState;
      m_akBranchChoice = null;
      notifyCallback(EVENT_CHANGE_BRANCH);
      bFirstSelectedBranchStep = true;
    }

    // Note that iNumSteps may be negative!
    float fNormalizedPathStep = iNumSteps * getPathStep() / getPathLength();

    // Reverse direction if moving backward.
    if (!m_kBranchState.m_bMoveForward) {
      fNormalizedPathStep = -fNormalizedPathStep;
    }

    // Compute the new normalized path distance.
    float fNewNormalizedPathDistance = getNormalizedPathDistance() + fNormalizedPathStep;

    // Note which branch we are currently on before we possibly change it.
    int iBranch = getBranchIndex();

    // Determine which segment of the branch path, in relation to the
    // branch points, that we are currently in and that we are
    // stepping into.
    int iPathSegment = m_kBranchState.getBranchPointSegment(getNormalizedPathDistance());
    int iNewPathSegment = m_kBranchState.getBranchPointSegment(fNewNormalizedPathDistance);

    // If the segments are different, then we will step into the branch.
    // The subbranch information is indexed by the minimum
    // of the two indexes.  Don't check if this is the first step
    // being taken after selecting a branch at a branch point.
    if (((Math.abs(iPathSegment - iNewPathSegment) >= 1) && !bFirstSelectedBranchStep)
        || ((Math.abs(iPathSegment - iNewPathSegment) > 1) && bFirstSelectedBranchStep)) {
      beep();

      // Access the branch point by its segment.
      int iSegment = Math.min(iPathSegment, iNewPathSegment);

      // Clamp the path distance to this branch point.
      fNewNormalizedPathDistance = m_kBranchState.m_afBranchPoint[iSegment];
      m_kBranchState.updateDistUnvisited(fNewNormalizedPathDistance);
      setPathDist(fNewNormalizedPathDistance);

      // Build the list of possible branches.
      setupBranchChoices(iBranch, iSegment);
    } // Check for reaching the beginning of the branch in which

    // there is a parent.  Then we will step back onto the parent.
    // Don't check if this is the first step being taken after
    // selecting a branch at a branch point.
    else if ((fNewNormalizedPathDistance < 0.0f)
        && (-1 != m_kBranchState.m_iParentBranchIndex)
        && !bFirstSelectedBranchStep) {
      beep();

      // Clamp the path distance to this branch point.
      fNewNormalizedPathDistance = 0.0f;
      m_kBranchState.updateDistUnvisited(fNewNormalizedPathDistance);
      setPathDist(fNewNormalizedPathDistance);

      // Access the branch point by its segment.
      int iBranchParent = m_kBranchState.m_iParentBranchIndex;
      BranchState kBranchStateParent = m_akBranchState[iBranchParent];
      int iSegment = 0;

      while (iSegment < kBranchStateParent.m_afBranchPoint.length) {

        if (m_kBranchState.m_fParentBranchPoint == kBranchStateParent.m_afBranchPoint[iSegment]) {
          break;
        }

        ++iSegment;
      }

      // Build the list of possible branches.
      setupBranchChoices(iBranchParent, iSegment);
    } // Remain on the same branch.
    else {

      // Make sure the distance is in the [0,1] range.
      fNewNormalizedPathDistance = clampNormalizedPathDistance(fNewNormalizedPathDistance);

      m_kBranchState.updateDistUnvisited(fNewNormalizedPathDistance);
      setPathDist(fNewNormalizedPathDistance);
    }
  }
예제 #7
0
  /**
   * Call from the JPanelFlythruMove.
   *
   * @param command move command.
   */
  public void move(String command) {

    if (command.equals("lookup")) {
      // pitch - look up
      Vector3f kRight = new Vector3f();
      kRight.UnitCross(m_kViewDirection, m_kViewUp);
      Matrix3f kRotate = new Matrix3f();
      kRotate.FromAxisAngle(kRight, (float) Math.toRadians(1));
      kRotate.Mult(m_kViewDirection, m_kViewDirection);
      kRotate.Mult(m_kViewUp, m_kViewUp);
      // Notify listener that we are updated.
      notifyCallback(EVENT_CHANGE_POSITION);
    } else if (command.equals("lookdown")) {
      // pitch - look down
      Vector3f kRight = new Vector3f();
      kRight.UnitCross(m_kViewDirection, m_kViewUp);
      Matrix3f kRotate = new Matrix3f();
      kRotate.FromAxisAngle(kRight, (float) Math.toRadians(-1));
      kRotate.Mult(m_kViewDirection, m_kViewDirection);
      kRotate.Mult(m_kViewUp, m_kViewUp);
      // Notify listener that we are updated.
      notifyCallback(EVENT_CHANGE_POSITION);
    } else if (command.equals("lookleft")) {
      // yaw - look left
      Matrix3f kRotate = new Matrix3f();
      kRotate.FromAxisAngle(m_kViewUp, (float) Math.toRadians(1));
      kRotate.Mult(m_kViewDirection, m_kViewDirection);
      // Notify listener that we are updated.
      notifyCallback(EVENT_CHANGE_POSITION);
    } else if (command.equals("lookright")) {
      // case KeyEvent.VK_RIGHT:
      // yaw - look right
      Matrix3f kRotate = new Matrix3f();
      kRotate.FromAxisAngle(m_kViewUp, (float) Math.toRadians(-1));
      kRotate.Mult(m_kViewDirection, m_kViewDirection);
      // Notify listener that we are updated.
      notifyCallback(EVENT_CHANGE_POSITION);
    } else if (command.equals("counterclockwise")) {
      // case KeyEvent.VK_F3:
      // roll - counterclockwise
      Matrix3f kRotate = new Matrix3f();
      kRotate.FromAxisAngle(m_kViewDirection, (float) Math.toRadians(-1));
      kRotate.Mult(m_kViewUp, m_kViewUp);
      // Notify listener that we are updated.
      notifyCallback(EVENT_CHANGE_POSITION);
    } else if (command.equals("clockwise")) {
      // roll - clockwise
      Matrix3f kRotate = new Matrix3f();
      kRotate.FromAxisAngle(m_kViewDirection, (float) Math.toRadians(1));
      kRotate.Mult(m_kViewUp, m_kViewUp);
      // Notify listener that we are updated.
      notifyCallback(EVENT_CHANGE_POSITION);
    } else if (command.equals("escape")) {

      // VK_ESCAPE
      setIdentityViewOrientation();
    } else if (command.equals("home")) {

      // case KeyEvent.VK_HOME:
      // reset position to the beginning of the path
      if (!m_bChooseBranch && (null == m_akBranchChoice)) {
        setPathDist(0.0f);
      } else {
        beep();
      }
    } else if (command.equals("end")) {

      // case KeyEvent.VK_END:
      // reset position to the end of the path
      if (!m_bChooseBranch && (null == m_akBranchChoice)) {
        setPathDist(1.0f);
      } else {
        beep();
      }
    } else if (command.equals("forward")) {

      // case KeyEvent.VK_UP:
      // move forward along the path
      if (!m_bChooseBranch) {
        doPathStep(1);
      } else {
        beep();
      }
    } else if (command.equals("backward")) {

      // case KeyEvent.VK_DOWN:
      // move backward along the path
      if (!m_bChooseBranch) {
        doPathStep(-1);
      } else {
        beep();
      }
    } else if (command.equals("reverse")) {

      // case KeyEvent.VK_R:
      // follow path in reverse heading
      m_kBranchState.m_bMoveForward = !m_kBranchState.m_bMoveForward;
      setPathDist(m_kBranchState.m_fNormalizedPathDist);

    } else if (command.equals("prevAnnotatePt")) {

      // case KeyEvent.VK_F5:
      // go to previous annotate point
      if (!m_bChooseBranch && (m_kAnnotateList.getNumItems() > 0)) {

        if (--m_iAnnotateListItemSelected < 0) {
          m_iAnnotateListItemSelected = m_kAnnotateList.getNumItems() - 1;
        }

        setCurvePathAnnotateItem(m_iAnnotateListItemSelected);
      } else {
        beep();
      }
    } else if (command.equals("nextAnnotatePt")) {

      // case KeyEvent.VK_F6:
      // go to next annotate point
      if (!m_bChooseBranch && (m_kAnnotateList.getNumItems() > 0)) {

        if (++m_iAnnotateListItemSelected >= m_kAnnotateList.getNumItems()) {
          m_iAnnotateListItemSelected = 0;
        }

        setCurvePathAnnotateItem(m_iAnnotateListItemSelected);
      } else {
        beep();
      }
    } else if (command.equals("nextBranch")) {

      // case KeyEvent.VK_SPACE:
      // select next branch choice
      if (null != m_akBranchChoice) {
        setClosestChoiceBranch();
      } else {
        beep();
      }
    } else if (command.equals("stepDistanceIncrease")) {
      m_fPathStep += 0.1f;
      setPathDist(m_kBranchState.m_fNormalizedPathDist);
    } else if (command.equals("stepDistanceDecrease")) {
      m_fPathStep -= 0.1f;

      if (m_fPathStep < 0.1f) {
        m_fPathStep = 0.1f;
        beep();
      }

      setPathDist(m_kBranchState.m_fNormalizedPathDist);
    } else if (command.equals("gazeDistanceDecrease")) {
      m_fGazeDist -= 1.0f;

      if (m_fGazeDist < 0.0f) {
        m_fGazeDist = 0.0f;
        beep();
      }

      setPathDist(m_kBranchState.m_fNormalizedPathDist);
    } else if (command.equals("gazeDistanceIncrease")) {
      m_fGazeDist += 1.0f;
      setPathDist(m_kBranchState.m_fNormalizedPathDist);
    }
  }
예제 #8
0
  /**
   * Handle the key pressed event from the text field.
   *
   * @param event key event to handle
   */
  @Override
  public void keyPressed(KeyEvent event) {
    if (KeyEvent.KEY_PRESSED == event.getID()) {
      int iKeyCode = event.getKeyCode();
      char iKeyChar = event.getKeyChar();

      switch (iKeyCode) {
        case KeyEvent.VK_ESCAPE:
          setIdentityViewOrientation();
          break;

        case KeyEvent.VK_HOME:

          // reset position to the beginning of the path
          if (!m_bChooseBranch && (null == m_akBranchChoice)) {
            setPathDist(0.0f);
          } else {
            beep();
          }

          break;

        case KeyEvent.VK_END:

          // reset position to the end of the path
          if (!m_bChooseBranch && (null == m_akBranchChoice)) {
            setPathDist(1.0f);
          } else {
            beep();
          }

          break;

        case KeyEvent.VK_UP:

          // move forward along the path
          if (!m_bChooseBranch) {
            doPathStep(1);
          } else {
            beep();
          }

          break;

        case KeyEvent.VK_DOWN:

          // move backward along the path
          if (!m_bChooseBranch) {
            doPathStep(-1);
          } else {
            beep();
          }

          break;

        case KeyEvent.VK_R:

          // follow path in reverse heading
          m_kBranchState.m_bMoveForward = !m_kBranchState.m_bMoveForward;
          setPathDist(m_kBranchState.m_fNormalizedPathDist);
          break;

        case KeyEvent.VK_F5:

          // go to previous annotate point
          if (!m_bChooseBranch && (m_kAnnotateList.getNumItems() > 0)) {

            if (--m_iAnnotateListItemSelected < 0) {
              m_iAnnotateListItemSelected = m_kAnnotateList.getNumItems() - 1;
            }

            setCurvePathAnnotateItem(m_iAnnotateListItemSelected);
          } else {
            beep();
          }

          break;

        case KeyEvent.VK_F6:

          // go to next annotate point
          if (!m_bChooseBranch && (m_kAnnotateList.getNumItems() > 0)) {

            if (++m_iAnnotateListItemSelected >= m_kAnnotateList.getNumItems()) {
              m_iAnnotateListItemSelected = 0;
            }

            setCurvePathAnnotateItem(m_iAnnotateListItemSelected);
          } else {
            beep();
          }

          break;

        case KeyEvent.VK_SPACE:

          // select next branch choice
          if (null != m_akBranchChoice) {
            setClosestChoiceBranch();
          } else {
            beep();
          }

          break;

        case KeyEvent.VK_S:

          // change the distance of a single step
          if ('s' == iKeyChar) {
            m_fPathStep -= 0.1f;

            if (m_fPathStep < 0.1f) {
              m_fPathStep = 0.1f;
              beep();
            }
          } else {
            m_fPathStep += 0.1f;
          }

          setPathDist(m_kBranchState.m_fNormalizedPathDist);
          break;

        case KeyEvent.VK_G:

          // change the gaze distance
          if ('g' == iKeyChar) {
            m_fGazeDist -= 1.0f;

            if (m_fGazeDist < 0.0f) {
              m_fGazeDist = 0.0f;
              beep();
            }
          } else {
            m_fGazeDist += 1.0f;
          }

          setPathDist(m_kBranchState.m_fNormalizedPathDist);
          break;
      }
    }
  }
예제 #9
0
 /**
  * Get the current state of traversing.
  *
  * @return BranchState
  */
 public BranchState getBranchState() {
   return m_kBranchState.createCopy();
 }