/** * Set the camera to the specified be located at the specified view point and looking in the * specified direction. * * @param kViewPoint coordinates of the camera view point * @param kViewdirVector coordinates of the camera view direction vector. This vector must be * normalized. */ private void setView(Vector3f kViewPoint, Vector3f kViewdirVector) { // Use the view direction vector to create positive weights where more // weight is given to an axis that has less of a component in the // direction vector. Use the weights to create an average of // two desired (orthogonal axis) up vectors. Normalize this average // vector to create a combined view up vector to use. Vector3f kV = new Vector3f(kViewdirVector); kV.Set(Math.abs(kV.X), Math.abs(kV.Y), Math.abs(kV.Z)); kV.Sub(Vector3f.ONE, kV); Vector3f kViewupVector = new Vector3f(0.0f, 0.0f, 0.0f); kViewupVector.ScaleAdd(m_kViewup1.Dot(kV), m_kViewup1, kViewupVector); kViewupVector.ScaleAdd(m_kViewup2.Dot(kV), m_kViewup2, kViewupVector); kViewupVector.Normalize(); // Project the view-up vector onto the plane which is // perpendicular to the view direction vector. By getting to // this point, we know that the view-up vector and the view // direction vectors are not aligned. This projected vector is // normalized and becomes the new view-up vector. Vector3f kViewdirProjection = new Vector3f(); kViewdirProjection.Scale(kViewdirVector.Dot(kViewupVector), kViewdirVector); kViewupVector.Sub(kViewdirProjection); kViewupVector.Normalize(); Vector3f kViewleftVector = new Vector3f(); kViewleftVector.Cross(kViewupVector, kViewdirVector); m_kViewPoint.Copy(kViewPoint); m_kViewDirection.Copy(kViewdirVector); m_kViewUp.Copy(kViewupVector); }
/** * 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(); } }