28package com.jogamp.graph.ui;
30import java.util.ArrayList;
32import java.util.Random;
34import com.jogamp.common.os.Clock;
35import com.jogamp.graph.curve.opengl.GLRegion;
36import com.jogamp.graph.curve.opengl.RegionRenderer;
37import com.jogamp.graph.font.Font;
38import com.jogamp.graph.font.Font.Glyph;
39import com.jogamp.graph.ui.Group.Layout;
40import com.jogamp.graph.ui.shapes.GlyphShape;
41import com.jogamp.math.FloatUtil;
42import com.jogamp.math.Quaternion;
43import com.jogamp.math.Recti;
44import com.jogamp.math.Vec2f;
45import com.jogamp.math.Vec3f;
46import com.jogamp.math.Vec4f;
47import com.jogamp.math.geom.AABBox;
48import com.jogamp.math.geom.plane.AffineTransform;
49import com.jogamp.math.util.PMVMatrix4f;
50import com.jogamp.opengl.GL2ES2;
51import com.jogamp.opengl.GLProfile;
52import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
61 private static final boolean DEBUG =
false;
63 public static final float POS_EPS = FloatUtil.EPSILON * 5000;
67 private volatile long tstart_us = 0;
68 private volatile long tlast_us = 0;
69 private volatile long tpause_us = 0;
70 private volatile float fixed_frame_period = 0f;
71 private volatile float duration_s = 0;
73 private volatile boolean tickOnDraw =
true;
74 private volatile boolean tickPaused =
false;
75 private long frame_count = 0;
101 public static final class Set {
151 this.accel_obj = accel_px / this.pixPerShapeUnit.x();
154 this.start_velocity_obj = velocity_px / this.pixPerShapeUnit.x();
174 final int idx = this.allShapes.size();
175 this.allShapes.add( sd );
177 op.
setup(
this, idx, sd);
221 if( sd.active ) {
return true; }
226 private final List<Set> animSets =
new ArrayList<Set>();
241 if( idx < animSets.size() ) {
242 return animSets.get(idx);
249 for(
final Set as : animSets) {
250 as.remove(
this, gl, renderer);
258 as.remove(
this, gl, renderer);
265 for(
final Set as : asList) {
267 as.remove(
this, gl, renderer);
304 public boolean eval(
long frame_cnt,
Set as,
final int idx,
ShapeData sd,
float at_s,
float dt_s);
329 final float accel,
final float velocity,
330 final float ang_accel,
final float ang_velo,
339 accel, velocity, ang_accel, ang_velo,
340 new ArrayList<ShapeData>(),
new AABBox(), lerp);
374 final Font font,
final char refChar,
final CharSequence text,
final float fontScale,
375 final float accel,
final float velocity,
final float ang_accel,
final float ang_velo,
380 final List<ShapeData> allShapes =
new ArrayList<ShapeData>();
381 final AABBox sourceBounds = processString(allShapes, renderModes, font, fontScale, text);
383 refShape.
setScale(fontScale, fontScale, 1f);
389 accel, velocity, ang_accel, ang_velo, allShapes, sourceBounds, lerp);
395 for (
int idx = 0; idx < as.
allShapes.size(); ++idx) {
397 op.
setup(as, idx, sd);
398 super.addShape(sd.
shape);
401 System.err.println(
"addAnimShapes: AnimSet.sourceBounds = "+as.
sourceBounds);
406 private static final AABBox processString(
final List<ShapeData> res,
final int renderModes,
407 final Font font,
final float fontScale,
final CharSequence text)
414 gs.
setScale(fontScale, fontScale, 1f);
416 res.add(
new ShapeData( gs ) );
420 return font.
processString(fgv,
null, text,
new AffineTransform(),
new AffineTransform());
455 final Font font,
final CharSequence text,
final float fontScale,
final Vec4f fgCol,
456 final float accel,
final float velocity,
final float ang_accel,
final float ang_velo,
457 final AABBox animBox,
final boolean z_only,
final Random random,
final LerpFunc lerp)
459 return addGlyphSet(pixPerMM, glp, pmv, viewport, renderModes, font,
'X', text, fontScale,
460 accel, velocity, ang_accel, ang_velo, lerp, (
final Set as,
final int idx,
final ShapeData sd) -> {
469 z_only ? target.y() : animBox.
getMinY() + random.nextFloat() * animBox.
getHeight(),
470 0f + random.nextFloat() * animBox.
getHeight() * 1f);
498 final Font font,
final CharSequence text,
final float fontScale,
final Vec4f fgCol,
499 final float velocity,
final AABBox animBox,
final float y_offset)
502 renderModes, font,
'X', text, fontScale,
503 0f , velocity, 0f , 0f ,
506 sd.shape.setColor(fgCol);
508 sd.targetPos.set(animBox.getMinX(), y_offset, 0);
510 sd.startPos.set( sd.startPos.x() + animBox.getMaxX(), sd.targetPos.y(), sd.targetPos.z());
512 sd.shape.moveTo( sd.startPos );
528 if( tickPaused == v ) {
533 tpause_us = Clock.currentNanos() / 1000;
535 final long tnow_us = Clock.currentNanos() / 1000;
536 final long dtP_us = tnow_us - tpause_us;
546 if( tickOnDraw && !tickPaused) {
549 super.draw(gl, renderer);
553 tstart_us = Clock.currentNanos() / 1000;
554 tlast_us = tstart_us;
560 super.runSynced( () -> {
561 for(
final Set as : animSets) {
562 as.setAnimationActive(
true);
568 super.runSynced( () -> {
569 for(
final Set as : animSets) {
570 as.setAnimationActive(
false);
575 for(
final Set as : animSets) {
576 if( as.isAnimationActive() ) {
return true; }
605 super.runSynced( () -> { tickImpl(); } );
608 private final void tickImpl() {
609 final long tnow_us = Clock.currentNanos() / 1000;
610 final float dt_s, at_s;
612 dt_s = (tnow_us - tlast_us) / 1e6f;
613 at_s = (tnow_us - tstart_us) / 1e6f;
616 dt_s = fixed_frame_period;
621 for(
final Set as : animSets) {
622 if( as.isAnimationActive() ) {
623 if( !FloatUtil.isZero( as.accel ) ) {
624 as.velocity += as.accel * dt_s;
625 as.velocity_obj += as.accel_obj * dt_s;
627 if( !FloatUtil.isZero( as.ang_accel ) ) {
628 as.ang_velo += as.ang_accel * dt_s;
630 for (
int idx = 0; idx < as.allShapes.size(); ++idx) {
631 final ShapeData sd = as.allShapes.get(idx);
632 if( !as.lerp.eval(frame_count, as, idx, sd, at_s, dt_s) ) {
655 this.rotAxis = rotAxis;
658 public boolean eval(
final long frame_cnt,
final Set as,
final int idx,
final ShapeData sd,
final float at_s,
final float dt_s) {
659 final float dxy = as.velocity_obj * dt_s;
660 final float rot_step = as.ang_velo * dt_s;
664 final float p_t_diff = p_t.
length();
667 final float rotAngDiff = Math.min(Math.abs(rotAng),
FloatUtil.
TWO_PI - Math.abs(rotAng));
670 final boolean rot_ok = pos_near && ( rot_step < AnimGroup.ROT_EPS || rotAngDiff <= AnimGroup.ROT_EPS || rotAngDiff <= rot_step * 2f );
671 if ( pos_ok && rot_ok ) {
675 System.err.println(
"F: dt "+(dt_s*1000f)+
" ms, p_t[OK "+pos_ok+
", near "+pos_near+
", diff: "+p_t_diff+
", dxy "+dxy+
"], rot[OK "+rot_ok+
", radY "+rotAng+
" ("+
FloatUtil.
radToADeg(rotAng)+
"), diff "+rotAngDiff+
" ("+
FloatUtil.
radToADeg(rotAngDiff)+
"), ang_velo "+as.
ang_velo+
", step "+rot_step+
" ("+
FloatUtil.
radToADeg(rot_step)+
")]");
687 System.err.println(
"P: dt "+(dt_s*1000f)+
" ms, p_t[OK "+pos_ok+
", near "+pos_near+
", diff: "+p_t_diff+
", dxy "+dxy+
"], rot[OK "+rot_ok+
", radY "+rotAng+
" ("+
FloatUtil.
radToADeg(rotAng)+
"), diff "+rotAngDiff+
" ("+
FloatUtil.
radToADeg(rotAngDiff)+
"), ang_velo "+as.
ang_velo+
", step "+rot_step+
" ("+
FloatUtil.
radToADeg(rot_step)+
")]");
707 System.err.println(
"p: dt "+(dt_s*1000f)+
" ms, p_t[OK "+pos_ok+
", near "+pos_near+
", diff: "+p_t_diff+
", dxy "+dxy+
"], rot[OK "+rot_ok+
", radY "+rotAng+
" ("+
FloatUtil.
radToADeg(rotAng)+
"), diff "+rotAngDiff+
" ("+
FloatUtil.
radToADeg(rotAngDiff)+
"), ang_velo "+as.
ang_velo+
", step "+rot_step+
" ("+
FloatUtil.
radToADeg(rot_step)+
")]");
710 if( rot_ok || rotAngDiff <= rot_step * 3f ) {
738 public boolean eval(
final long frame_cnt,
final Set as,
final int idx,
final ShapeData sd,
final float at_s,
final float dt_s) {
739 final float dxy = as.velocity_obj * dt_s;
742 final float p_t_diff = p_t.
length();
752 final float angle_thisstart_lastpos =
Vec3f.
UNIT_X.
angle(v_thisstart_lastpos);
793 final float sineScale;
794 final float shapeStep;
802 public SineLerp(
final Vec3f sineDir,
final float sineScale,
final float shapeStep) {
803 this.sineDir = sineDir;
804 this.sineScale = sineScale;
805 this.shapeStep = shapeStep;
808 public boolean eval(
final long frame_cnt,
final Set as,
final int idx,
final ShapeData sd,
final float at_s,
final float dt_s) {
809 final float dxy = as.velocity_obj * dt_s;
810 final float angle = as.ang_velo * ( at_s + idx * shapeStep * dt_s );
812 if( 0 == frame_cnt ) {
814 }
else if(
null != sd.
user ) {
816 pos.sub(lastSineVal);
819 final float p_t_diff = p_t.
length();
829 final float p_t_norm;
832 p_t_norm = p_t_diff / s_t.
length();
834 final float sineAmp =
FloatUtil.
sin(angle)*p_t_norm*shapeScale*sineScale;
841 static final boolean methodB =
true;
Animation-Set covering its ShapeData elements, LerpFunc and animation parameter.
float velocity
Current translation velocity in [m]/[s].
final float accel_obj
Translation acceleration in [shapeUnit]/[s*s].
final float accel
Translation acceleration in [m]/[s*s].
final Vec2f pixPerShapeUnit
Pixel per shape unit.
final float start_velocity_obj
Start translation velocity in [shapeUnit]/[s].
void removeShape(final AnimGroup g, final GL2ES2 gl, final RegionRenderer renderer, final ShapeData sd)
Removes given ShapeData from this Set and its AnimGroup.
void setAnimationActive(final boolean v)
ShapeData addShape(final AnimGroup g, final Shape s, final ShapeSetup op)
Adds given Shape to this Set and its AnimGroup wrapping it in ShapeData.
final List< ShapeData > allShapes
All Shapes wrapped within ShapeData.
float ang_velo
Current angular velocity in [radians]/[s].
final Shape refShape
Reference Shape giving reference size.
void removeShapes(final AnimGroup g, final GL2ES2 gl, final RegionRenderer renderer)
Removes all ShapeData from this Set and its AnimGroup.
final float start_ang_velo
Start angular velocity in [radians]/[s].
final float start_velocity
Start translation velocity in [m]/[s].
final float pixPerMM
Pixel per millimeter.
boolean isAnimationActive()
final LerpFunc lerp
LerpFunc function
float velocity_obj
Current translation velocity in [shapeUnit]/[s].
final float ang_accel
Angular acceleration in [radians]/[s*s].
final AABBox sourceBounds
Unscaled bounds of allShapes at their original position, size and rotation.
Animation Shapes data covering one Shape of Set.
Object user
Optional user attachment per Shape to be used within LerpFunc.
ShapeData(final Shape s)
New instance with set Shape using its scaled Shape#getPosition() for startPos and targetPos.
final Shape shape
The Shapes.
final Vec3f targetPos
Shapes scaled target position
boolean active
Indicator whether the Shapes is animating or not.
final Vec3f startPos
Shapes scaled start position
Sine target LerpFunc, approaching ShapeData's target position utilizing the angular value for sine am...
SineLerp(final Vec3f sineDir, final float sineScale, final float shapeStep)
New sine LerpFunc instance.
boolean eval(final long frame_cnt, final Set as, final int idx, final ShapeData sd, final float at_s, final float dt_s)
Evaluate next LERP step for the given ShapeData within the animation Set.
Default target LerpFunc, approaching ShapeData's target position inclusive angular rotation around gi...
boolean eval(final long frame_cnt, final Set as, final int idx, final ShapeData sd, final float at_s, final float dt_s)
Evaluate next LERP step for the given ShapeData within the animation Set.
TargetLerp(final Vec3f rotAxis)
New target LerpFunc instance.
Group of animated Shapes including other static Shapes, optionally utilizing a Group....
final void resetAnimation()
final void removeAnimSet(final GL2ES2 gl, final RegionRenderer renderer, final Set as)
Removes the given Set and destroys it, including its ShapeData and Shape.
final float getDuration()
Returns either the actual duration between now-start, or the fixed frame duration increment.
final boolean getTickOnDraw()
final void tick()
Issues an animation tick, usually done at draw(GL2ES2, RegionRenderer).
final void setTickPaused(final boolean v)
Sets whether tick() shall be paused, default is false.
final void removeAllAnimSets(final GL2ES2 gl, final RegionRenderer renderer)
Removes all Sets and destroys them, including all ShapeData and their Shapes.
static final float POS_EPS
Epsilon of position, 5000 x FloatUtil#EPSILON.
final boolean getTickPaused()
final void setTickOnDraw(final boolean v)
Sets whether tick() shall be automatic issued on draw(GL2ES2, RegionRenderer), default is true.
final Set addGlyphSetRandom01(final float pixPerMM, final GLProfile glp, final PMVMatrix4f pmv, final Recti viewport, final int renderModes, final Font font, final CharSequence text, final float fontScale, final Vec4f fgCol, final float accel, final float velocity, final float ang_accel, final float ang_velo, final AABBox animBox, final boolean z_only, final Random random, final LerpFunc lerp)
Add a new Set with ShapeData for each GlyphShape, moving towards its target position using a fixed di...
Set getAnimSet(final int idx)
Return the Set at given index or null if n/a.
final void removeAnimSets(final GL2ES2 gl, final RegionRenderer renderer, final List< Set > asList)
Removes the given Sets and destroys them, including their ShapeData and Shape.
AnimGroup(final Layout l)
Create a group of animated Shapes including other static Shapes w/ given Group.Layout.
final Set addGlyphSet(final float pixPerMM, final GLProfile glp, final PMVMatrix4f pmv, final Recti viewport, final int renderModes, final Font font, final char refChar, final CharSequence text, final float fontScale, final float accel, final float velocity, final float ang_accel, final float ang_velo, final LerpFunc lerp, final ShapeSetup op)
Add a new Set with ShapeData for each GlyphShape, moving towards its target position using a generic ...
Set addAnimSet(final float pixPerMM, final GLProfile glp, final PMVMatrix4f pmv, final Recti viewport, final float accel, final float velocity, final float ang_accel, final float ang_velo, final LerpFunc lerp, final Shape refShape)
Add a new Set with an empty ShapeData container.
final boolean isAnimationActive()
static final float ROT_EPS
Epsilon of rotation [radian], 0.5 degrees or 0.008726646 radians.
final Set addGlyphSetHorizScroll01(final float pixPerMM, final GLProfile glp, final PMVMatrix4f pmv, final Recti viewport, final int renderModes, final Font font, final CharSequence text, final float fontScale, final Vec4f fgCol, final float velocity, final AABBox animBox, final float y_offset)
Add a new Set with ShapeData for each GlyphShape, implementing horizontal continuous scrolling while...
final void setFixedPeriod(final float p)
Allows setting a fixed frame period like 1f/60f.
void draw(final GL2ES2 gl, final RegionRenderer renderer)
Renders the shape.
final float getFixedPeriod()
See setFixedPeriod(float).
final void restartAnimation()
Group of Shapes, optionally utilizing a Group.Layout.
void addShape(final Shape s)
Adds a Shape.
Shape removeShape(final Shape s)
Removes given shape, w/o Shape#destroy(GL2ES2, RegionRenderer).
Generic Shape, potentially using a Graph via GraphShape or other means of representing content.
Shape setColor(final float r, final float g, final float b, final float a)
Set base color.
final Shape setScale(final Vec3f s)
Set scale factor to given scale.
final Shape setInteractive(final boolean v)
Set whether this shape is interactive in general, i.e.
final Vec3f getScale()
Returns scale Vec3f reference.
final Shape moveTo(final float tx, final float ty, final float tz)
Move to scaled position.
final float getScaledWidth()
Returns the scaled width of the bounding AABBox for this shape.
final float getScaledHeight()
Returns the scaled height of the bounding AABBox for this shape.
final Vec3f getPosition()
Returns position Vec3f reference, i.e.
final float[] getPixelPerShapeUnit(final int[] shapeSizePx, final float[] pixPerShape)
Retrieve pixel per scaled shape-coordinate unit, i.e.
final AABBox getBounds()
Returns the unscaled bounding AABBox for this shape, borrowing internal instance.
final Quaternion getRotation()
Returns Quaternion for rotation.
final Shape validate(final GL2ES2 gl)
Validates the shape's underlying GLRegion.
final Shape setRotation(final Quaternion q)
Sets the rotation Quaternion.
final void destroy(final GL2ES2 gl, final RegionRenderer renderer)
Destroys all data.
final void applyMatToMv(final PMVMatrix4f pmv)
Applies the internal Matrix4f to the given modelview matrix, i.e.
final Shape setVisible(final boolean v)
Enable (default) or disable this shape's visibility.
Representing a single Font.Glyph as a GraphShape.
Vec3f getOrigPos()
Returns the unscaled original position of this glyph, e.g.
Basic Float math utility functions.
static final float TWO_PI
The value 2PI, i.e.
static float sin(final float a)
static float radToADeg(final float rad)
Converts radians to arc-degree.
static float adegToRad(final float arc_degree)
Converts arc-degree to radians.
static boolean isZero(final float a, final float epsilon)
Returns true if value is zero, i.e.
static final float HALF_PI
The value PI/2, i.e.
Quaternion implementation supporting Gimbal-Lock free rotations.
Vec3f toEuler(final Vec3f result)
Transform this quaternion to Euler rotation angles in radians (pitchX, yawY and rollZ).
Quaternion rotateByAngleNormalAxis(final float angle, final float axisX, final float axisY, final float axisZ)
Rotate this quaternion by the given angle and axis.
final Quaternion setIdentity()
Rectangle with x, y, width and height integer components.
2D Vector based upon two float components.
3D Vector based upon three float components.
Vec3f mul(final float val)
Returns this * val; creates new vector.
float angle(final Vec3f o)
Return the angle between two vectors in radians using Math#acos(double) on cosAngle(Vec3f).
Vec3f scale(final float s)
this = this * s, returns this.
Vec3f normalize()
Normalize this vector in place.
float length()
Return the length of this vector, a.k.a the norm or magnitude
static final Vec3f UNIT_X
Vec3f minus(final Vec3f arg)
Returns this - arg; creates new vector.
Vec3f set(final Vec3f o)
this = o, returns this.
Vec3f add(final float dx, final float dy, final float dz)
this = this + { dx, dy, dz }, returns this.
4D Vector based upon four float components.
Axis Aligned Bounding Box.
final float getSize()
Get the size of this AABBox where the size is represented by the length of the vector between low and...
final AABBox resize(final AABBox newBox)
Resize the AABBox to encapsulate another AABox.
final boolean intersects2DRegion(final float x, final float y, final float w, final float h)
Check if there is a common region between this AABBox and the passed 2D region irrespective of z rang...
PMVMatrix4f implements the basic computer graphics Matrix4f pack using projection (P),...
final PMVMatrix4f popMv()
Pop the modelview matrix from its stack.
final PMVMatrix4f pushMv()
Push the modelview matrix to its stack, while preserving its values.
Specifies the the OpenGL profile.
General purpose Font.Glyph visitor.
boolean isNonContour()
Returns true if isWhitespace() or isUndefined().
Interface wrapper for font implementation.
AABBox processString(final Font.GlyphVisitor visitor, final AffineTransform transform, final CharSequence string)
Try using processString(GlyphVisitor, AffineTransform, CharSequence, AffineTransform,...
Linear interpolation (LERP) function to evaluate the next animated frame for each ShapeData of a Set.
boolean eval(long frame_cnt, Set as, final int idx, ShapeData sd, float at_s, float dt_s)
Evaluate next LERP step for the given ShapeData within the animation Set.
ShapeData setup function for animation using its enclosing Set and other data points
void setup(final Set as, final int idx, final ShapeData sd)
Setting up the ShapeData for animation using its enclosing Set and other data points.
Layout for the GraphUI Group, called @ Shape#validate(GL2ES2) or Shape#validate(GLProfile).