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 boolean tickOnDraw =
true;
71 private volatile boolean tickPaused =
false;
72 private long frame_count = 0;
98 public static final class Set {
148 this.accel_obj = accel_px / this.pixPerShapeUnit.x();
151 this.start_velocity_obj = velocity_px / this.pixPerShapeUnit.x();
171 final int idx = this.allShapes.size();
172 this.allShapes.add( sd );
174 op.
setup(
this, idx, sd);
218 if( sd.active ) {
return true; }
223 private final List<Set> animSets =
new ArrayList<Set>();
238 if( idx < animSets.size() ) {
239 return animSets.get(idx);
246 for(
final Set as : animSets) {
247 as.remove(
this, gl, renderer);
255 as.remove(
this, gl, renderer);
262 for(
final Set as : asList) {
264 as.remove(
this, gl, renderer);
301 public boolean eval(
long frame_cnt,
Set as,
final int idx,
ShapeData sd,
float at_s,
float dt_s);
326 final float accel,
final float velocity,
327 final float ang_accel,
final float ang_velo,
336 accel, velocity, ang_accel, ang_velo,
337 new ArrayList<ShapeData>(),
new AABBox(), lerp);
371 final Font font,
final char refChar,
final CharSequence text,
final float fontScale,
372 final float accel,
final float velocity,
final float ang_accel,
final float ang_velo,
377 final List<ShapeData> allShapes =
new ArrayList<ShapeData>();
378 final AABBox sourceBounds = processString(allShapes, renderModes, font, fontScale, text);
380 refShape.
setScale(fontScale, fontScale, 1f);
386 accel, velocity, ang_accel, ang_velo, allShapes, sourceBounds, lerp);
392 for (
int idx = 0; idx < as.
allShapes.size(); ++idx) {
394 op.
setup(as, idx, sd);
395 super.addShape(sd.
shape);
398 System.err.println(
"addAnimShapes: AnimSet.sourceBounds = "+as.
sourceBounds);
403 private static final AABBox processString(
final List<ShapeData> res,
final int renderModes,
404 final Font font,
final float fontScale,
final CharSequence text)
411 gs.
setScale(fontScale, fontScale, 1f);
413 res.add(
new ShapeData( gs ) );
417 return font.
processString(fgv,
null, text,
new AffineTransform(),
new AffineTransform());
452 final Font font,
final CharSequence text,
final float fontScale,
final Vec4f fgCol,
453 final float accel,
final float velocity,
final float ang_accel,
final float ang_velo,
454 final AABBox animBox,
final boolean z_only,
final Random random,
final LerpFunc lerp)
456 return addGlyphSet(pixPerMM, glp, pmv, viewport, renderModes, font,
'X', text, fontScale,
457 accel, velocity, ang_accel, ang_velo, lerp, (
final Set as,
final int idx,
final ShapeData sd) -> {
466 z_only ? target.y() : animBox.
getMinY() + random.nextFloat() * animBox.
getHeight(),
467 0f + random.nextFloat() * animBox.
getHeight() * 1f);
495 final Font font,
final CharSequence text,
final float fontScale,
final Vec4f fgCol,
496 final float velocity,
final AABBox animBox,
final float y_offset)
499 renderModes, font,
'X', text, fontScale,
500 0f , velocity, 0f , 0f ,
503 sd.shape.setColor(fgCol);
505 sd.targetPos.set(animBox.getMinX(), y_offset, 0);
507 sd.startPos.set( sd.startPos.x() + animBox.getMaxX(), sd.targetPos.y(), sd.targetPos.z());
509 sd.shape.moveTo( sd.startPos );
525 if( tickPaused == v ) {
530 tpause_us = Clock.currentNanos() / 1000;
532 final long tnow_us = Clock.currentNanos() / 1000;
533 final long dtP_us = tnow_us - tpause_us;
543 if( tickOnDraw && !tickPaused) {
546 super.draw(gl, renderer);
550 tstart_us = Clock.currentNanos() / 1000;
551 tlast_us = tstart_us;
556 super.runSynced( () -> {
557 for(
final Set as : animSets) {
558 as.setAnimationActive(
true);
564 super.runSynced( () -> {
565 for(
final Set as : animSets) {
566 as.setAnimationActive(
false);
571 for(
final Set as : animSets) {
572 if( as.isAnimationActive() ) {
return true; }
584 super.runSynced( () -> { tickImpl(); } );
587 private final void tickImpl() {
588 final long tnow_us = Clock.currentNanos() / 1000;
589 final float at_s = (tnow_us - tstart_us) / 1e6f;
590 final float dt_s = (tnow_us - tlast_us) / 1e6f;
592 for(
final Set as : animSets) {
593 if( as.isAnimationActive() ) {
595 as.velocity += as.accel * dt_s;
596 as.velocity_obj += as.accel_obj * dt_s;
598 if( !FloatUtil.isZero( as.ang_accel ) ) {
599 as.ang_velo += as.ang_accel * dt_s;
601 for (
int idx = 0; idx < as.allShapes.size(); ++idx) {
602 final ShapeData sd = as.allShapes.get(idx);
603 if( !as.lerp.eval(frame_count, as, idx, sd, at_s, dt_s) ) {
626 this.rotAxis = rotAxis;
629 public boolean eval(
final long frame_cnt,
final Set as,
final int idx,
final ShapeData sd,
final float at_s,
final float dt_s) {
630 final float dxy = as.velocity_obj * dt_s;
631 final float rot_step = as.ang_velo * dt_s;
635 final float p_t_diff = p_t.
length();
638 final float rotAngDiff = Math.min(Math.abs(rotAng),
FloatUtil.
TWO_PI - Math.abs(rotAng));
641 final boolean rot_ok = pos_near && ( rot_step < AnimGroup.ROT_EPS || rotAngDiff <= AnimGroup.ROT_EPS || rotAngDiff <= rot_step * 2f );
642 if ( pos_ok && rot_ok ) {
646 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)+
")]");
658 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)+
")]");
678 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)+
")]");
681 if( rot_ok || rotAngDiff <= rot_step * 3f ) {
709 public boolean eval(
final long frame_cnt,
final Set as,
final int idx,
final ShapeData sd,
final float at_s,
final float dt_s) {
710 final float dxy = as.velocity_obj * dt_s;
713 final float p_t_diff = p_t.
length();
723 final float angle_thisstart_lastpos =
Vec3f.
UNIT_X.
angle(v_thisstart_lastpos);
764 final float sineScale;
765 final float shapeStep;
773 public SineLerp(
final Vec3f sineDir,
final float sineScale,
final float shapeStep) {
774 this.sineDir = sineDir;
775 this.sineScale = sineScale;
776 this.shapeStep = shapeStep;
779 public boolean eval(
final long frame_cnt,
final Set as,
final int idx,
final ShapeData sd,
final float at_s,
final float dt_s) {
780 final float dxy = as.velocity_obj * dt_s;
781 final float angle = as.ang_velo * ( at_s + idx * shapeStep * dt_s );
783 if( 0 == frame_cnt ) {
785 }
else if(
null != sd.
user ) {
787 pos.sub(lastSineVal);
790 final float p_t_diff = p_t.
length();
800 final float p_t_norm;
803 p_t_norm = p_t_diff / s_t.
length();
805 final float sineAmp =
FloatUtil.
sin(angle)*p_t_norm*shapeScale*sineScale;
812 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 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...
void draw(final GL2ES2 gl, final RegionRenderer renderer)
Renders the shape.
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).