Java tutorial
// Copyright 2010 DEF // // This file is part of V3dScene. // // V3dScene is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // V3dScene is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with V3dScene. If not, see <http://www.gnu.org/licenses/>. package fr.def.iss.vd2.lib_v3d.camera; import java.awt.Point; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.List; import org.lwjgl.opengl.GL11; import org.lwjgl.util.glu.GLU; import com.spaceagencies.i3d.scene.I3dCamera; import fr.def.iss.vd2.lib_v3d.V3DContext; import fr.def.iss.vd2.lib_v3d.V3DVect3; /** * * @author fberto */ public class V3DSimple2DCamera extends I3dCamera { private Point2D.Float position = new Point2D.Float(0, 0); private float rotation = 0; private float zoom = 10; private float lastWidth = 0; private float lastHeight = 0; private boolean showCenter = false; public V3DSimple2DCamera() { } @Override protected void configureView(GLU glu) { if (lastWidth != currentWidth || lastHeight != currentHeight) { fireZoomChanged(); } lastWidth = currentWidth; lastHeight = currentHeight; GL11.glRotatef(-90, 0, 0, 1.0f); GL11.glRotatef(rotation, 0, 0, 1.0f); glu.gluLookAt(position.x, position.y, 0, position.x, position.y, -200, 1, 0, 0); } public Point2D.Float getPosition() { return position; } public void move(Point2D.Float offset) { Point2D.Float currentPosition = getPosition(); setPosition(currentPosition.x + offset.x, currentPosition.y + offset.y); } public void setPosition(Point2D.Float position) { this.position = position; firePositionChanged(); } public V3DVect3 getRotation() { return new V3DVect3(rotation, 0, 0); } public void setRotation(float rotation) { this.rotation = rotation; } public void setPosition(float x, float y) { this.position.x = x; this.position.y = y; firePositionChanged(); } public float getZoom() { return zoom; } public void setZoom(float zoom) { this.zoom = zoom; fireZoomChanged(); } public void setShowCenter(boolean showCenter) { this.showCenter = showCenter; } @Override protected void preDisplayScene() { if (showCenter) { displayTarget(); } } private void displayTarget() { GL11.glColor4f(1.0f, 0.5f, 0.5f, 0.8f); GL11.glLineWidth(1.2f); GL11.glBegin(GL11.GL_LINES); { GL11.glColor4f(1.0f, 0.0f, 0.0f, 0.8f); GL11.glVertex3d(-1, 0, 0); GL11.glVertex3d(1, 0, 0); GL11.glVertex3d(0.9, 0.1, 0); GL11.glVertex3d(1, 0, 0); GL11.glVertex3d(0.9, -0.1, 0); GL11.glVertex3d(1, 0, 0); //y GL11.glColor4f(0.0f, 1.0f, 0.0f, 0.8f); GL11.glVertex3d(0, -1, 0); GL11.glVertex3d(0, 1, 0); GL11.glVertex3d(0.1, 0.9, 0); GL11.glVertex3d(0, 1, 0); GL11.glVertex3d(-0.1, 0.9, 0); GL11.glVertex3d(0, 1, 0); //z GL11.glColor4f(0.0f, 0.0f, 1.0f, 0.8f); GL11.glVertex3d(0, 0, -1); GL11.glVertex3d(0, 0, 1); GL11.glVertex3d(0.1, 0, 0.9); GL11.glVertex3d(0, 0, 1); GL11.glVertex3d(-0.1, 0, 0.9); GL11.glVertex3d(0, 0, 1); } GL11.glEnd(); GL11.glPointSize(1.2f); GL11.glBegin(GL11.GL_POINTS); { GL11.glVertex3d(position.x, position.y, 0); } GL11.glEnd(); } @Override public void enableRotation() { GL11.glPopMatrix(); } @Override public void disableRotation() { GL11.glPushMatrix(); GL11.glRotatef(-rotation, 0, 0, 1.0f); } @Override public float getRelativeSize() { /*if (height <= 0) { // avoid a divide by zero error! height = 1; } final float h = width / height; return h * zoom;*/ if (currentHeight <= 0) { // avoid a divide by zero error! currentHeight = 1; } float x = 2 * zoom / currentHeight; return x; } public Point2D.Float getSize() { if (currentHeight <= 0) { // avoid a divide by zero error! currentHeight = 1; } final float h = currentWidth / currentHeight; return new Point2D.Float(2 * zoom * h, 2 * zoom); } @Override protected void initPerspective() { if (currentHeight <= 0) { // avoid a divide by zero error! currentHeight = 1; } final float h = currentWidth / currentHeight; GL11.glOrtho(-zoom * h, zoom * h, -zoom, zoom, -2000.0, 2000.0); } public Point2D.Float pick(int pickX, int pickY) { final float h = currentWidth / currentHeight; pickY = (int) currentHeight - pickY; float x = ((float) pickX) / ((float) currentWidth) * (2 * zoom * h) + (-zoom * h) + position.x; float y = ((float) pickY) / ((float) currentHeight) * (2 * zoom) + (-zoom) + position.y; return new Point2D.Float(x, y); } public Point unPick(float x, float y) { final float h = currentWidth / currentHeight; int pickX = (int) (((x - position.x + zoom * h) * currentWidth) / (2 * zoom * h)); int pickY = (int) (((y - position.y + zoom) * currentHeight) / (2 * zoom)); pickY = (int) currentHeight - pickY; return new Point(pickX, pickY); } public Point2D.Float dist(int distX, int distY) { if (currentHeight <= 0) { // avoid a divide by zero error! currentHeight = 1; } if (currentWidth <= 0) { // avoid a divide by zero error! currentWidth = 1; } final float h = currentWidth / currentHeight; float x = ((float) distX) / ((float) currentWidth) * (2 * zoom * h); float y = ((float) distY) / ((float) currentHeight) * (2 * zoom); return new Point2D.Float(x, y); } public Point distMouse(Point2D.Float dist) { if (currentHeight <= 0) { // avoid a divide by zero error! currentHeight = 1; } final float h = currentWidth / currentHeight; int x = (int) (((float) currentWidth) * dist.x / (2 * zoom * h)); int y = (int) (((float) currentHeight) * dist.y / (2 * zoom)); return new Point(x, y); } public void fit(Point2D.Float leftTopCorner, Point2D.Float size) { fit(leftTopCorner, size, 5); } public float getFitZoom(Point2D.Float size, int padding) { float fitZoom = 0; if (currentHeight <= 0) { // avoid a divide by zero error! currentHeight = 1; } final float h = currentWidth / currentHeight; if (h > 0) { //Compute zoom float usableWidth = size.x * (1 + padding / 100f); float usableHeight = size.y * (1 + padding / 100f); float zoomWidth = usableWidth / (2f * h); float zoomHeight = usableHeight / 2f; fitZoom = Math.max(zoomWidth, zoomHeight); if (fitZoom == 0) { fitZoom = 1; } } return fitZoom; } public void fit(final Point2D.Float leftTopCorner, final Point2D.Float size, final int padding) { Runnable fitAction = new Runnable() { @Override public void run() { zoom = getFitZoom(size, padding); setPosition(size.x / 2 + leftTopCorner.x, size.y / 2 + leftTopCorner.y); fireZoomChanged(); } }; if (isConfigured()) { fitAction.run(); } else { setCameraInitialisation(fitAction); } } @Override public void fitAll() { fitAll(5); } public void fitAll(int padding) { V3DVect3 scenePosition = currentScene.getRootElement().getBoundingBox().getPosition(); V3DVect3 sceneSize = currentScene.getRootElement().getBoundingBox().getSize(); fit(new Point2D.Float(scenePosition.x - sceneSize.x / 2f, scenePosition.y - sceneSize.y / 2f), new Point2D.Float(sceneSize.x, sceneSize.y), padding); } public boolean containsAll() { V3DVect3 sceneSize = currentScene.getRootElement().getBoundingBox().getSize(); return zoom > getFitZoom(new Point2D.Float(sceneSize.x, sceneSize.y), 5); } //Zoom Listener List<CameraListener> cameraListenerList = new ArrayList<CameraListener>(); public void addCameraListener(CameraListener listener) { cameraListenerList.add(listener); } public void removeCameraChangeListener(CameraListener listener) { cameraListenerList.remove(listener); } private void fireZoomChanged() { for (CameraListener listener : cameraListenerList) { listener.zoomChanged(); } } private void firePositionChanged() { for (CameraListener listener : cameraListenerList) { listener.positionChanged(); } } @Override public void fitAllIfInvalid() { if (zoom == 0) { fitAll(); } } @Override public void center(V3DVect3 position) { setPosition(position.x, position.y); } public interface CameraListener { public void zoomChanged(); public void positionChanged(); } }