/** * Efficient Gram-Schmitt Ortho-normalization for the special case of 2 vectors. * * @param v1 The first {@link Vector3} object to be ortho-normalized. * @param v2 The second {@link Vector3}. {@link Vector3} object to be ortho-normalized. */ public static void orthoNormalize(@NonNull Vector3 v1, @NonNull Vector3 v2) { v1.normalize(); v2.subtract(Vector3.projectAndCreate(v2, v1)); v2.normalize(); }
private void mapToSphere(final float x, final float y, Vector3 out) { float lengthSquared = x * x + y * y; if (lengthSquared > 1) { out.setAll(x, y, 0); out.normalize(); } else { out.setAll(x, y, Math.sqrt(1 - lengthSquared)); } }
private Vector3 calculateFaceNormal(int[] vertexIDs) { ArrayList<Vector3> vertices = mVertices.get(mObjects); Vector3 v1 = vertices.get(vertexIDs[0]); Vector3 v2 = vertices.get(vertexIDs[2]); Vector3 v3 = vertices.get(vertexIDs[1]); Vector3 vector1 = Vector3.subtractAndCreate(v2, v1); Vector3 vector2 = Vector3.subtractAndCreate(v3, v1); Vector3 normal = Vector3.crossAndCreate(vector1, vector2); normal.normalize(); return normal; }
/** * Sets this {@link Quaternion}'s components to the rotation between the given * two vectors. The incoming vectors should be normalized. This will fail if the two * vectors are parallel. * * @param x1 double The base vector's x component. * @param y1 double The base vector's y component. * @param z1 double The base vector's z component. * @param x2 double The target vector's x component. * @param y2 double The target vector's y component. * @param z2 double The target vector's z component. * * @return A reference to this {@link Quaternion} to facilitate chaining. */ @NonNull public Quaternion fromRotationBetween(double x1, double y1, double z1, double x2, double y2, double z2) { mTmpVec1.setAll(x1, y1, z1).normalize(); mTmpVec2.setAll(x2, y2, z2).normalize(); return fromRotationBetween(mTmpVec1, mTmpVec2); }
/** * Sets this {@link Matrix4} to a world matrix with the specified cardinal axis and the origin at the * provided position. * * @param position {@link Vector3} The position to use as the origin of the world coordinates. * @param forward {@link Vector3} The direction of the forward (z) vector. * @param up {@link Vector3} The direction of the up (y) vector. * * @return A reference to this {@link Matrix4} to facilitate chaining. */ @NonNull public Matrix4 setToWorld(@NonNull Vector3 position, @NonNull Vector3 forward, @NonNull Vector3 up) { mVec1.setAll(forward).normalize(); // Forward mVec2.setAll(mVec1).cross(up).normalize(); // Right mVec3.setAll(mVec2).cross(mVec1).normalize(); // Up return setAll(mVec2, mVec3, mVec1.multiply(-1d), position); }
/** * Applies Gram-Schmitt Ortho-normalization to the given set of input {@link Vector3} objects. * * @param vecs Array of {@link Vector3} objects to be ortho-normalized. */ public static void orthoNormalize(@NonNull @Size(min = 2) Vector3[] vecs) { for (int i = 0; i < vecs.length; ++i) { vecs[i].normalize(); for (int j = i + 1; j < vecs.length; ++j) { vecs[j].subtract(Vector3.projectAndCreate(vecs[j], vecs[i])); } } }
/** * Sets this {@link Quaternion}'s components from the given axis vector and angle around the axis. * * @param axis {@link Vector3} The axis to set rotation on. * @param angle double The rotation angle in degrees. * * @return A reference to this {@link Quaternion} to facilitate chaining. */ @NonNull public Quaternion fromAngleAxis(@NonNull Vector3 axis, double angle) { if (axis.isZero()) { return identity(); } else { mTmpVec1.setAll(axis); if (!mTmpVec1.isUnit()) { mTmpVec1.normalize(); } double radian = MathUtil.degreesToRadians(angle); double halfAngle = radian * .5; double halfAngleSin = Math.sin(halfAngle); w = Math.cos(halfAngle); x = halfAngleSin * mTmpVec1.x; y = halfAngleSin * mTmpVec1.y; z = halfAngleSin * mTmpVec1.z; return this; } }
protected Quaternion quaternionFromVector(Vector3 vec) { vec.normalize(); final double angle = MathUtil.radiansToDegrees(Math.acos(Vector3.dot(mForwardVec, vec))); final Quaternion q = new Quaternion(); q.fromAngleAxis(mTmpQuatVector.crossAndSet(mForwardVec, vec), angle); return q; } }
/** * Calculates the position on the spiral for the specified polar angle. This takes an additional * parameter of a {@link Vector3} which will be set to the calculated position. * * @param result {@link Vector3} to set with the updated position. * @param theta {@code double} the polar angle to calculate for, in degrees. */ @Override public void calculatePoint(Vector3 result, double theta) { final double angle = mSpiralIn ? mThetaOffset + theta : theta - mThetaOffset; final double r = a * Math.exp(mDensity * angle); // Update the rotation mRotation.fromAngleAxis(mUp, Math.toDegrees(angle)); //.inverse(); // Rotate the start-end vector based on the angle mScratch.setAll(mRotation.multiply(mStart)).normalize(); // Set the correct length result.setAll(mScratch.multiply(r)); if (mCalculateTangents) { mCurrentTangent.crossAndSet(mUp, mScratch); } }
/** * Calculates the position on the spiral for the specified polar angle. This takes an additional * parameter of a {@link Vector3} which will be set to the calculated position. * * @param result {@link Vector3} to set with the updated position. * @param theta {@code double} the polar angle to calculate for, in degrees. */ @Override public void calculatePoint(Vector3 result, double theta) { double angle = mSpiralIn ? mThetaOffset - theta : theta + mThetaOffset; if (angle == 0.0) angle = 1e-9; //Prevent a divide by zero for negative densities. final double r = a * Math.pow(angle, mInvDensity); // Update the rotation mRotation.fromAngleAxis(mUp, Math.toDegrees(angle)); // Rotate the start-end vector based on the angle mScratch.setAll(mRotation.multiply(mStart)).normalize(); // Set the correct length result.setAll(mScratch.multiply(r)); if (mCalculateTangents) { mCurrentTangent.crossAndSet(mUp, mScratch); } }
public void calculatePoint(Vector3 result, final double t) { if (mCalculateTangents) { double prevt = t == 0 ? t + DELTA : t - DELTA; double nextt = t == 1 ? t - DELTA : t + DELTA; p(mCurrentTangent, prevt); p(mTempNext, nextt); mCurrentTangent.subtract(mTempNext); mCurrentTangent.multiply(.5); mCurrentTangent.normalize(); } p(result,t); }
public Vector3 getCurrentTangent() { Vector3 startPortion = new Vector3(mStartTangent).multiply(1-mCurrent); Vector3 endPortion = new Vector3(mEndTangent).multiply(mCurrent); Vector3 result = startPortion.add(endPortion); result.normalize(); return result; }
public void set(Vector3 point1, Vector3 point2, Vector3 point3) { Vector3 v1 = new Vector3(); Vector3 v2 = new Vector3(); v1.subtractAndSet(point1, point2); v2.subtractAndSet(point3, point2); mNormal = v1.cross(v2); mNormal.normalize(); mD = -point1.dot(mNormal); }
public Vector3 getCurrentTangent() { double t = mCurrent; Vector3 startPortion = new Vector3(mStartTangent).multiply(3*(1-t)*(1-t)); Vector3 transferPortion = new Vector3(mTransferTangent).multiply(6*(1-t)*t); Vector3 endPortion = new Vector3(mEndTangent).multiply(3*t*t); Vector3 result = startPortion.add(transferPortion).add(endPortion); result.normalize(); return result; }
/** * Utility method to move the specified number of units along the current forward axis. This will * also adjust the look at target (if a valid one is currently set). * * @param units {@code double} Number of units to move. If negative, movement will be in the "back" direction. */ public void moveForward(double units) { mTempVec.setAll(WorldParameters.FORWARD_AXIS); mTempVec.rotateBy(mOrientation).normalize(); mTempVec.multiply(units); mPosition.add(mTempVec); if (mLookAtEnabled && mLookAtValid) { mLookAt.add(mTempVec); resetToLookAt(); } markModelMatrixDirty(); }
/** * Utility method to move the specified number of units along the current up axis. This will * also adjust the look at target (if a valid one is currently set). * * @param units {@code double} Number of units to move. If negative, movement will be in the "down" direction. */ public void moveUp(double units) { mTempVec.setAll(WorldParameters.UP_AXIS); mTempVec.rotateBy(mOrientation).normalize(); mTempVec.multiply(units); mPosition.add(mTempVec); if (mLookAtEnabled && mLookAtValid) { mLookAt.add(mTempVec); resetToLookAt(); } markModelMatrixDirty(); }
/** * Utility method to move the specified number of units along the current right axis. This will * also adjust the look at target (if a valid one is currently set). * * @param units {@code double} Number of units to move. If negative, movement will be in the "left" direction. */ public void moveRight(double units) { mTempVec.setAll(WorldParameters.RIGHT_AXIS); mTempVec.rotateBy(mOrientation).normalize(); mTempVec.multiply(units); mPosition.add(mTempVec); if (mLookAtValid) { mLookAt.add(mTempVec); resetToLookAt(); } markModelMatrixDirty(); }
private void applyRotation() { if (mIsRotating) { mapToSphere((float) mPrevScreenCoord.getX(), (float) mPrevScreenCoord.getY(), mPrevSphereCoord); mapToSphere((float) mCurrScreenCoord.getX(), (float) mCurrScreenCoord.getY(), mCurrSphereCoord); Vector3 rotationAxis = mPrevSphereCoord.clone(); rotationAxis.cross(mCurrSphereCoord); rotationAxis.normalize(); double rotationAngle = Math.acos(Math.min(1, mPrevSphereCoord.dot(mCurrSphereCoord))); mCurrentOrientation.fromAngleAxis(rotationAxis, MathUtil.radiansToDegrees(rotationAngle)); mCurrentOrientation.normalize(); Quaternion q = new Quaternion(mStartOrientation); q.multiply(mCurrentOrientation); mEmpty.setOrientation(q); } }
public boolean isLookingAtObject(Object3D target, float maxAngle) { mHeadViewQuaternion.fromMatrix(mHeadViewMatrix); mHeadViewQuaternion.inverse(); mForwardVec.setAll(0, 0, 1); mForwardVec.rotateBy(mHeadViewQuaternion); mHeadTranslation.setAll(mHeadViewMatrix.getTranslation()); mHeadTranslation.subtract(target.getPosition()); mHeadTranslation.normalize(); return mHeadTranslation.angle(mForwardVec) < maxAngle; } }
@Test public void testNormalize() { final Vector3 v = new Vector3(1d, 2d, 3d); final double mod = v.normalize(); assertEquals(3.7416573867739413, mod, 1e-14); assertEquals(0.267261241912424, v.x, 1e-14); assertEquals(0.534522483824849, v.y, 1e-14); assertEquals(0.801783725737273, v.z, 1e-14); final Vector3 v1 = new Vector3(1d, 0d, 0d); final double mod1 = v1.normalize(); assertEquals(1d, mod1, 0); assertEquals(1d, v1.x, 0); assertEquals(0d, v1.y, 0); assertEquals(0d, v1.z, 0); final Vector3 v2 = new Vector3(0d, 0d, 0d); final double mod2 = v2.normalize(); assertEquals(0d, mod2, 0); assertEquals(0d, v2.x, 0); assertEquals(0d, v2.y, 0); assertEquals(0d, v2.z, 0); }