[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[gef3d-commits] r320 - in trunk/org.eclipse.draw3d/src/java/org/eclipse: draw2d draw3d draw3d/camera draw3d/picking draw3d/shapes

Author: kduske
Date: 2009-09-21 12:02:07 -0400 (Mon, 21 Sep 2009)
New Revision: 320

Added:
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ArrowDecoration3D.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/BorderAnchor3D.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ConnectionLocator3D.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/Locator1D.java
Modified:
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw2d/EventDispatcher3D.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ArrowLocator3D.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/Export3DOperation.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/Figure3D.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/LightweightSystem3D.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/PolylineConnection3D.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/RenderContext.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ShapeDecoration.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ShapeFigure3D.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/camera/AbstractCamera.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/camera/FirstPersonCamera.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/camera/RestrictedFirstPersonCamera.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/picking/Pickable.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/picking/Query.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CuboidFigureShape.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CuboidShape.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CylinderShape.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CylindricFigureShape.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/NullShape.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/ParaxialBoundsFigureShape.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/PolylineFigureShape.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/PositionableShape.java
   trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/SphereShape.java
Log:
- added arrow decoration and made ShapeDecoration abstract
- added border anchor and 1D locators
- adapted Figure3D, RootFigure3D, ShapeFigure to changes in Pickable interface
- cleaned up Javadoc in RenderContext
- a few minor changes in RenderContext (renamed a method and cleaned up #dispose())
- fixed a bug in AbstractCamera (ConcurrentModificationException)
- changed the far and near clipping planes (moved the near plane away from and the far plane nearer to the camera)
- minor performance optimization in FirstPersonCamera#orbit
- fixed the restricted first person camera
- Pickable#getDistance now takes a ray and a map instead of a picking query as parameters to make it more flexible
- removed Query#set
- adapted all shapes to changes in Pickable


Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw2d/EventDispatcher3D.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw2d/EventDispatcher3D.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw2d/EventDispatcher3D.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -276,8 +276,7 @@
 				m_getAccessibilityDispatcherMethod.setAccessible(true);
 			}
 
-			return (AccessibilityDispatcher) m_getAccessibilityDispatcherMethod
-				.invoke(m_dispatcher);
+			return (AccessibilityDispatcher) m_getAccessibilityDispatcherMethod.invoke(m_dispatcher);
 		} catch (Exception e) {
 			// very unlikely to happen, so
 			throw new RuntimeException("could not reflectively invoke method "

Added: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ArrowDecoration3D.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ArrowDecoration3D.java	                        (rev 0)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ArrowDecoration3D.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Jens von Pilgrim and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kristian Duske - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.draw3d;
+
+import org.eclipse.draw3d.shapes.CylindricFigureShape;
+import org.eclipse.draw3d.shapes.Shape;
+
+/**
+ * A decoration figure that renders an arrow head.
+ * 
+ * @author Kristian Duske
+ * @version $Revision$
+ * @since 20.09.2009
+ */
+public class ArrowDecoration3D extends ShapeDecoration {
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.draw3d.ShapeFigure3D#createShape()
+	 */
+	@Override
+	protected Shape createShape() {
+
+		CylindricFigureShape s = new CylindricFigureShape(this, 12, 0, false);
+		s.setFill(true);
+		s.setOutline(true);
+
+		return s;
+	}
+
+	/**
+	 * Specifies whether the arrow head should be filled with the background
+	 * color.
+	 * 
+	 * @param i_fill <code>true</code> if the arrow head should be filled and
+	 *            <code>false</code> otherwise
+	 */
+	public void setFill(boolean i_fill) {
+
+		((CylindricFigureShape) getShape()).setFill(i_fill);
+	}
+
+	/**
+	 * Specifies whether the arrow head should be outlined with the foreground
+	 * color.
+	 * 
+	 * @param i_outline <code>true</code> if the arrow should be outlined and
+	 *            <code>false</code> otherwise
+	 */
+	public void setOutline(boolean i_outline) {
+
+		((CylindricFigureShape) getShape()).setOutline(i_outline);
+	}
+}

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ArrowLocator3D.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ArrowLocator3D.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ArrowLocator3D.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -16,11 +16,7 @@
 
 import org.eclipse.draw2d.DelegatingLayout;
 import org.eclipse.draw2d.IFigure;
-import org.eclipse.draw2d.Locator;
 import org.eclipse.draw3d.geometry.IVector3f;
-import org.eclipse.draw3d.geometry.Math3D;
-import org.eclipse.draw3d.geometry.Vector3f;
-import org.eclipse.draw3d.geometry.Vector3fImpl;
 
 /**
  * Locator used to place a {@link RotatableDecoration3D} on a
@@ -32,135 +28,34 @@
  * @version $Revision$
  * @since 17.05.2008
  */
-public class ArrowLocator3D implements Locator {
+public class ArrowLocator3D extends ConnectionLocator3D {
 
 	/**
-	 * Enumerates the alignment options for a 3D locator.
+	 * Creates a new locator for the given connection and alignment.
 	 * 
-	 * @author Kristian Duske
-	 * @version $Revision$
-	 * @since 19.05.2008
+	 * @param i_connection the connection
+	 * @param i_alignment the alignment
 	 */
-	public static enum Alignment {
-		/**
-		 * The middle of the connection.
-		 */
-		MIDDLE,
-		/**
-		 * The source of the connection.
-		 */
-		SOURCE,
-		/**
-		 * The target of the connection.
-		 */
-		TARGET
-	}
-
-	private Alignment m_alignment;
-
-	private Connection3D m_connection;
-
-	/**
-	 * Creates a new locator for the given connection and with the given
-	 * alignment.
-	 * 
-	 * @param i_connection the connection associated with the locator
-	 * @param i_alignment the alignment of the locator
-	 * @throws NullPointerException if either of the given arguments is
-	 *             <code>null</code>
-	 */
 	public ArrowLocator3D(Connection3D i_connection, Alignment i_alignment) {
-
-		if (i_connection == null)
-			throw new NullPointerException("i_connection must not be null");
-
-		if (i_alignment == null)
-			throw new NullPointerException("i_alignment must not be null");
-
-		m_connection = i_connection;
-		m_alignment = i_alignment;
+		super(i_connection, i_alignment);
 	}
 
 	/**
-	 * Returns the alignment of this locator.
-	 * 
-	 * @return the alignment of this locator
-	 */
-	public Alignment getAlignment() {
-
-		return m_alignment;
-	}
-
-	/**
-	 * Returns the connection associated with this locator.
-	 * 
-	 * @return the connection associated with this locator
-	 */
-	public Connection3D getConnection() {
-
-		return m_connection;
-	}
-
-	/**
-	 * Returns the location of a decoration depending on the locator's
-	 * alignment.
-	 * 
-	 * @param i_points the point list
-	 * @param io_result the result vector, can be <code>null</code>
-	 * @return the location
-	 * @throws NullPointerException if the given point list is <code>null</code>
-	 */
-	protected IVector3f getLocation(List<IVector3f> i_points, Vector3f io_result) {
-
-		if (i_points == null)
-			throw new NullPointerException("i_points must not be null");
-
-		if (io_result == null)
-			io_result = new Vector3fImpl();
-
-		int size = i_points.size();
-		switch (m_alignment) {
-		case SOURCE:
-			io_result.set(i_points.get(0));
-			break;
-		case TARGET:
-			io_result.set(i_points.get(size - 1));
-			break;
-		case MIDDLE:
-			if ((size % 2) == 0) {
-				int i = size / 2;
-				IVector3f p1 = i_points.get(i - 1);
-				IVector3f p2 = i_points.get(i);
-				Math3D.sub(p2, p1, io_result);
-				io_result.scale(0.5f);
-				Math3D.add(p1, io_result, io_result);
-			} else {
-				io_result.set(i_points.get((size - 1) / 2));
-			}
-			break;
-		default:
-			throw new IllegalStateException("unknown location: " + m_alignment);
-		}
-
-		return io_result;
-	}
-
-	/**
 	 * {@inheritDoc}
 	 * 
 	 * @see org.eclipse.draw2d.Locator#relocate(org.eclipse.draw2d.IFigure)
 	 */
+	@Override
 	public void relocate(IFigure i_target) {
 
-		List<IVector3f> points = m_connection.getPoints3D();
+		super.relocate(i_target);
+
+		List<IVector3f> points = getConnection().getPoints3D();
 		RotatableDecoration3D arrow = (RotatableDecoration3D) i_target;
 
-		IVector3f location = getLocation(points, null);
-		arrow.getPosition3D().setLocation3D(location);
-
-		if (m_alignment == Alignment.SOURCE)
+		if (getAlignment() == Alignment.SOURCE)
 			arrow.setReferencePoint3D(points.get(1));
-		else if (m_alignment == Alignment.TARGET)
+		else if (getAlignment() == Alignment.TARGET)
 			arrow.setReferencePoint3D(points.get(points.size() - 2));
 	}
 }

Added: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/BorderAnchor3D.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/BorderAnchor3D.java	                        (rev 0)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/BorderAnchor3D.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -0,0 +1,369 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others,
+ * Copyright (c) 2008 Jens von Pilgrim and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    IBM Corporation - initial API and implementation of 2D version
+ *    Jens von Pilgrim - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.draw3d;
+
+import java.util.logging.Logger;
+
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.geometry.Point;
+import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.draw3d.geometry.BoundingBoxImpl;
+import org.eclipse.draw3d.geometry.IBoundingBox;
+import org.eclipse.draw3d.geometry.IVector3f;
+import org.eclipse.draw3d.geometry.Math3D;
+import org.eclipse.draw3d.geometry.Vector3f;
+import org.eclipse.draw3d.geometry.Vector3fImpl;
+import org.eclipse.draw3d.util.Draw3DCache;
+
+/**
+ * 3D version of {@link org.eclipse.draw2d.ChopboxAnchor}.
+ * 
+ * @author IBM Corporation (original 2D version)
+ * @author Jens von Pilgrim
+ * @version $Revision: 284 $
+ * @since 31.10.2007
+ * @see org.eclipse.draw2d.ChopboxAnchor
+ */
+public class BorderAnchor3D extends AbstractConnectionAnchor3D {
+
+	@SuppressWarnings("unused")
+	private static final Logger log =
+		Logger.getLogger(BorderAnchor3D.class.getName());
+
+	private ISurface m_surface;
+
+	private Locator1D m_xLocator;
+
+	private Locator1D m_yLocator;
+
+	private Locator1D m_zLocator;
+
+	/**
+	 * Constructs a new ChopboxAnchor.
+	 */
+	protected BorderAnchor3D() {
+		// nothing to initialize
+	}
+
+	/**
+	 * Constructs a border anchor with the given <i>owner</i> figure that
+	 * positions the connection endpoint in the center of the owner.
+	 * 
+	 * @param owner the owner figure
+	 * @since 2.0
+	 */
+	public BorderAnchor3D(IFigure owner) {
+		this(owner, new Locator1D.Relative(0.5f), new Locator1D.Relative(0.5f),
+			new Locator1D.Relative(0.5f));
+	}
+
+	/**
+	 * Creates a new anchor with the given 1D locators for the X, Y and Z axes.
+	 * 
+	 * @param i_owner the owner of this anchor
+	 * @param i_xLocator the X axis locator
+	 * @param i_yLocator the Y axis locator
+	 * @param i_zLocator the Z axis locator
+	 */
+	public BorderAnchor3D(IFigure i_owner, Locator1D i_xLocator,
+			Locator1D i_yLocator, Locator1D i_zLocator) {
+
+		super(i_owner);
+
+		if (i_xLocator == null)
+			throw new NullPointerException("i_xLocator must not be null");
+
+		if (i_yLocator == null)
+			throw new NullPointerException("i_yLocator must not be null");
+
+		if (i_zLocator == null)
+			throw new NullPointerException("i_zLocator must not be null");
+
+		m_xLocator = i_xLocator;
+		m_yLocator = i_yLocator;
+		m_zLocator = i_zLocator;
+	}
+
+	/**
+	 * @param reference
+	 * @param absoluteMode used in 2D mode to translate owner to absolute. In 3D
+	 *            mode this is done when converting the location to 3D. (have I
+	 *            heard someone whisper "this is a hack"?)
+	 * @return
+	 */
+	private Point doGetLocation(Point reference, boolean absoluteMode) {
+
+		// TODO: this is buggy
+		Rectangle r = Rectangle.SINGLETON;
+		r.setBounds(getBox());
+		r.translate(-1, -1);
+		r.resize(1, 1);
+
+		if (absoluteMode)
+			getOwner().translateToAbsolute(r);
+		float centerX = r.x + 0.5f * r.width;
+		float centerY = r.y + 0.5f * r.height;
+
+		if (r.isEmpty() || reference == null
+			|| (reference.x == (int) centerX && reference.y == (int) centerY)) {
+			return new Point((int) centerX, (int) centerY); // This avoids
+			// divide-by-zero
+		}
+
+		float dx = reference.x - centerX;
+		float dy = reference.y - centerY;
+
+		// r.width, r.height, dx, and dy are guaranteed to be non-zero.
+		float scale =
+			0.5f / Math.max(Math.abs(dx) / r.width, Math.abs(dy) / r.height);
+
+		dx *= scale;
+		dy *= scale;
+		centerX += dx;
+		centerY += dy;
+
+		return new Point(Math.round(centerX), Math.round(centerY));
+	}
+
+	private Vector3f doGetReferencePoint3D(IFigure3D i_owner3D,
+		Vector3f io_result) {
+
+		Vector3f result = io_result;
+		if (result == null)
+			result = new Vector3fImpl();
+
+		Vector3f size = Draw3DCache.getVector3f();
+		try {
+			IBoundingBox boundingBox = getBounds3D();
+			boundingBox.getSize(size);
+
+			// bounding box is a dot
+			if (size.lengthSquared() == 0) {
+				boundingBox.getCenter(result);
+				return result;
+			}
+
+			result.setX(m_xLocator.getLocation(size.getX()));
+			result.setY(m_yLocator.getLocation(size.getY()));
+			result.setZ(m_zLocator.getLocation(size.getZ()));
+
+			ISurface surface = getSurface();
+			surface.getWorldLocation(result, result);
+
+			return result;
+		} finally {
+			Draw3DCache.returnVector3f(size);
+		}
+
+	}
+
+	/**
+	 * Returns the 3D bounding box of this ChopboxAnchor's owner. Subclasses can
+	 * override this method to adjust the box the anchor can be placed on.
+	 * 
+	 * @return the bounds of this ChopboxAnchor's owner
+	 * @throws IllegalStateException if no 3D bounding box can be determined
+	 */
+	protected IBoundingBox getBounds3D() {
+
+		IFigure owner = getOwner();
+		if (owner instanceof IFigure3D) {
+			IFigure3D owner3D = (IFigure3D) owner;
+			return owner3D.getBounds3D();
+		} else {
+			Vector3f origin3D = Draw3DCache.getVector3f();
+			Vector3f tmp = Draw3DCache.getVector3f();
+			Vector3f size3D = Draw3DCache.getVector3f();
+
+			try {
+				IFigure3D host = Figure3DHelper.getAncestor3D(owner);
+				if (host == null)
+					throw new IllegalStateException("no 3D host found");
+
+				ISurface surface = host.getSurface();
+
+				Rectangle bounds = owner.getBounds();
+				Point bl = bounds.getBottomLeft();
+				Point tr = bounds.getTopRight();
+
+				surface.getWorldLocation(bl, origin3D);
+				surface.getWorldLocation(tr, tmp);
+
+				Math3D.sub(tmp, origin3D, size3D);
+				return new BoundingBoxImpl(origin3D, size3D);
+			} finally {
+				Draw3DCache.returnVector3f(origin3D, tmp, size3D);
+			}
+		}
+	}
+
+	/**
+	 * Returns the 2D bounds of this ChopboxAnchor's owner. Subclasses can
+	 * override this method to adjust the box the anchor can be placed on. For
+	 * instance, the owner figure may have a drop shadow that should not be
+	 * included in the box.
+	 * <p>
+	 * Copied from original {@link org.eclipse.draw2d.ChopboxAnchor}.
+	 * </p>
+	 * 
+	 * @return the 2D bounds of this ChopboxAnchor's owner
+	 */
+	protected Rectangle getBox() {
+		return getOwner().getBounds();
+	}
+
+	/**
+	 * Gets a Rectangle from {@link #getBox()} and returns the Point where a
+	 * line from the center of the Rectangle to the Point <i>reference</i>
+	 * intersects the Rectangle.
+	 * <p>
+	 * Copied from original
+	 * {@link org.eclipse.draw2d.ChopboxAnchor#getLocation(Point)}.
+	 * </p>
+	 * 
+	 * @param reference The reference point
+	 * @return The anchor location
+	 */
+	@Override
+	public Point getLocation(Point reference) {
+		return doGetLocation(reference, true);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.draw3d.AbstractConnectionAnchor3D#getLocation3D(IVector3f,
+	 *      Vector3f)
+	 */
+	@Override
+	public IVector3f getLocation3D(IVector3f i_reference, Vector3f io_result) {
+
+		Vector3f result = io_result;
+		if (result == null)
+			result = new Vector3fImpl();
+
+		Vector3f localReference = Draw3DCache.getVector3f();
+		Vector3f rayDirection = Draw3DCache.getVector3f();
+		try {
+			if (getOwner() instanceof IFigure3D) {
+				IFigure3D owner3D = (IFigure3D) getOwner();
+				doGetReferencePoint3D(owner3D, localReference);
+
+				Math3D.sub(localReference, i_reference, rayDirection);
+				Math3D.normalise(rayDirection, rayDirection);
+
+				float distance =
+					owner3D.getDistance(i_reference, rayDirection, null);
+
+				Math3D.getLocation(i_reference, rayDirection, distance, result);
+			} else { // 2D owner
+				Point reference = getReferencePoint();
+
+				ISurface surface = getSurface();
+				surface.getWorldLocation(reference, result);
+			}
+
+			return result;
+		} finally {
+			Draw3DCache.returnVector3f(localReference, rayDirection);
+		}
+	}
+
+	/**
+	 * Returns the anchor's reference point. In the case of the ChopboxAnchor,
+	 * this is the center of the anchor's owner. Copied from original
+	 * {@link org.eclipse.draw2d.ChopboxAnchor}.
+	 * 
+	 * @return The reference point
+	 */
+	@Override
+	public Point getReferencePoint() {
+
+		Point reference = new Point(getBox().getTopLeft());
+		reference.x += (int) m_xLocator.getLocation(getBox().width);
+		reference.y += (int) m_yLocator.getLocation(getBox().height);
+
+		getOwner().translateToAbsolute(reference);
+		return reference;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.draw3d.ConnectionAnchor3D#getReferencePoint3D(Vector3f)
+	 */
+	@Override
+	public Vector3f getReferencePoint3D(Vector3f io_result) {
+
+		IFigure owner = getOwner();
+		if (owner == null)
+			return null;
+
+		Vector3f result = io_result;
+		if (result == null)
+			result = new Vector3fImpl();
+
+		if (owner instanceof IFigure3D) {
+			doGetReferencePoint3D((IFigure3D) owner, result);
+		} else {
+			Point ref2D = getReferencePoint();
+			IFigure3D host = Figure3DHelper.getAncestor3D(owner);
+
+			ISurface surface = host.getSurface();
+			surface.getWorldLocation(ref2D, result);
+		}
+
+		return result;
+	}
+
+	/**
+	 * Returns a surface for the owner of this anchor. If is not a 3D figure,
+	 * its closest 3D ancestor will be used to get a surface. If that figure
+	 * does not have a surface, one will be created and cached for it. If the
+	 * owner does not have a 3D ancestor, <code>null</code> is returned.
+	 * 
+	 * @return a surface for the owner of this anchor or <code>null</code> if
+	 *         the owner does not have a 3D ancestor
+	 */
+	protected ISurface getSurface() {
+
+		IFigure figure = getOwner();
+		IFigure3D figure3D = Figure3DHelper.getAncestor3D(figure);
+		if (figure3D == null)
+			return null;
+
+		ISurface surface = figure3D.getSurface();
+		if (surface != null)
+			return surface;
+
+		if (m_surface == null)
+			m_surface = new FigureSurface(figure3D);
+
+		return m_surface;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.draw2d.AbstractConnectionAnchor#setOwner(org.eclipse.draw2d.IFigure)
+	 */
+	@Override
+	public void setOwner(IFigure i_owner) {
+
+		if (i_owner != getOwner())
+			m_surface = null;
+
+		super.setOwner(i_owner);
+	}
+
+}

Added: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ConnectionLocator3D.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ConnectionLocator3D.java	                        (rev 0)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ConnectionLocator3D.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Jens von Pilgrim and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kristian Duske - initial API and implementation
+ *    Jens von Pilgrim - initial API and implementation
+ ******************************************************************************/
+
+package org.eclipse.draw3d;
+
+import java.util.List;
+
+import org.eclipse.draw2d.DelegatingLayout;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Locator;
+import org.eclipse.draw3d.geometry.IVector3f;
+import org.eclipse.draw3d.geometry.Math3D;
+import org.eclipse.draw3d.geometry.Vector3f;
+import org.eclipse.draw3d.geometry.Vector3fImpl;
+import org.eclipse.draw3d.util.Draw3DCache;
+
+/**
+ * Locator used to place an {@link IFigure3D} on a {@link Connection3D}. The
+ * figure can be placed at the source or target end of the connection figure.
+ * The default connection implementation uses a {@link DelegatingLayout} which
+ * requires locators.
+ * 
+ * @author Kristian Duske
+ * @version $Revision: 248 $
+ * @since 17.05.2008
+ */
+public class ConnectionLocator3D implements Locator {
+
+	/**
+	 * Enumerates the alignment options for a 3D locator.
+	 * 
+	 * @author Kristian Duske
+	 * @version $Revision: 248 $
+	 * @since 19.05.2008
+	 */
+	public static enum Alignment {
+		/**
+		 * The middle of the connection.
+		 */
+		MIDDLE,
+		/**
+		 * The source of the connection.
+		 */
+		SOURCE,
+		/**
+		 * The target of the connection.
+		 */
+		TARGET
+	}
+
+	private Alignment m_alignment;
+
+	private Connection3D m_connection;
+
+	/**
+	 * Creates a new locator for the given connection and with the given
+	 * alignment.
+	 * 
+	 * @param i_connection the connection associated with the locator
+	 * @param i_alignment the alignment of the locator
+	 * @throws NullPointerException if either of the given arguments is
+	 *             <code>null</code>
+	 */
+	public ConnectionLocator3D(Connection3D i_connection, Alignment i_alignment) {
+
+		if (i_connection == null)
+			throw new NullPointerException("i_connection must not be null");
+
+		if (i_alignment == null)
+			throw new NullPointerException("i_alignment must not be null");
+
+		m_connection = i_connection;
+		m_alignment = i_alignment;
+	}
+
+	/**
+	 * Returns the alignment of this locator.
+	 * 
+	 * @return the alignment of this locator
+	 */
+	public Alignment getAlignment() {
+
+		return m_alignment;
+	}
+
+	/**
+	 * Returns the connection associated with this locator.
+	 * 
+	 * @return the connection associated with this locator
+	 */
+	public Connection3D getConnection() {
+
+		return m_connection;
+	}
+
+	/**
+	 * Returns the location of a decoration depending on the locator's
+	 * alignment.
+	 * 
+	 * @param i_points the point list
+	 * @param io_result the result vector, can be <code>null</code>
+	 * @return the location
+	 * @throws NullPointerException if the given point list is <code>null</code>
+	 */
+	protected IVector3f getLocation(List<IVector3f> i_points, Vector3f io_result) {
+
+		if (i_points == null)
+			throw new NullPointerException("i_points must not be null");
+
+		Vector3f result = io_result;
+		if (result == null)
+			result = new Vector3fImpl();
+
+		int size = i_points.size();
+		switch (m_alignment) {
+		case SOURCE:
+			result.set(i_points.get(0));
+			break;
+		case TARGET:
+			result.set(i_points.get(size - 1));
+			break;
+		case MIDDLE:
+			if ((size % 2) == 0) {
+				int i = size / 2;
+				IVector3f p1 = i_points.get(i - 1);
+				IVector3f p2 = i_points.get(i);
+				Math3D.sub(p2, p1, result);
+				result.scale(0.5f);
+				Math3D.add(p1, result, result);
+			} else {
+				result.set(i_points.get((size - 1) / 2));
+			}
+			break;
+		default:
+			throw new IllegalStateException("unknown location: " + m_alignment);
+		}
+
+		return result;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.draw2d.Locator#relocate(org.eclipse.draw2d.IFigure)
+	 */
+	public void relocate(IFigure i_target) {
+
+		IFigure3D target3D = (IFigure3D) i_target;
+
+		Vector3f location = Draw3DCache.getVector3f();
+		try {
+			List<IVector3f> points = m_connection.getPoints3D();
+
+			getLocation(points, location);
+			target3D.getPosition3D().setLocation3D(location);
+		} finally {
+			Draw3DCache.returnVector3f(location);
+		}
+	}
+}

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/Export3DOperation.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/Export3DOperation.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/Export3DOperation.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -75,7 +75,7 @@
 			rootFigure.paint(dummy);
 		} finally {
 			renderContext.setGraphics3D(g3dSave);
-			renderContext.clearDisplayManager(); // was in try block only?!
+			renderContext.clearDisplayListManager(); // was in try block only?!
 		}
 	}
 

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/Figure3D.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/Figure3D.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/Figure3D.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -12,6 +12,7 @@
 
 import java.util.EnumSet;
 import java.util.List;
+import java.util.Map;
 import java.util.logging.Logger;
 
 import org.eclipse.draw2d.ConnectionLayer;
@@ -36,7 +37,6 @@
 import org.eclipse.draw3d.geometry.IPosition3D.PositionHint;
 import org.eclipse.draw3d.geometryext.SyncedVector3f;
 import org.eclipse.draw3d.geometryext.SynchronizedPosition3DImpl;
-import org.eclipse.draw3d.picking.Query;
 import org.eclipse.draw3d.util.Draw3DCache;
 import org.eclipse.swt.graphics.Font;
 
@@ -307,9 +307,11 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.picking.Query)
+	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.geometry.IVector3f,
+	 *      org.eclipse.draw3d.geometry.IVector3f, java.util.Map)
 	 */
-	public float getDistance(Query i_query) {
+	public float getDistance(IVector3f i_rayOrigin, IVector3f i_rayDirection,
+		Map<Object, Object> i_context) {
 
 		return Float.NaN;
 	}
@@ -408,7 +410,11 @@
 	 */
 	public IScene getScene() {
 
-		return Figure3DHelper.getAncestor3D(getParent()).getScene();
+		IFigure p = getParent();
+		if (p == null)
+			return null;
+
+		return Figure3DHelper.getAncestor3D(p).getScene();
 	}
 
 	/**

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/LightweightSystem3D.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/LightweightSystem3D.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/LightweightSystem3D.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -13,6 +13,7 @@
 import java.util.ArrayList;
 import java.util.EnumSet;
 import java.util.List;
+import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -43,7 +44,6 @@
 import org.eclipse.draw3d.graphics3d.Graphics3D;
 import org.eclipse.draw3d.graphics3d.Graphics3DDraw;
 import org.eclipse.draw3d.picking.Picker;
-import org.eclipse.draw3d.picking.Query;
 import org.eclipse.draw3d.util.ColorConverter;
 import org.eclipse.draw3d.util.DebugPrimitives;
 import org.eclipse.draw3d.util.Draw3DCache;
@@ -266,9 +266,11 @@
 		/**
 		 * {@inheritDoc}
 		 * 
-		 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.picking.Query)
+		 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.geometry.IVector3f,
+		 *      org.eclipse.draw3d.geometry.IVector3f, java.util.Map)
 		 */
-		public float getDistance(Query i_query) {
+		public float getDistance(IVector3f i_rayOrigin,
+			IVector3f i_rayDirection, Map<Object, Object> i_context) {
 
 			return Float.NaN;
 		}
@@ -479,8 +481,7 @@
 			IVector3f i_delta) {
 
 			if (log.isLoggable(Level.WARNING)) {
-				log
-					.warning("positionChanged on root figure, this must not happen"); //$NON-NLS-1$
+				log.warning("positionChanged on root figure, this must not happen"); //$NON-NLS-1$
 			}
 
 		}

Added: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/Locator1D.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/Locator1D.java	                        (rev 0)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/Locator1D.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Jens von Pilgrim and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Kristian Duske - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.draw3d;
+
+/**
+ * A locator that calculates the location of a point along a singular axis.
+ * 
+ * @author Kristian Duske
+ * @version $Revision$
+ * @since 20.09.2009
+ */
+public interface Locator1D {
+
+	/**
+	 * Absolute locator that locates a point at a given fixed distance from 0 or
+	 * the length given to {@link #getLocation(float)}.
+	 * 
+	 * @author Kristian Duske
+	 * @version $Revision$
+	 * @since 20.09.2009
+	 */
+	public class Absolute implements Locator1D {
+
+		/**
+		 * Position at the beginning or end of the axis.
+		 * 
+		 * @author Kristian Duske
+		 * @version $Revision$
+		 * @since 20.09.2009
+		 */
+		public enum Position {
+			/**
+			 * Position at the beginning.
+			 */
+			BEGINNING,
+			/**
+			 * Position at the end.
+			 */
+			END
+		}
+
+		private float m_offset;
+
+		private Absolute.Position m_position;
+
+		/**
+		 * Creates a new absolute locator at the given position and offset.
+		 * 
+		 * @param i_position the position
+		 * @param i_offset the offset
+		 */
+		public Absolute(Position i_position, float i_offset) {
+
+			if (i_position == null)
+				throw new NullPointerException("i_position must not be null");
+
+			m_position = i_position;
+			m_offset = Math.max(0, i_offset);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.draw3d.BorderAnchor3D.RelativeLocator1D#getLocation(float)
+		 */
+		public float getLocation(float i_length) {
+
+			if (m_position == Position.BEGINNING)
+				return Math.min(m_offset, i_length);
+
+			return Math.max(0, i_length - m_offset);
+		}
+
+	}
+
+	/**
+	 * A locator that positions a point at a relative distance.
+	 * 
+	 * @author Kristian Duske
+	 * @version $Revision$
+	 * @since 20.09.2009
+	 */
+	public class Relative implements Locator1D {
+
+		private float m_weight;
+
+		/**
+		 * Creates a new relative locator with the given weight. The weight
+		 * specifies the relative offset between 0 and 1.
+		 * 
+		 * @param i_weight the weight, must be greater or equal to 0 and less or
+		 *            equal to 1
+		 */
+		public Relative(float i_weight) {
+
+			if (i_weight < 0 || i_weight > 1)
+				throw new IllegalArgumentException(
+					"weight must be 0 <= weight <= 1, was " + i_weight);
+
+			m_weight = i_weight;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @see org.eclipse.draw3d.Locator1D#getLocation(float)
+		 */
+		public float getLocation(float i_length) {
+
+			return m_weight * i_length;
+		}
+
+	}
+
+	/**
+	 * Returns the new location a point in relation to the given length of the
+	 * axis.
+	 * 
+	 * @param i_length the length of the axis
+	 * @return the locationO
+	 */
+	public float getLocation(float i_length);
+}
\ No newline at end of file

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/PolylineConnection3D.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/PolylineConnection3D.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/PolylineConnection3D.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -27,7 +27,7 @@
 import org.eclipse.draw2d.RotatableDecoration;
 import org.eclipse.draw2d.RoutingListener;
 import org.eclipse.draw2d.geometry.Rectangle;
-import org.eclipse.draw3d.ArrowLocator3D.Alignment;
+import org.eclipse.draw3d.ConnectionLocator3D.Alignment;
 import org.eclipse.draw3d.geometry.Vector3fImpl;
 
 /**

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/RenderContext.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/RenderContext.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/RenderContext.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -23,29 +23,12 @@
 import org.eclipse.swt.opengl.GLCanvas;
 
 /**
- * The render state encapsulates information about the current render pass and
- * also collects transparent objects that need to be rendered last.
- * <p>
- * Note on transparent and superimposed object: An object becomes transparent by
- * firstly setting its color alpha to a value less 255 and by secondly adding it
- * to the list of transparent objects via
- * {@link #addTransparentObject(TransparentObject)}. The overall strategy is to
- * firstly render all opaque objects, correctly sorted and drawn by OpenGL.
- * Secondly, all transparent objects are drawn (ordered by their distance to the
- * camera) in order to enable real transparency which OpenGL does not support
- * directly. A problem may occure when objects are registered as transparent
- * objects while the transparent objects are already rendered here. This may
- * occur if an transparent object is composed of other transparent objects, and
- * recursively calls their render method (which only then adds the nested
- * objecdt to the list of transparent objects here). If this case the newly
- * added transparent (nested) object is rendered directly after the object was
- * rendered in which this object is nested. The problem is that the order may be
- * corrupt, that is the nested object should have been rendered before its
- * container. This case cannot be corrected here. To prevent this, try to make
- * rendering of objects as flat as possible. Especially shapes tend to be
- * nested. In this case, simply try to prevent calling a nested shapes render
- * method from within a container shapes doRender method.
- * </p>
+ * The render context collects fragments to be rendered during a render pass,
+ * sorts them appropriately (by render type and distance from the camera) and
+ * renders them after the actual painting of the figures is finished. It also
+ * functions as a container for some objects that figures may need when they
+ * render themselves, for example the {@link Graphics3D} instance, the
+ * {@link DisplayListManager} and the {@link IScene}.
  * 
  * @author Jens von Pilgrim
  * @version $Revision$
@@ -124,7 +107,7 @@
 	/**
 	 * Clears the display manager for the current g3d instance.
 	 */
-	public void clearDisplayManager() {
+	public void clearDisplayListManager() {
 		if (getGraphics3D() == null) {
 			throw new IllegalStateException("no graphics3D intance set yet");
 		}
@@ -138,23 +121,14 @@
 	 */
 	public synchronized void dispose() {
 
-		for (DisplayListManager displayListManager : m_displayListManagers
-			.values()) {
-			try {
-				displayListManager.dispose();
-			} catch (Exception ex) {
-				log.warning("Error disposing dipslay list manager: " + ex);
-			}
-		}
 		try {
+			for (DisplayListManager manager : m_displayListManagers.values())
+				manager.dispose();
+
 			m_displayListManagers.clear();
-		} catch (Exception ex) {
-			log.warning("Error clearing dispy list manager map: " + ex);
-		}
-		try {
 			m_g3d.dispose();
 		} catch (Exception ex) {
-			log.warning("Error disposing current graphics 3D instance: " + ex);
+			log.warning("Error disposing render context: " + ex);
 		}
 	}
 

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ShapeDecoration.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ShapeDecoration.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ShapeDecoration.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -16,8 +16,6 @@
 import org.eclipse.draw3d.geometry.Math3D;
 import org.eclipse.draw3d.geometry.Vector3f;
 import org.eclipse.draw3d.geometry.Vector3fImpl;
-import org.eclipse.draw3d.shapes.NullShape;
-import org.eclipse.draw3d.shapes.Shape;
 import org.eclipse.draw3d.util.Draw3DCache;
 
 /**
@@ -27,31 +25,11 @@
  * @version $Revision$
  * @since 18.05.2008
  */
-/**
- * ShapeDecoration
- * There should really be more documentation here.
- *
- * @author 	Jens von Pilgrim
- * @version	$Revision$
- * @since 	Aug 7, 2009
- */	
-public class ShapeDecoration extends ShapeFigure3D implements
+public abstract class ShapeDecoration extends ShapeFigure3D implements
 		RotatableDecoration3D {
 
 	private Vector3fImpl m_lastReference = new Vector3fImpl(0, 0, 0);
 
-	
-	/** 
-	 * {@inheritDoc}
-	 * @see org.eclipse.draw3d.ShapeFigure3D#createShape()
-	 */
-	@Override
-	protected Shape createShape() {
-		return new NullShape();
-	}
-	
-	
-
 	/**
 	 * {@inheritDoc}
 	 * 
@@ -95,6 +73,4 @@
 			}
 		}
 	}
-
-	
 }

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ShapeFigure3D.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ShapeFigure3D.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/ShapeFigure3D.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -10,11 +10,12 @@
  ******************************************************************************/
 package org.eclipse.draw3d;
 
+import java.util.Map;
+
+import org.eclipse.draw3d.geometry.IVector3f;
 import org.eclipse.draw3d.geometry.ParaxialBoundingBox;
 import org.eclipse.draw3d.geometry.ParaxialBoundingBoxImpl;
 import org.eclipse.draw3d.geometry.Vector3f;
-import org.eclipse.draw3d.picking.Query;
-import org.eclipse.draw3d.shapes.ParaxialBoundsFigureShape;
 import org.eclipse.draw3d.shapes.Shape;
 import org.eclipse.draw3d.util.Draw3DCache;
 
@@ -44,12 +45,14 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.draw3d.Figure3D#getDistance(org.eclipse.draw3d.picking.Query)
+	 * @see org.eclipse.draw3d.Figure3D#getDistance(org.eclipse.draw3d.geometry.IVector3f,
+	 *      org.eclipse.draw3d.geometry.IVector3f, java.util.Map)
 	 */
 	@Override
-	public float getDistance(Query i_query) {
+	public float getDistance(IVector3f i_rayOrigin, IVector3f i_rayDirection,
+		Map<Object, Object> i_context) {
 
-		return getShape().getDistance(i_query);
+		return getShape().getDistance(i_rayOrigin, i_rayDirection, i_context);
 	}
 
 	/**
@@ -101,8 +104,7 @@
 		if (m_shape == null) {
 			m_shape = createShape();
 			if (m_shape == null) {
-				throw new NullPointerException(
-					"created shape mmust not be null");
+				throw new NullPointerException("created shape must not be null");
 			}
 		}
 

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/camera/AbstractCamera.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/camera/AbstractCamera.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/camera/AbstractCamera.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -12,8 +12,9 @@
  ******************************************************************************/
 package org.eclipse.draw3d.camera;
 
+import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.List;
-import java.util.Vector;
 
 /**
  * This abstract camera is to be subclassed by concrete cameras.
@@ -25,57 +26,59 @@
  */
 public abstract class AbstractCamera implements ICamera {
 
-    private final List<ICameraListener> m_listeners;
+	private final List<ICameraListener> m_listeners;
 
-    /**
-     * @param i_lightweightSystem3D
-     */
-    public AbstractCamera() {
+	/**
+	 * @param i_lightweightSystem3D
+	 */
+	public AbstractCamera() {
 
-        m_listeners = new Vector<ICameraListener>(3);
-    }
+		m_listeners = new LinkedList<ICameraListener>();
+	}
 
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.eclipse.draw3d.camera.ICamera#addCameraListener(org.eclipse.draw3d.camera.ICameraListener)
-     */
-    public void addCameraListener(ICameraListener i_listener) {
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.draw3d.camera.ICamera#addCameraListener(org.eclipse.draw3d.camera.ICameraListener)
+	 */
+	public void addCameraListener(ICameraListener i_listener) {
 
-        if (!m_listeners.contains(i_listener))
-            m_listeners.add(i_listener);
-    }
+		if (!m_listeners.contains(i_listener))
+			m_listeners.add(i_listener);
+	}
 
-    /**
-     * Notifies all camera listeners that this camera has changed.
-     */
-    protected void fireCameraChanged() {
+	/**
+	 * Notifies all camera listeners that this camera has changed.
+	 */
+	protected void fireCameraChanged() {
 
-        for (ICameraListener listener : m_listeners)
-            listener.cameraChanged();
-    }
+		for (ICameraListener listener : m_listeners)
+			listener.cameraChanged();
+	}
 
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.eclipse.draw3d.camera.ICamera#removeCameraListener(org.eclipse.draw3d.camera.ICameraListener)
-     */
-    public void removeCameraListener(ICameraListener i_listener) {
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.draw3d.camera.ICamera#removeCameraListener(org.eclipse.draw3d.camera.ICameraListener)
+	 */
+	public void removeCameraListener(ICameraListener i_listener) {
 
-        if (m_listeners.contains(i_listener))
-            m_listeners.remove(i_listener);
-    }
+		if (m_listeners.contains(i_listener))
+			m_listeners.remove(i_listener);
+	}
 
-    /**
-     * {@inheritDoc}
-     * 
-     * @see org.eclipse.draw3d.camera.ICamera#transferListeners(org.eclipse.draw3d.camera.ICamera)
-     */
-    public void transferListeners(ICamera i_newCamera) {
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * @see org.eclipse.draw3d.camera.ICamera#transferListeners(org.eclipse.draw3d.camera.ICamera)
+	 */
+	public void transferListeners(ICamera i_newCamera) {
 
-        for (ICameraListener listener : m_listeners) {
-            removeCameraListener(listener);
-            i_newCamera.addCameraListener(listener);
-        }
-    }
+		for (Iterator<ICameraListener> i = m_listeners.iterator(); i.hasNext();) {
+			ICameraListener listener = i.next();
+
+			i.remove();
+			i_newCamera.addCameraListener(listener);
+		}
+	}
 }

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/camera/FirstPersonCamera.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/camera/FirstPersonCamera.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/camera/FirstPersonCamera.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -208,7 +208,7 @@
 	/**
 	 * Distance of the far clipping plane.
 	 */
-	protected int m_far = 40000;
+	protected int m_far = 10000;
 
 	/**
 	 * The field of vision angle in degrees.
@@ -220,7 +220,7 @@
 	/**
 	 * Distance of the near clipping plane.
 	 */
-	protected int m_near = 1;
+	protected int m_near = 100;
 
 	/**
 	 * The current camera position.
@@ -293,9 +293,9 @@
 	@Override
 	protected void fireCameraChanged() {
 
-		super.fireCameraChanged();
 		m_matricesValid = false;
 		m_cachedProjection.invalidate();
+		super.fireCameraChanged();
 	}
 
 	private float getAspect() {
@@ -515,7 +515,11 @@
 			tmp.transform(rot);
 			Math3D.add(tmp, i_center, m_position);
 
-			rotate(0, i_vAngle, i_hAngle);
+			// view direction and reference vectors
+			m_viewDir.transform(rot);
+			m_right.transform(rot);
+			m_up.transform(rot);
+
 			fireCameraChanged();
 		} finally {
 			Math3DCache.returnMatrix4f(rot);
@@ -570,8 +574,8 @@
 	 */
 	public Point project(IVector3f i_wLocation, Point io_result) {
 
-		return project(i_wLocation.getX(), i_wLocation.getY(), i_wLocation
-			.getZ(), io_result);
+		return project(i_wLocation.getX(), i_wLocation.getY(),
+			i_wLocation.getZ(), io_result);
 	}
 
 	/**
@@ -698,8 +702,8 @@
 			calculateInversionMatrix(i_modelMatrix, inversion);
 			result.transform(inversion);
 
-			m_cachedProjection.update(result.getX(), result.getY(), result
-				.getZ(), i_mx, i_my, i_depth, i_modelMatrix);
+			m_cachedProjection.update(result.getX(), result.getY(),
+				result.getZ(), i_mx, i_my, i_depth, i_modelMatrix);
 
 			return result;
 		} finally {

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/camera/RestrictedFirstPersonCamera.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/camera/RestrictedFirstPersonCamera.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/camera/RestrictedFirstPersonCamera.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -12,11 +12,10 @@
 
 import java.util.logging.Logger;
 
-import org.eclipse.draw3d.geometry.Math3DCache;
 import org.eclipse.draw3d.geometry.IVector3f;
 import org.eclipse.draw3d.geometry.Math3D;
+import org.eclipse.draw3d.geometry.Math3DCache;
 import org.eclipse.draw3d.geometry.Matrix4f;
-import org.eclipse.draw3d.geometry.Vector3f;
 
 /**
  * A camera that implements a first person strategy and that restricts movement
@@ -31,8 +30,8 @@
 	private static final float HALF_PI = (float) Math.PI / 2;
 
 	@SuppressWarnings("unused")
-	private static Logger log = Logger
-			.getLogger(RestrictedFirstPersonCamera.class.getName());
+	private static Logger log =
+		Logger.getLogger(RestrictedFirstPersonCamera.class.getName());
 
 	/**
 	 * {@inheritDoc}
@@ -66,25 +65,31 @@
 		boolean allowPitch = Math.abs(currentPitch + i_vAngle) < HALF_PI;
 
 		Matrix4f rot = Math3DCache.getMatrix4f();
-		Vector3f tmp = Math3DCache.getVector3f();
 		try {
 			rot.setIdentity();
 			if (i_hAngle != 0)
-				Math3D.rotate(i_hAngle, m_up, rot, rot);
+				Math3D.rotate(i_hAngle, UP_REF, rot, rot);
 
 			if (i_vAngle != 0 && allowPitch)
 				Math3D.rotate(i_vAngle, m_right, rot, rot);
 
 			// camera position
-			Math3D.sub(m_position, i_center, tmp);
-			tmp.transform(rot);
-			Math3D.add(tmp, i_center, m_position);
+			Math3D.sub(m_position, i_center, m_position);
+			m_position.transform(rot);
+			Math3D.add(m_position, i_center, m_position);
 
-			rotate(0, i_vAngle, i_hAngle);
+			// view direction and reference vectors
+			m_viewDir.transform(rot);
+
+			Math3D.cross(m_viewDir, UP_REF, m_right);
+			Math3D.normalise(m_right, m_right);
+
+			Math3D.cross(m_right, m_viewDir, m_up);
+			Math3D.normalise(m_up, m_up);
+
 			fireCameraChanged();
 		} finally {
 			Math3DCache.returnMatrix4f(rot);
-			Math3DCache.returnVector3f(tmp);
 		}
 	}
 

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/picking/Pickable.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/picking/Pickable.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/picking/Pickable.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -10,6 +10,9 @@
  ******************************************************************************/
 package org.eclipse.draw3d.picking;
 
+import java.util.Map;
+
+import org.eclipse.draw3d.geometry.IVector3f;
 import org.eclipse.draw3d.geometry.ParaxialBoundingBox;
 
 /**
@@ -34,13 +37,15 @@
 	 * in which p is the point of intersection, if any. If the given ray does
 	 * not intersect with this object, {@link Float#NaN} is returned.
 	 * 
-	 * @param i_query the current picking query
+	 * @param i_rayOrigin the origin of the picking ray
+	 * @param i_rayDirection the direction of the picking ray
+	 * @param i_context a map that can be used to store context information if
+	 *            not <code>null</code>
 	 * @return the scalar value as described above or {@link Float#NaN} if the
 	 *         given ray does not intersect with this object
-	 * @throws IllegalArgumentException if the given direction vector has a
-	 *             length of zero
 	 */
-	public float getDistance(Query i_query);
+	public float getDistance(IVector3f i_rayOrigin, IVector3f i_rayDirection,
+		Map<Object, Object> i_context);
 
 	/**
 	 * Returns a paraxial (to the world coordinate system) bounding box that

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/picking/Query.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/picking/Query.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/picking/Query.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -10,7 +10,6 @@
  ******************************************************************************/
 package org.eclipse.draw3d.picking;
 
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -41,7 +40,7 @@
 	/**
 	 * This is a simple map for storing client specific data.
 	 */
-	private Map<Object, Object> m_objects;
+	private Map<Object, Object> m_context;
 
 	private IVector3f m_rayDirection;
 
@@ -112,13 +111,10 @@
 		if (parentFigure3D.equals(m_rootFigure)) {
 			if (m_debug)
 				if (i_childHit != null)
-					log
-						.info(i_childHit.getFigure3D() + " wins over parent "
-							+ i_parentFigure
-							+ " because parent is the root figure");
+					log.info(i_childHit.getFigure3D() + " wins over parent "
+						+ i_parentFigure + " because parent is the root figure");
 				else
-					log
-						.info("neither parent nor child was hit, parent is root");
+					log.info("neither parent nor child was hit, parent is root");
 
 			return i_childHit;
 		}
@@ -144,7 +140,9 @@
 
 		HitImpl hit = i_childHit;
 		if (accept(parentFigure3D, m_search) || searchResult != null) {
-			float realDistance = parentFigure3D.getDistance(this);
+			float realDistance =
+				parentFigure3D.getDistance(m_rayOrigin, m_rayDirection,
+					m_context);
 			if (!Float.isNaN(realDistance)
 				&& (hit == null || realDistance < hit.getDistance())) {
 				if (searchResult == null)
@@ -274,10 +272,10 @@
 		if (i_key == null)
 			throw new NullPointerException("i_key must not be null");
 
-		if (m_objects == null)
+		if (m_context == null)
 			return null;
 
-		return m_objects.get(i_key);
+		return m_context.get(i_key);
 	}
 
 	private float getBoundingBoxDistance(IFigure3D i_figure) {
@@ -344,37 +342,6 @@
 	}
 
 	/**
-	 * Caches the given object in this query under the given key. This can be
-	 * used by objects implementing {@link Pickable} to store information that
-	 * is valid for the duration of a query, for example helper objects or
-	 * derived mathematical variables.
-	 * <p>
-	 * If the given object is <code>null</code>, it will be removed from the
-	 * cache.
-	 * </p>
-	 * 
-	 * @param i_key the key to store the object under
-	 * @param i_object the object to store
-	 * @throws NullPointerException if the given key is <code>null</code>
-	 */
-	public void set(Object i_key, Object i_object) {
-
-		if (i_key == null)
-			throw new NullPointerException("i_key must not be null");
-
-		if (i_object == null) {
-			if (m_objects != null)
-				m_objects.remove(i_key);
-			return;
-		}
-
-		if (m_objects == null)
-			m_objects = new HashMap<Object, Object>();
-
-		m_objects.put(i_key, i_object);
-	}
-
-	/**
 	 * Specifies whether debug mode is enabled.
 	 * 
 	 * @param i_debug <code>true</code> if debug mode should be enabled and

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CuboidFigureShape.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CuboidFigureShape.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CuboidFigureShape.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -10,11 +10,13 @@
  ******************************************************************************/
 package org.eclipse.draw3d.shapes;
 
+import java.util.Map;
+
 import org.eclipse.draw3d.IFigure3D;
 import org.eclipse.draw3d.RenderContext;
+import org.eclipse.draw3d.geometry.IVector3f;
 import org.eclipse.draw3d.geometry.ParaxialBoundingBox;
 import org.eclipse.draw3d.graphics3d.Graphics3D;
-import org.eclipse.draw3d.picking.Query;
 
 /**
  * A figure shape that renders itself as a cuboid.
@@ -59,11 +61,13 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.picking.Query)
+	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.geometry.IVector3f,
+	 *      org.eclipse.draw3d.geometry.IVector3f, java.util.Map)
 	 */
-	public float getDistance(Query i_query) {
+	public float getDistance(IVector3f i_rayOrigin, IVector3f i_rayDirection,
+		Map<Object, Object> i_context) {
 
-		return m_shape.getDistance(i_query);
+		return m_shape.getDistance(i_rayOrigin, i_rayDirection, i_context);
 	}
 
 	/**

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CuboidShape.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CuboidShape.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CuboidShape.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -11,6 +11,7 @@
  ******************************************************************************/
 package org.eclipse.draw3d.shapes;
 
+import java.util.Map;
 import java.util.logging.Logger;
 
 import org.eclipse.draw3d.DisplayListManager;
@@ -24,7 +25,6 @@
 import org.eclipse.draw3d.geometry.Vector3fImpl;
 import org.eclipse.draw3d.graphics3d.Graphics3D;
 import org.eclipse.draw3d.graphics3d.Graphics3DDraw;
-import org.eclipse.draw3d.picking.Query;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.widgets.Display;
@@ -165,14 +165,13 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.draw3d.shapes.PositionableShape#doGetDistance(org.eclipse.draw3d.picking.Query)
+	 * @see org.eclipse.draw3d.shapes.PositionableShape#doGetDistance(org.eclipse.draw3d.geometry.IVector3f,
+	 *      org.eclipse.draw3d.geometry.IVector3f, java.util.Map)
 	 */
 	@Override
-	protected float doGetDistance(Query i_query) {
+	protected float doGetDistance(IVector3f i_rayOrigin,
+		IVector3f i_rayDirection, Map<Object, Object> i_context) {
 
-		IVector3f rayOrigin = i_query.getRayOrigin();
-		IVector3f rayDirection = i_query.getRayDirection();
-
 		IVector3f[] face = new Vector3f[4];
 		float distance;
 
@@ -181,7 +180,7 @@
 				face[j] = VERTICES[FACES[i][j]];
 
 			distance =
-				Math3D.rayIntersectsPolygon(rayOrigin, rayDirection, face,
+				Math3D.rayIntersectsPolygon(i_rayOrigin, i_rayDirection, face,
 					NORMALS[i], null);
 
 			if (!Float.isNaN(distance))

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CylinderShape.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CylinderShape.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CylinderShape.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -10,8 +10,8 @@
  ******************************************************************************/
 package org.eclipse.draw3d.shapes;
 
+import java.util.HashMap;
 import java.util.Map;
-import java.util.WeakHashMap;
 
 import org.eclipse.draw3d.DisplayListManager;
 import org.eclipse.draw3d.RenderContext;
@@ -22,7 +22,6 @@
 import org.eclipse.draw3d.geometry.Vector3fImpl;
 import org.eclipse.draw3d.graphics3d.Graphics3D;
 import org.eclipse.draw3d.graphics3d.Graphics3DDraw;
-import org.eclipse.draw3d.picking.Query;
 import org.eclipse.draw3d.util.Draw3DCache;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.graphics.Color;
@@ -258,7 +257,7 @@
 	}
 
 	private static final Map<CylinderConfigKey, CylinderConfig> CONFIG_CACHE =
-		new WeakHashMap<CylinderConfigKey, CylinderConfig>();
+		new HashMap<CylinderConfigKey, CylinderConfig>();
 
 	private static final float[] TMP_F2 = new float[2];
 
@@ -447,18 +446,20 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.draw3d.shapes.PositionableShape#doGetDistance(org.eclipse.draw3d.picking.Query)
+	 * @see org.eclipse.draw3d.shapes.PositionableShape#doGetDistance(org.eclipse.draw3d.geometry.IVector3f,
+	 *      org.eclipse.draw3d.geometry.IVector3f, java.util.Map)
 	 */
 	@Override
-	protected float doGetDistance(Query i_query) {
+	protected float doGetDistance(IVector3f i_rayOrigin,
+		IVector3f i_rayDirection, Map<Object, Object> i_context) {
 
 		float radiusProportions = m_config.getRadiusProportions();
 		if (radiusProportions == 1)
-			return getCylinderDistance(i_query);
+			return getCylinderDistance(i_rayOrigin, i_rayDirection);
 		else if (radiusProportions == 0)
-			return getConeDistance(i_query);
+			return getConeDistance(i_rayOrigin, i_rayDirection);
 		else
-			return getTruncatedConeDistance(i_query);
+			return getTruncatedConeDistance(i_rayOrigin, i_rayDirection);
 	}
 
 	/**
@@ -486,68 +487,62 @@
 		}
 	}
 
-	private float getCapDistance(Query i_query) {
+	private float getCapDistance(IVector3f i_rayOrigin, IVector3f i_rayDirection) {
 
-		IVector3f rayOrigin = i_query.getRayOrigin();
-		IVector3f rayDirection = i_query.getRayDirection();
-
 		IVector3f[] bottom = m_config.getBottomVertices();
 		if (bottom.length > 1) {
 			float d =
-				Math3D.rayIntersectsPolygon(rayOrigin, rayDirection, bottom,
-					IVector3f.Z_AXIS_NEG, null);
+				Math3D.rayIntersectsPolygon(i_rayOrigin, i_rayDirection,
+					bottom, IVector3f.Z_AXIS_NEG, null);
 			if (!Float.isNaN(d))
 				return d;
 		}
 
 		IVector3f[] top = m_config.getTopVertices();
-		return Math3D.rayIntersectsPolygon(rayOrigin, rayDirection, top,
+		return Math3D.rayIntersectsPolygon(i_rayOrigin, i_rayDirection, top,
 			IVector3f.Z_AXIS, null);
 	}
 
-	private float getConeDistance(Query i_query) {
+	private float getConeDistance(IVector3f i_rayOrigin,
+		IVector3f i_rayDirection) {
 
 		// if we hit an end cap, we are done
-		float d = getCapDistance(i_query);
+		float d = getCapDistance(i_rayOrigin, i_rayDirection);
 		if (!Float.isNaN(d))
 			return d;
 
 		// it's much quicker to intersect with a cone whose apex is the
 		// origin and that extends along the positive Z axis, so translate the
 		// ray accordingly
-		Vector3f rayOrigin = Draw3DCache.getVector3f();
+		Vector3f newOrigin = Draw3DCache.getVector3f();
 		try {
-			Math3D
-				.translate(i_query.getRayOrigin(), -0.5f, -0.5f, 0, rayOrigin);
-			IVector3f rayDirection = i_query.getRayDirection();
-
-			return doGetConeDistance(rayOrigin, rayDirection, 0, 1);
+			Math3D.translate(i_rayOrigin, -0.5f, -0.5f, 0, newOrigin);
+			return doGetConeDistance(newOrigin, i_rayDirection, 0, 1);
 		} finally {
-			Draw3DCache.returnVector3f(rayOrigin);
+			Draw3DCache.returnVector3f(newOrigin);
 		}
 	}
 
-	private float getCylinderDistance(Query i_query) {
+	private float getCylinderDistance(IVector3f i_rayOrigin,
+		IVector3f i_rayDirection) {
 
 		// if we hit one of the end caps, we are done
-		float d = getCapDistance(i_query);
+		float d = getCapDistance(i_rayOrigin, i_rayDirection);
 		if (!Float.isNaN(d))
 			return d;
 
 		// it's much quicker to intersect with a cylinder that stands on the
 		// origin and extends along the positive Z axis, so translate the ray
 		// accordingly
-		Vector3f rayOrigin = Draw3DCache.getVector3f();
+		Vector3f newOrigin = Draw3DCache.getVector3f();
 		try {
-			Math3D
-				.translate(i_query.getRayOrigin(), -0.5f, -0.5f, 0, rayOrigin);
-			IVector3f rayDirection = i_query.getRayDirection();
+			Math3D.translate(i_rayOrigin, -0.5f, -0.5f, 0, newOrigin);
 
 			// now intersect with infinite cylinder along Z axis:
-			float xo = rayOrigin.getX();
-			float yo = rayOrigin.getY();
-			float xd = rayDirection.getX();
-			float yd = rayDirection.getY();
+			float xo = newOrigin.getX();
+			float yo = newOrigin.getY();
+			float xd = i_rayDirection.getX();
+			float yd = i_rayDirection.getY();
 
 			float A = xd * xd + yd * yd;
 			float B = 2 * (xo * xd + yo * yd);
@@ -556,7 +551,7 @@
 			Math3D.solveQuadraticEquation(A, B, C, TMP_F2);
 			return Math3D.minDistance(TMP_F2);
 		} finally {
-			Draw3DCache.returnVector3f(rayOrigin);
+			Draw3DCache.returnVector3f(newOrigin);
 		}
 	}
 
@@ -570,26 +565,25 @@
 		return RenderType.getRenderType(m_alpha, m_superimposed);
 	}
 
-	private float getTruncatedConeDistance(Query i_query) {
+	private float getTruncatedConeDistance(IVector3f i_rayOrigin,
+		IVector3f i_rayDirection) {
 
 		// if we hit an end cap, we are done
-		float d = getCapDistance(i_query);
+		float d = getCapDistance(i_rayOrigin, i_rayDirection);
 		if (!Float.isNaN(d))
 			return d;
 
 		// it's much quicker to intersect with a cone whose apex is the
 		// origin and that extends along the positive Z axis, so translate the
 		// ray accordingly and then check with a positive min Z value
-		Vector3f rayOrigin = Draw3DCache.getVector3f();
+		Vector3f newOrigin = Draw3DCache.getVector3f();
 		try {
 			float h = m_config.getHeight();
-			Math3D.translate(i_query.getRayOrigin(), -0.5f, -0.5f, h - 1,
-				rayOrigin);
-			IVector3f rayDirection = i_query.getRayDirection();
+			Math3D.translate(i_rayOrigin, -0.5f, -0.5f, h - 1, newOrigin);
 
-			return doGetConeDistance(rayOrigin, rayDirection, h - 1, h);
+			return doGetConeDistance(newOrigin, i_rayDirection, h - 1, h);
 		} finally {
-			Draw3DCache.returnVector3f(rayOrigin);
+			Draw3DCache.returnVector3f(newOrigin);
 		}
 	}
 

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CylindricFigureShape.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CylindricFigureShape.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/CylindricFigureShape.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -10,11 +10,12 @@
  ******************************************************************************/
 package org.eclipse.draw3d.shapes;
 
-import org.eclipse.draw2d.IFigure;
+import java.util.Map;
+
 import org.eclipse.draw3d.IFigure3D;
 import org.eclipse.draw3d.RenderContext;
+import org.eclipse.draw3d.geometry.IVector3f;
 import org.eclipse.draw3d.geometry.ParaxialBoundingBox;
-import org.eclipse.draw3d.picking.Query;
 
 /**
  * CylindricFigureShape There should really be more documentation here.
@@ -40,12 +41,13 @@
 	 *      int, float, boolean)
 	 * @throws NullPointerException if the given figure is <code>null</code>
 	 */
-	public CylindricFigureShape(IFigure i_figure, int i_segments,
+	public CylindricFigureShape(IFigure3D i_figure, int i_segments,
 			float i_radiusProportions, boolean i_superimposed) {
 
 		if (i_figure == null)
 			throw new NullPointerException("i_figure must not be null");
 
+		m_figure = i_figure;
 		m_shape =
 			new CylinderShape(m_figure.getPosition3D(), i_segments,
 				i_radiusProportions, i_superimposed);
@@ -54,11 +56,13 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.picking.Query)
+	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.geometry.IVector3f,
+	 *      org.eclipse.draw3d.geometry.IVector3f, java.util.Map)
 	 */
-	public float getDistance(Query i_query) {
+	public float getDistance(IVector3f i_rayOrigin, IVector3f i_rayDirection,
+		Map<Object, Object> i_context) {
 
-		return m_shape.getDistance(i_query);
+		return m_shape.getDistance(i_rayOrigin, i_rayDirection, i_context);
 	}
 
 	/**

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/NullShape.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/NullShape.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/NullShape.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -10,9 +10,11 @@
  ******************************************************************************/
 package org.eclipse.draw3d.shapes;
 
+import java.util.Map;
+
 import org.eclipse.draw3d.RenderContext;
+import org.eclipse.draw3d.geometry.IVector3f;
 import org.eclipse.draw3d.geometry.ParaxialBoundingBox;
-import org.eclipse.draw3d.picking.Query;
 
 /**
  * An invisible shape which cannot be picked. This shape is used mainly during
@@ -27,9 +29,11 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.picking.Query)
+	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.geometry.IVector3f,
+	 *      org.eclipse.draw3d.geometry.IVector3f, java.util.Map)
 	 */
-	public float getDistance(Query iQuery) {
+	public float getDistance(IVector3f i_rayOrigin, IVector3f i_rayDirection,
+		Map<Object, Object> i_context) {
 
 		return Float.NaN;
 	}

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/ParaxialBoundsFigureShape.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/ParaxialBoundsFigureShape.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/ParaxialBoundsFigureShape.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -10,14 +10,16 @@
  ******************************************************************************/
 package org.eclipse.draw3d.shapes;
 
+import java.util.Map;
+
 import org.eclipse.draw3d.IFigure3D;
 import org.eclipse.draw3d.RenderContext;
+import org.eclipse.draw3d.geometry.IVector3f;
 import org.eclipse.draw3d.geometry.Math3D;
 import org.eclipse.draw3d.geometry.ParaxialBoundingBox;
 import org.eclipse.draw3d.geometry.Position3D;
 import org.eclipse.draw3d.geometry.Position3DUtil;
 import org.eclipse.draw3d.geometry.Vector3f;
-import org.eclipse.draw3d.picking.Query;
 import org.eclipse.draw3d.util.Draw3DCache;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Display;
@@ -57,9 +59,11 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.picking.Query)
+	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.geometry.IVector3f,
+	 *      org.eclipse.draw3d.geometry.IVector3f, java.util.Map)
 	 */
-	public float getDistance(Query i_query) {
+	public float getDistance(IVector3f i_rayOrigin, IVector3f i_rayDirection,
+		Map<Object, Object> i_context) {
 
 		return Float.NaN;
 	}

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/PolylineFigureShape.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/PolylineFigureShape.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/PolylineFigureShape.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -10,6 +10,8 @@
  ******************************************************************************/
 package org.eclipse.draw3d.shapes;
 
+import java.util.Map;
+
 import org.eclipse.draw3d.Polyline3D;
 import org.eclipse.draw3d.RenderContext;
 import org.eclipse.draw3d.geometry.IVector3f;
@@ -22,7 +24,6 @@
 import org.eclipse.draw3d.geometryext.PointList3D;
 import org.eclipse.draw3d.graphics3d.Graphics3D;
 import org.eclipse.draw3d.graphics3d.Graphics3DDraw;
-import org.eclipse.draw3d.picking.Query;
 
 /**
  * A polyline shape can be used to render polylines.
@@ -59,9 +60,11 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.picking.Query)
+	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.geometry.IVector3f,
+	 *      org.eclipse.draw3d.geometry.IVector3f, java.util.Map)
 	 */
-	public float getDistance(Query i_query) {
+	public float getDistance(IVector3f i_rayOrigin, IVector3f i_rayDirection,
+		Map<Object, Object> i_context) {
 
 		// TODO handle line width!
 
@@ -97,9 +100,12 @@
 		 * calculate the point of intersection between the segment and the ray.
 		 */
 
-		Plane visBorder = getVisibleBorder(i_query);
-		Plane hBorder = getHorizontalBorder(i_query);
-		Plane vBorder = getVerticalBorder(i_query);
+		Plane visBorder =
+			getVisibleBorder(i_rayOrigin, i_rayDirection, i_context);
+		Plane hBorder =
+			getHorizontalBorder(i_rayOrigin, i_rayDirection, i_context);
+		Plane vBorder =
+			getVerticalBorder(i_rayOrigin, i_rayDirection, i_context);
 
 		IVector3f p1 = points.get(0);
 		IVector3f p2;
@@ -144,14 +150,11 @@
 
 							// intersection only if tmp is on the
 							// picking ray
-							IVector3f rayOrigin = i_query.getRayOrigin();
-							IVector3f rayDirection = i_query.getRayDirection();
+							Math3D.sub(intersection, i_rayOrigin, tmp);
+							float fx = tmp.getX() / i_rayDirection.getX();
+							float fy = tmp.getY() / i_rayDirection.getY();
+							float fz = tmp.getZ() / i_rayDirection.getZ();
 
-							Math3D.sub(intersection, rayOrigin, tmp);
-							float fx = tmp.getX() / rayDirection.getX();
-							float fy = tmp.getY() / rayDirection.getY();
-							float fz = tmp.getZ() / rayDirection.getZ();
-
 							if (!Math3D.equals(fx, fy, ACCURACY))
 								return Float.NaN;
 
@@ -199,22 +202,24 @@
 		return 0;
 	}
 
-	private Plane getHorizontalBorder(Query i_query) {
+	private Plane getHorizontalBorder(IVector3f i_rayOrigin,
+		IVector3f i_rayDirection, Map<Object, Object> i_context) {
 
-		Plane horizontalBorder = (Plane) i_query.get(KEY_HORIZONTAL_BORDER);
+		Plane horizontalBorder = null;
+		if (i_context != null)
+			horizontalBorder = (Plane) i_context.get(KEY_HORIZONTAL_BORDER);
+
 		if (horizontalBorder == null) {
 			Vector3f normal = Math3DCache.getVector3f();
 			try {
-				IVector3f rayOrigin = i_query.getRayOrigin();
-				IVector3f rayDirection = i_query.getRayDirection();
-
-				Math3D.cross(rayOrigin, rayDirection, normal);
+				Math3D.cross(i_rayOrigin, i_rayDirection, normal);
 				Math3D.normalise(normal, normal);
 
 				horizontalBorder = new Plane();
-				horizontalBorder.set(rayOrigin, normal);
+				horizontalBorder.set(i_rayOrigin, normal);
 
-				i_query.set(KEY_HORIZONTAL_BORDER, horizontalBorder);
+				if (i_context != null)
+					i_context.put(KEY_HORIZONTAL_BORDER, horizontalBorder);
 			} finally {
 				Math3DCache.returnVector3f(normal);
 			}
@@ -244,23 +249,28 @@
 		return RenderType.getRenderType(m_figure.getAlpha(), false);
 	}
 
-	private Plane getVerticalBorder(Query i_query) {
+	private Plane getVerticalBorder(IVector3f i_rayOrigin,
+		IVector3f i_rayDirection, Map<Object, Object> i_context) {
 
-		Plane verticalBorder = (Plane) i_query.get(KEY_VERTICAL_BORDER);
+		Plane verticalBorder = null;
+		if (i_context != null)
+			verticalBorder = (Plane) i_context.get(KEY_VERTICAL_BORDER);
+
 		if (verticalBorder == null) {
 			Vector3f hNormal = Math3DCache.getVector3f();
 			Vector3f vNormal = Math3DCache.getVector3f();
 			try {
-				Plane horizontalBorder = getHorizontalBorder(i_query);
+				Plane horizontalBorder =
+					getHorizontalBorder(i_rayOrigin, i_rayDirection, i_context);
 				horizontalBorder.getNormal(hNormal);
-				IVector3f rayDirection = i_query.getRayDirection();
 
-				Math3D.cross(rayDirection, hNormal, vNormal);
+				Math3D.cross(i_rayDirection, hNormal, vNormal);
 
 				verticalBorder = new Plane();
-				verticalBorder.set(i_query.getRayOrigin(), vNormal);
+				verticalBorder.set(i_rayOrigin, vNormal);
 
-				i_query.set(KEY_VERTICAL_BORDER, verticalBorder);
+				if (i_context != null)
+					i_context.put(KEY_VERTICAL_BORDER, verticalBorder);
 			} finally {
 				Math3DCache.returnVector3f(hNormal, vNormal);
 			}
@@ -269,17 +279,19 @@
 		return verticalBorder;
 	}
 
-	private Plane getVisibleBorder(Query i_query) {
+	private Plane getVisibleBorder(IVector3f i_rayOrigin,
+		IVector3f i_rayDirection, Map<Object, Object> i_context) {
 
-		Plane visibleBorder = (Plane) i_query.get(KEY_VISIBLE_BORDER);
+		Plane visibleBorder = null;
+		if (i_context != null)
+			visibleBorder = (Plane) i_context.get(KEY_VISIBLE_BORDER);
+
 		if (visibleBorder == null) {
-			IVector3f rayOrigin = i_query.getRayOrigin();
-			IVector3f rayDirection = i_query.getRayDirection();
-
 			visibleBorder = new Plane();
-			visibleBorder.set(rayOrigin, rayDirection);
+			visibleBorder.set(i_rayOrigin, i_rayDirection);
 
-			i_query.set(KEY_VISIBLE_BORDER, visibleBorder);
+			if (i_context != null)
+				i_context.put(KEY_VISIBLE_BORDER, visibleBorder);
 		}
 
 		return visibleBorder;

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/PositionableShape.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/PositionableShape.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/PositionableShape.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -10,6 +10,7 @@
  ******************************************************************************/
 package org.eclipse.draw3d.shapes;
 
+import java.util.Map;
 import java.util.logging.Logger;
 
 import org.eclipse.draw3d.RenderContext;
@@ -24,7 +25,6 @@
 import org.eclipse.draw3d.geometry.Vector3f;
 import org.eclipse.draw3d.graphics3d.Graphics3D;
 import org.eclipse.draw3d.graphics3d.Graphics3DDraw;
-import org.eclipse.draw3d.picking.Query;
 import org.eclipse.draw3d.util.Draw3DCache;
 
 /**
@@ -57,12 +57,15 @@
 	 * Performs the intersection calculation using the given picking ray. The
 	 * picking ray may have been transformed due to the position of this shape.
 	 * 
-	 * @param i_query the modified query
+	 * @param i_rayOrigin the origin of the modified picking ray
+	 * @param i_rayDirection the direction of the modified picking ray
+	 * @param i_context a map for storing context information
 	 * @return the distance between the point of intersection of the picking ray
 	 *         and this shape or {@link Float#NaN} if the ray does not intersect
 	 *         with this shape
 	 */
-	protected abstract float doGetDistance(Query i_query);
+	protected abstract float doGetDistance(IVector3f i_rayOrigin,
+		IVector3f i_rayDirection, Map<Object, Object> i_context);
 
 	/**
 	 * Performs the actual rendering.
@@ -74,24 +77,22 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.picking.Query)
+	 * @see org.eclipse.draw3d.picking.Pickable#getDistance(org.eclipse.draw3d.geometry.IVector3f,
+	 *      org.eclipse.draw3d.geometry.IVector3f, java.util.Map)
 	 */
-	public float getDistance(Query i_query) {
+	public float getDistance(IVector3f i_rayOrigin, IVector3f i_rayDirection,
+		Map<Object, Object> i_context) {
 
 		if (m_position3D == null
-			|| m_position3D.getTransformationMatrix()
-				.equals(IMatrix4f.IDENTITY))
-			return doGetDistance(i_query);
+			|| m_position3D.getTransformationMatrix().equals(IMatrix4f.IDENTITY))
+			return doGetDistance(i_rayOrigin, i_rayDirection, i_context);
 
 		Vector3f newOrigin = Draw3DCache.getVector3f();
 		Vector3f newDirection = Draw3DCache.getVector3f();
 		try {
-			IVector3f oldOrigin = i_query.getRayOrigin();
-			IVector3f oldDirection = i_query.getRayDirection();
+			newOrigin.set(i_rayOrigin);
+			newDirection.set(i_rayDirection);
 
-			newOrigin.set(oldOrigin);
-			newDirection.set(oldDirection);
-
 			// transform picking ray
 			if (!m_position3D.transformRay(newOrigin, newDirection))
 				return Float.NaN;
@@ -100,11 +101,7 @@
 			if (newLength != 1)
 				newDirection.scale(1 / newLength); // normalise
 
-			i_query.setRay(newOrigin, newDirection);
-			float distance = doGetDistance(i_query);
-
-			i_query.setRay(oldOrigin, oldDirection);
-
+			float distance = doGetDistance(newOrigin, newDirection, i_context);
 			if (Float.isNaN(distance))
 				return Float.NaN;
 
@@ -185,8 +182,7 @@
 			Graphics3D g3d = i_renderContext.getGraphics3D();
 			boolean useModelMatrix =
 				m_position3D != null
-					&& !IMatrix4f.IDENTITY.equals(m_position3D
-						.getTransformationMatrix());
+					&& !IMatrix4f.IDENTITY.equals(m_position3D.getTransformationMatrix());
 
 			g3d.glMatrixMode(Graphics3DDraw.GL_MODELVIEW);
 

Modified: trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/SphereShape.java
===================================================================
--- trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/SphereShape.java	2009-09-08 12:57:28 UTC (rev 319)
+++ trunk/org.eclipse.draw3d/src/java/org/eclipse/draw3d/shapes/SphereShape.java	2009-09-21 16:02:07 UTC (rev 320)
@@ -10,8 +10,8 @@
  ******************************************************************************/
 package org.eclipse.draw3d.shapes;
 
+import java.util.HashMap;
 import java.util.Map;
-import java.util.WeakHashMap;
 
 import org.eclipse.draw3d.DisplayListManager;
 import org.eclipse.draw3d.RenderContext;
@@ -118,7 +118,7 @@
 	 * Caches the stripes across multiple instances since they never change.
 	 */
 	private static final Map<Integer, SphereTriangle[][]> STRIPE_CACHE =
-		new WeakHashMap<Integer, SphereTriangle[][]>();
+		new HashMap<Integer, SphereTriangle[][]>();
 
 	private static final float[] TMP_F2 = new float[2];
 
@@ -251,10 +251,12 @@
 	/**
 	 * {@inheritDoc}
 	 * 
-	 * @see org.eclipse.draw3d.shapes.PositionableShape#doGetDistance(org.eclipse.draw3d.picking.Query)
+	 * @see org.eclipse.draw3d.shapes.PositionableShape#doGetDistance(org.eclipse.draw3d.geometry.IVector3f,
+	 *      org.eclipse.draw3d.geometry.IVector3f, java.util.Map)
 	 */
 	@Override
-	protected float doGetDistance(Query i_query) {
+	protected float doGetDistance(IVector3f i_rayOrigin,
+		IVector3f i_rayDirection, Map<Object, Object> i_context) {
 
 		// TODO: intersect with individual triangles for low precision
 
@@ -265,15 +267,12 @@
 		// vector from origin + proj to sphere center
 		Vector3f orth = Draw3DCache.getVector3f();
 		try {
-			IVector3f rayOrigin = i_query.getRayOrigin();
-			IVector3f rayDirection = i_query.getRayDirection();
-
 			// vector from ray origin to center
-			Math3D.sub(CENTER, rayOrigin, roToC);
+			Math3D.sub(CENTER, i_rayOrigin, roToC);
 
 			// project that vector onto the ray direction
-			float dot = Math3D.dot(roToC, rayDirection);
-			Math3D.scale(dot, rayDirection, proj);
+			float dot = Math3D.dot(roToC, i_rayDirection);
+			Math3D.scale(dot, i_rayDirection, proj);
 
 			Math3D.sub(roToC, proj, orth);