package teamcomm.gui.drawings.common;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.glu.GLUquadric;
import data.PlayerInfo;
import data.SPLStandardMessage;
import teamcomm.data.RobotState;
import teamcomm.gui.Camera;
import teamcomm.gui.drawings.RoSi2Loader;
import teamcomm.gui.drawings.PerPlayer;
/**
* Drawing for the ball as seen by a robot.
*
* @author Felix Thielke
*/
public class Ball extends PerPlayer {
private static final float ROBOT_HEAD_Z = 0.5f;
private static final float BALL_RADIUS = 0.0325f;
private static final float MIN_CYLINDER_RADIUS = 0.01f;
private static final float MAX_BALLAGE = 5.0f;
@Override
protected void init(GL2 gl) {
RoSi2Loader.getInstance().cacheModels(gl, new String[]{"ball"});
}
@Override
public void draw(final GL2 gl, final RobotState player, final Camera camera) {
final SPLStandardMessage msg = player.getLastMessage();
if (msg != null && msg.poseValid && msg.ballValid && msg.ballAge > -1 && msg.ballAge < MAX_BALLAGE && player.getPenalty() == PlayerInfo.PENALTY_NONE) {
final float[] ball = {msg.ball[0] / 1000.f, msg.ball[1] / 1000.f};
gl.glPushMatrix();
// Translate to robot
gl.glTranslatef(msg.pose[0] / 1000.f, msg.pose[1] / 1000.f, 0);
gl.glRotatef((float) Math.toDegrees(msg.pose[2]), 0, 0, 1);
// Translate to ball
gl.glTranslatef(ball[0], ball[1], 0);
// Draw ball
gl.glCallList(RoSi2Loader.getInstance().loadModel(gl, "ball"));
// Draw ball velocity
gl.glBegin(GL.GL_LINES);
gl.glColor3f(1, 0, 0);
gl.glNormal3f(0, 0, 1);
gl.glVertex3f(0, 0, BALL_RADIUS);
gl.glVertex3f(msg.ballVel[0] / 1000.f, msg.ballVel[1] / 1000.f, BALL_RADIUS);
gl.glEnd();
// Translate back to robot
gl.glTranslatef(-ball[0], -ball[1], 0);
// Draw cylinder from robot to ball
gl.glTranslatef(0, 0, ROBOT_HEAD_Z);
gl.glRotatef((float) Math.toDegrees(Math.atan2(ball[1], ball[0])), 0, 0, 1);
gl.glRotatef((float) Math.toDegrees(Math.atan2(Math.sqrt(ball[0] * ball[0] + ball[1] * ball[1]), BALL_RADIUS - ROBOT_HEAD_Z)), 0, 1, 0);
gl.glColorMaterial(GL2.GL_FRONT, GL2.GL_AMBIENT_AND_DIFFUSE);
gl.glColor4f(1, 0, 0, 0.25f);
gl.glEnable(GL2.GL_BLEND);
gl.glBlendFunc(GL2.GL_SRC_ALPHA, GL2.GL_ONE_MINUS_SRC_ALPHA);
final GLU glu = GLU.createGLU(gl);
final GLUquadric q = glu.gluNewQuadric();
final double cylinderLength = Math.sqrt(ball[0] * ball[0] + ball[1] * ball[1] + (BALL_RADIUS - ROBOT_HEAD_Z) * (BALL_RADIUS - ROBOT_HEAD_Z));
final double relativeAge = (double) msg.ballAge / (double) MAX_BALLAGE;
final double thinpart = cylinderLength * relativeAge;
final double thickpart = cylinderLength - thinpart;
if (thickpart < 0.05) {
glu.gluCylinder(q, MIN_CYLINDER_RADIUS, MIN_CYLINDER_RADIUS, cylinderLength, 16, 1);
} else {
glu.gluCylinder(q, BALL_RADIUS, BALL_RADIUS, thickpart - 0.05, 16, 1);
gl.glTranslated(0, 0, thickpart - 0.05);
glu.gluCylinder(q, BALL_RADIUS, MIN_CYLINDER_RADIUS, 0.05, 16, 1);
glu.gluCylinder(q, MIN_CYLINDER_RADIUS, MIN_CYLINDER_RADIUS, thinpart, 16, 1);
}
glu.gluDeleteQuadric(q);
gl.glDisable(GL2.GL_BLEND);
gl.glPopMatrix();
}
}
@Override
public boolean hasAlpha() {
return true;
}
@Override
public int getPriority() {
return 500;
}
}