/** * Generates the arc lengths, generates the reverse table if the * {@link #setRepeatType(com.ardor3d.scenegraph.controller.ComplexSpatialController.RepeatType) repeat type} is set * to {@link ComplexSpatialController.RepeatType#CYCLE cycle} * * @param step * 'See Also:' method for more info. * @see #generateArcLengths(int, boolean) */ public void generateArcLengths(final int step) { generateArcLengths(step, RepeatType.CYCLE.equals(getRepeatType())); }
@Override protected Vector3 interpolateVectors(final ReadOnlyVector3 from, final ReadOnlyVector3 to, final double delta, final Vector3 target) { assert (null != from) : "parameter 'from' can not be null"; assert (null != to) : "parameter 'to' can not be null"; final ReadOnlyVector3 p0 = getControlPointStart(); final ReadOnlyVector3 p3 = getCotnrolPointEnd(); final Spline spline = getCurve().getSpline(); return spline.interpolate(p0, from, to, p3, delta, target); }
/** * @return The final control point, will not be <code>null</code>. */ protected ReadOnlyVector3 getCotnrolPointEnd() { ReadOnlyVector3 control = null; final int toIndex = getIndex(); switch (getRepeatType()) { case CLAMP: control = getControls().get(toIndex + 2); break; case CYCLE: if (isCycleForward()) { control = getControls().get(toIndex + 2); } else { control = getControls().get(toIndex - 2); } break; case WRAP: control = getControls().get(toIndex + 2); break; } return control; }
@Override public void update(final double time, final Spatial caller) { if (null == caller) { throw new IllegalArgumentException("caller can not be null!"); } final Vector3 interpolated = Vector3.fetchTempInstance(); final Matrix3 rotation = Matrix3.fetchTempInstance(); _curveController.interpolateVectors(_curveController.getControlFrom(), _curveController.getControlTo(), _curveController.getDelta(), interpolated); MathUtils.matrixLookAt(_previous, interpolated, _worldUp, rotation); if (isLocalRotation()) { caller.setRotation(rotation); } else { caller.setWorldRotation(rotation); } _previous.set(interpolated); Matrix3.releaseTempInstance(rotation); Vector3.releaseTempInstance(interpolated); }
@Override protected double incrementDelta(final double by) { double delta; /* * If constant speed we need to also check we aren't clamped at max index before we call lookup in the arc * length table because there would be no point */ if (isConstantSpeed()) { _distance += by; if (isCycleForward()) { assert (null != _arcLengths) : "You need to call generateArcLengths(x, false) to create the required arc length table!"; delta = _arcLengths.getDelta(getIndex(), _distance); } else { assert (null != _arcLengthsReverse) : "You need to call generateArcLengths(x, true) to create the required reverse arc length table!"; delta = _arcLengthsReverse.getDelta(getIndex(), _distance); } setDelta(delta); } else { delta = super.incrementDelta(by); } return delta; }
@Override protected int decrementIndex() { assert (null != _arcLengthsReverse) : "You need to call generateArcLengths() to create the required arc length tables!"; _distance -= _arcLengthsReverse.getLength(getIndex()); return super.decrementIndex(); }
/** * Creates a new instance of <code>CurveLookAtController</code>. * * @param curveController * The curve interpolation controller that does the work of finding the correct position to look at, can * not be <code>null</code>. * @param worldUp * The world up vector, can not be <code>null</code>. */ public CurveLookAtController(final CurveInterpolationController curveController, final ReadOnlyVector3 worldUp) { super(); if (null == curveController) { throw new IllegalArgumentException("curveController can not be null!"); } _curveController = curveController; _previous = new Vector3(_curveController.getControlFrom()); setWorldUp(worldUp); }
/** * Generates arc lengths which are required if you wish to have {@link #setConstantSpeed(boolean) constant speed} * interpolation. * * @param step * 'See Also:' method for more info. * @param reverse * <code>true</code> to also generate a reverse look up table. This is only required if you plan to use * the {@link ComplexSpatialController.RepeatType#CYCLE} repeat type. * @see ArcLengthTable#generate(int, boolean) */ public void generateArcLengths(final int step, final boolean reverse) { _arcLengths = new ArcLengthTable(getCurve()); _arcLengths.generate(step, false); if (reverse) { _arcLengthsReverse = new ArcLengthTable(getCurve()); _arcLengthsReverse.generate(step, true); } }
@Override public void update(final double time, final Spatial caller) { if (null == caller) { throw new IllegalArgumentException("caller can not be null!"); } final Vector3 interpolated = Vector3.fetchTempInstance(); final Matrix3 rotation = Matrix3.fetchTempInstance(); _curveController.interpolateVectors(_curveController.getControlFrom(), _curveController.getControlTo(), _curveController.getDelta(), interpolated); MathUtils.matrixLookAt(_previous, interpolated, _worldUp, rotation); if (isLocalRotation()) { caller.setRotation(rotation); } else { caller.setWorldRotation(rotation); } _previous.set(interpolated); Matrix3.releaseTempInstance(rotation); Vector3.releaseTempInstance(interpolated); }
@Override protected double incrementDelta(final double by) { double delta; /* * If constant speed we need to also check we aren't clamped at max index before we call lookup in the arc * length table because there would be no point */ if (isConstantSpeed()) { _distance += by; if (isCycleForward()) { assert (null != _arcLengths) : "You need to call generateArcLengths(x, false) to create the required arc length table!"; delta = _arcLengths.getDelta(getIndex(), _distance); } else { assert (null != _arcLengthsReverse) : "You need to call generateArcLengths(x, true) to create the required reverse arc length table!"; delta = _arcLengthsReverse.getDelta(getIndex(), _distance); } setDelta(delta); } else { delta = super.incrementDelta(by); } return delta; }
@Override protected int incrementIndex() { assert (null != _arcLengths) : "You need to call generateArcLengths() to create the required arc length tables!"; _distance -= _arcLengths.getLength(getIndex()); return super.incrementIndex(); }
/** * Creates a new instance of <code>CurveLookAtController</code>. * * @param curveController * The curve interpolation controller that does the work of finding the correct position to look at, can * not be <code>null</code>. * @param worldUp * The world up vector, can not be <code>null</code>. */ public CurveLookAtController(final CurveInterpolationController curveController, final ReadOnlyVector3 worldUp) { super(); if (null == curveController) { throw new IllegalArgumentException("curveController can not be null!"); } _curveController = curveController; _previous = new Vector3(_curveController.getControlFrom()); setWorldUp(worldUp); }
/** * Generates arc lengths which are required if you wish to have {@link #setConstantSpeed(boolean) constant speed} * interpolation. * * @param step * 'See Also:' method for more info. * @param reverse * <code>true</code> to also generate a reverse look up table. This is only required if you plan to use * the {@link ComplexSpatialController.RepeatType#CYCLE} repeat type. * @see ArcLengthTable#generate(int, boolean) */ public void generateArcLengths(final int step, final boolean reverse) { _arcLengths = new ArcLengthTable(getCurve()); _arcLengths.generate(step, false); if (reverse) { _arcLengthsReverse = new ArcLengthTable(getCurve()); _arcLengthsReverse.generate(step, true); } }
/** * @return The initial control point, will not be <code>null</code>. */ protected ReadOnlyVector3 getControlPointStart() { ReadOnlyVector3 control = null; final int fromIndex = getIndex(); switch (getRepeatType()) { case CLAMP: control = getControls().get(fromIndex - 1); break; case CYCLE: if (isCycleForward()) { control = getControls().get(fromIndex - 1); } else { control = getControls().get(fromIndex + 1); } break; case WRAP: control = getControls().get(fromIndex - 1); break; } return control; }
@Override protected Vector3 interpolateVectors(final ReadOnlyVector3 from, final ReadOnlyVector3 to, final double delta, final Vector3 target) { assert (null != from) : "parameter 'from' can not be null"; assert (null != to) : "parameter 'to' can not be null"; final ReadOnlyVector3 p0 = getControlPointStart(); final ReadOnlyVector3 p3 = getCotnrolPointEnd(); final Spline spline = getCurve().getSpline(); return spline.interpolate(p0, from, to, p3, delta, target); }
/** * Generates the arc lengths, generates the reverse table if the * {@link #setRepeatType(com.ardor3d.scenegraph.controller.ComplexSpatialController.RepeatType) repeat type} is set * to {@link ComplexSpatialController.RepeatType#CYCLE cycle} * * @param step * 'See Also:' method for more info. * @see #generateArcLengths(int, boolean) */ public void generateArcLengths(final int step) { generateArcLengths(step, RepeatType.CYCLE.equals(getRepeatType())); }
@Override protected int incrementIndex() { assert (null != _arcLengths) : "You need to call generateArcLengths() to create the required arc length tables!"; _distance -= _arcLengths.getLength(getIndex()); return super.incrementIndex(); }
/** * @return The initial control point, will not be <code>null</code>. */ protected ReadOnlyVector3 getControlPointStart() { ReadOnlyVector3 control = null; final int fromIndex = getIndex(); switch (getRepeatType()) { case CLAMP: control = getControls().get(fromIndex - 1); break; case CYCLE: if (isCycleForward()) { control = getControls().get(fromIndex - 1); } else { control = getControls().get(fromIndex + 1); } break; case WRAP: control = getControls().get(fromIndex - 1); break; } return control; }
@Override protected int decrementIndex() { assert (null != _arcLengthsReverse) : "You need to call generateArcLengths() to create the required arc length tables!"; _distance -= _arcLengthsReverse.getLength(getIndex()); return super.decrementIndex(); }
/** * @return The final control point, will not be <code>null</code>. */ protected ReadOnlyVector3 getCotnrolPointEnd() { ReadOnlyVector3 control = null; final int toIndex = getIndex(); switch (getRepeatType()) { case CLAMP: control = getControls().get(toIndex + 2); break; case CYCLE: if (isCycleForward()) { control = getControls().get(toIndex + 2); } else { control = getControls().get(toIndex - 2); } break; case WRAP: control = getControls().get(toIndex + 2); break; } return control; }