void PPC::positionRelativeToPoint( const V3 & P, const V3 & vd, const V3 & up, float distance) { // assumes: up and vd are normalized // quit early if assumptions are not met if (!((fabs(vd.length() - 1.0f)) < epsilonNormalizedError) || !((fabs(up.length() - 1.0f)) < epsilonNormalizedError)) { cerr << "ERROR: Up or vd vectors are not normal vectors. Camera positioning aborted..." << endl; return; } V3 newa, newb, newc, newC; // compute new C, a, and b newC = P - (vd * distance); newa = (vd ^ up).getNormalized() * a.length(); newb = (vd ^ newa).getNormalized() * b.length(); V3 principalPoint = getPrincipalPoint(); float PPu = principalPoint.getX(); float PPv = principalPoint.getY(); // compute new c newc = vd*getFocalLength() - (PPu * newa) - (PPv * newb); // commit new values C = newC; a = newa; b = newb; c = newc; // update projection matrix buildProjM(); }
V3 PPC::unproject(const V3 & projP) const { // From projection of point formula we know // P = C + (au + bv + c) * w // but since our project function above returns 1/w // P = C + (au + bv + c) * (1/w) V3 ret = C + (a*projP.getX() + b*projP.getY() + c) / projP.getZ(); return ret; }
void PPC::zoom(float zoomFactor) { // calculate new focal length float newFocalLength = getFocalLength() * zoomFactor; // calculate new c V3 principalPoint = getPrincipalPoint(); V3 viewDirection = getViewDir(); float PPu = principalPoint.getX(); float PPv = principalPoint.getY(); c = -1.0f * (PPu * a) - (PPv * b) + viewDirection*newFocalLength; // update projection matrix buildProjM(); }
void V3::rotateThisPointAboutAxis(const V3 &axisOrigin, const V3 &axisDirection, float theta) { // axisOrigin is interpreted to be a point representing origin of axis // axisDirection is interpreted to be a vector representing axis direction // quit early if axisDirection is not unit length if ( !(fabs(axisDirection.length() - 1.0f) < epsilonNormalizedError) ) { cerr << "ERROR: Attempting to rotate about a non-normalized vector. Zero vector produced..." << endl; *this = V3(); return; } // step 1 create new coordinate system with axisOrigin and axisDirection // as one of its axis // decide whether to pick x-axis or y-axis to start deriving new basis // vectors for new coordinate system V3 xAxis(1.0f, 0.0f, 0.0f); V3 yAxis(0.0f, 1.0f, 0.0f); // choose the axis that makes the larger angle with axisDirection // assumes axisDirection is also a unit vector at this point, // therefore the dot product between axisDirection and the x and // y axis tells the magnitude of the angle between them. Smaller // the dot product the greater the angle. V3 chosenAxis = (fabs(axisDirection.getX()) < fabs(fabs(axisDirection.getY()))) ? xAxis : yAxis; // derive a vector that is perpendicular to axisDirection V3 basisVector2 = chosenAxis ^ axisDirection; // normalize in order to have an orthonormal basis set basisVector2.normalize(); // derive a third vector that is perpendicular to axisDirection // and basisVector2 V3 basisVector3 = axisDirection ^ basisVector2; // normalize in order to have an orthonormal basis set basisVector3.normalize(); // get representation of this point in new coordinate system // where axisDirection is the X axis V3 tempPoint = thisPointInNewCoordSystem( axisOrigin, axisDirection, basisVector2, basisVector3); // step 2 rotate point in new coordinate system rotate by theta degrees // assuming axisDirection represents the X axis in new coordiante // system (local space) M33 rotMatX; rotMatX.setRotationAboutX(theta); // rotate tempPoint theta degrees about axisDirection (x-axis in local space) tempPoint = rotMatX * tempPoint; // step 3 transform back to the original system // according to lecture the math for this can be derived from the // change of coordinate system formulation and its // P = Inverse(R)*P' + O' = Transpose(R)*P' + O' // where R is the matrix to rotate old axis into new axis, which // is technically a rotation matrix and that's why Inverse(R)=Transpose(R) M33 R(axisDirection, basisVector2, basisVector3); // transform point back to original system V3 &P = *this; P = (R.getTranspose() * tempPoint) + axisOrigin; }