package gl.animations; import gl.GLCamera; import gl.Renderable; import gl.scenegraph.MeshComponent; import javax.microedition.khronos.opengles.GL10; import util.Vec; import worldData.Updateable; import worldData.Visitor; public class AnimationFaceToCamera extends GLAnimation { private GLCamera myTargetCamera; private float lastUpdateAway = 0; private float myUpdateDelay; private Vec rotationVec = new Vec(); private Vec newRotationVec = new Vec(); private Vec adjustmentVec; private Vec myTargetCameraPosition; private boolean dontChangeXRotation; /** * @param targetCamera * @param targetMesh * @param updateDelay * around 0.5f s * @param dontChangeXRotation * if this is false, the mesh will also change the rotation x * value, otherwise only the z value to face to the camera */ public AnimationFaceToCamera(GLCamera targetCamera, float updateDelay, boolean dontChangeXRotation) { myTargetCamera = targetCamera; myUpdateDelay = updateDelay; myTargetCameraPosition = myTargetCamera.getPosition(); this.dontChangeXRotation = dontChangeXRotation; // Log.d("face camera animation", "created. camera=" + myTargetCamera // + " targetMesh class=" + myTargetMesh.getClass() // + " update delay=" + myUpdateDelay); } public AnimationFaceToCamera(GLCamera targetCamera, float updateDelay) { this(targetCamera, updateDelay, true); } public AnimationFaceToCamera(GLCamera targetCamera) { this(targetCamera, 0.5f, true); } /** * @param targetCamera * @param targetMesh * @param updateDelay * 0.5f * @param adjustmentVec */ public AnimationFaceToCamera(GLCamera targetCamera, float updateDelay, Vec adjustmentVec) { this(targetCamera, updateDelay); this.adjustmentVec = adjustmentVec; } @Override public boolean update(float timeDelta, Updateable parent) { /* * TODO use mesh instead of assigning a mesh while creating this * animation! */ timeDelta = Math.abs(timeDelta); lastUpdateAway += timeDelta; if (lastUpdateAway > myUpdateDelay) { updateRotation(parent); // Log.d("face camera animation", "new rotation vec calculated:"); // Log.d("face camera animation", // "x="+newRotationVec.x+" , z="+newRotationVec.z); lastUpdateAway = 0; } if (dontChangeXRotation) { Vec.morphToNewAngleVec(rotationVec, 0, 0, newRotationVec.z, timeDelta); } else { Vec.morphToNewAngleVec(rotationVec, newRotationVec.x, newRotationVec.y, newRotationVec.z, timeDelta); } return true; } Vec absolutePosition = new Vec(); private void updateRotation(Updateable parent) { if (parent instanceof MeshComponent) { absolutePosition.setToZero(); ((MeshComponent) parent).getAbsoluteMeshPosition(absolutePosition); // Log.d("face camera animation", "mesh position: "+pos); newRotationVec.toAngleVec(absolutePosition, myTargetCameraPosition); /* * substract 90 from the x value becaute calcanglevec returns 90 if * the rotation should be the horizon (which would mean no object * rotation) */ newRotationVec.x -= 90; newRotationVec.z *= -1; } } @Override public void render(GL10 gl, Renderable parent) { gl.glRotatef(rotationVec.z, 0, 0, 1); gl.glRotatef(rotationVec.x, 1, 0, 0); gl.glRotatef(rotationVec.y, 0, 1, 0); if (adjustmentVec != null) { /* * if an adjustment vector is set this adjustment has to be done * AFTER the rotation to be easy to use, see constructor for infos * about adjustment */ gl.glRotatef(adjustmentVec.x, 1, 0, 0); // TODO find correct order gl.glRotatef(adjustmentVec.z, 0, 0, 1); gl.glRotatef(adjustmentVec.y, 0, 1, 0); } } @Override public boolean accept(Visitor visitor) { return visitor.default_visit(this); } }