Author: paperwing
Date: 2012-02-29 15:45:01 -0800 (Wed, 29 Feb 2012)
New Revision: 28406
Modified:
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/Graphics.java
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/data/GraphicsData.java
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/geometric/ViewingVolume.java
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/rendering/RenderNodeLabelsProcedure.java
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/rendering/RenderNodesProcedure.java
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/tools/GeometryToolkit.java
Log:
refs #678 Viewing volume culling for node labels and nodes implemented; no
longer draws labels and nodes outside of the field of view.
Modified:
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/Graphics.java
===================================================================
---
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/Graphics.java
2012-02-29 22:45:50 UTC (rev 28405)
+++
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/Graphics.java
2012-02-29 23:45:01 UTC (rev 28406)
@@ -26,6 +26,7 @@
import org.cytoscape.paperwing.internal.input.KeyboardMonitor;
import org.cytoscape.paperwing.internal.input.MouseMonitor;
import org.cytoscape.paperwing.internal.picking.ShapePickingProcessor;
+import org.cytoscape.paperwing.internal.tools.GeometryToolkit;
import org.cytoscape.paperwing.internal.tools.SimpleCamera;
import org.cytoscape.view.model.CyNetworkView;
import org.cytoscape.view.model.VisualLexicon;
@@ -128,6 +129,13 @@
GL2 gl = drawable.getGL().getGL2();
graphicsData.setGlContext(gl);
+ // Re-calculate the viewing volume
+ SimpleCamera camera = graphicsData.getCamera();
+
graphicsData.getViewingVolume().calculateViewingVolume(camera.getPosition(),
camera.getDirection(), camera.getUp(),
+ graphicsData.getNearZ(),
graphicsData.getFarZ(), graphicsData.getVerticalFov(),
+
GeometryToolkit.findHorizontalFieldOfView(graphicsData.getDistanceScale(),
+ graphicsData.getScreenWidth(),
graphicsData.getScreenHeight()));
+
// Perform picking
shapePickingProcessor.processPicking(mouse, keys, graphicsData);
Modified:
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/data/GraphicsData.java
===================================================================
---
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/data/GraphicsData.java
2012-02-29 22:45:50 UTC (rev 28405)
+++
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/data/GraphicsData.java
2012-02-29 23:45:01 UTC (rev 28406)
@@ -9,6 +9,7 @@
import org.cytoscape.paperwing.internal.Graphics;
import org.cytoscape.paperwing.internal.coordinator.ViewingCoordinator;
import org.cytoscape.paperwing.internal.geometric.Vector3;
+import org.cytoscape.paperwing.internal.geometric.ViewingVolume;
import org.cytoscape.paperwing.internal.tools.SimpleCamera;
import org.cytoscape.view.model.CyNetworkView;
import org.cytoscape.view.model.VisualLexicon;
@@ -37,6 +38,8 @@
private float verticalFov = 45.0f;
+ private ViewingVolume viewingVolume;
+
/** Distance from eye to the near clipping plane */
private float nearZ = 0.2f;
@@ -97,6 +100,7 @@
pickingData = new PickingData();
camera = new SimpleCamera();
+ viewingVolume = new ViewingVolume();
}
public void setNetworkView(CyNetworkView networkView) {
@@ -234,4 +238,12 @@
public void setPickingData(PickingData pickingData) {
this.pickingData = pickingData;
}
+
+ public ViewingVolume getViewingVolume() {
+ return viewingVolume;
+ }
+
+ public void setViewingVolume(ViewingVolume viewingVolume) {
+ this.viewingVolume = viewingVolume;
+ }
}
Modified:
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/geometric/ViewingVolume.java
===================================================================
---
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/geometric/ViewingVolume.java
2012-02-29 22:45:50 UTC (rev 28405)
+++
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/geometric/ViewingVolume.java
2012-02-29 23:45:01 UTC (rev 28406)
@@ -29,10 +29,19 @@
private Plane top, bottom;
private Plane left, right;
+ public ViewingVolume() {
+ near = new Plane();
+ far = new Plane();
+ top = new Plane();
+ bottom = new Plane();
+ left = new Plane();
+ right = new Plane();
+ }
+
/**
* Tests if a given point is inside the viewing volume.
*
- * @param point
+ * @param point The test point
* @return <code>true</code> if the point is inside the volume,
<code>false</code> otherwise.
*/
public boolean inside(Vector3 point) {
@@ -50,6 +59,29 @@
}
/**
+ * Tests if a given point either inside the viewing volume or has a
distance to the viewing volume
+ * not exceeding a certain given value.
+ *
+ * @param point The test point
+ * @param distance The maximum distance between the point and the
volume volume before the point is
+ * considered to be outside the viewing volume.
+ * @return <code>true</code> If the point is inside or within a certain
distance from
+ */
+ public boolean inside(Vector3 point, double distance) {
+ if (isInsidePlane(point, near, distance) &&
+ isInsidePlane(point, far, distance) &&
+ isInsidePlane(point, top, distance) &&
+ isInsidePlane(point, bottom, distance) &&
+ isInsidePlane(point, left, distance) &&
+ isInsidePlane(point, right, distance)) {
+
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
* Checks if a point is inside the given plane, that is, it lies on the
opposite side of the normal.
*
* @param point The test point
@@ -70,6 +102,26 @@
}
/**
+ * Checks if a point is inside the given plane. If it is not, this
method still returns <code>true</code>
+ * as long as the point is within a certain distance from the plane.
+ *
+ * @param point The test point
+ * @param plane The plane to test against
+ * @param radius The maximum distance the point can be to the plane
before it is considered to be outside the plane
+ * @return <code>true</code> if the point lies on the opposite side of
the plane's normal, within the given distance.
+ * Returns <code>false</code> otherwise.
+ */
+ private boolean isInsidePlane(Vector3 point, Plane plane, double
distance) {
+ double signedDistance = plane.normal.dot(point) +
plane.parameterD;
+
+ if (signedDistance > distance) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
* Calculate the boundaries of the viewing volume given the camera
orientation, the distance to the near and far clipping planes,
* and the vertical and horizontal fields of view.
*
@@ -100,13 +152,46 @@
double farParameterD =
-farNormal.dot(cameraPosition.plus(cameraDirection.multiply(zFar)));
far.set(farNormal, farParameterD);
+ // Find the center point on the near plane for later use
+ Vector3 nearCenterPoint =
cameraPosition.plus(cameraDirection.multiply(zNear));
+
// Calculate left plane
// Rotate 90 degrees past the left plane to obtain the normal
Vector3 leftNormal = cameraDirection.rotate(cameraUp,
Math.toRadians(horizontalFieldOfView / 2 + 90));
// Find a point on the plane to find the D parameter
+ Vector3 leftSamplePosition =
cameraLeft.multiply(Math.tan(Math.toRadians(horizontalFieldOfView) / 2) *
zNear).plus(nearCenterPoint);
+ double leftParameterD = -leftNormal.dot(leftSamplePosition);
+ left.set(leftNormal, leftParameterD);
+ // Calculate right plane
+
+ // Rotate 90 degrees past the right plane to obtain the normal
+ Vector3 rightNormal = cameraDirection.rotate(cameraUp,
Math.toRadians(horizontalFieldOfView / 2 + 90));
+
+ // Find a point on the plane to find the D parameter
+ Vector3 rightSamplePosition =
cameraLeft.multiply(Math.tan(Math.toRadians(horizontalFieldOfView) / 2) *
-zNear).plus(nearCenterPoint);
+ double rightParameterD = -rightNormal.dot(rightSamplePosition);
+ right.set(rightNormal, rightParameterD);
+
+ // Calculate top plane
+
+ Vector3 topNormal = cameraDirection.rotate(cameraLeft,
-Math.toRadians(verticalFieldOfView / 2 + 90));
+
+ // Find a point on the plane
+ Vector3 topSamplePosition =
cameraUp.multiply(Math.tan(Math.toRadians(verticalFieldOfView) / 2) *
zNear).plus(nearCenterPoint);
+ double topParameterD = -topNormal.dot(topSamplePosition);
+ top.set(topNormal, topParameterD);
+
+ // Calculate bottom plane
+
+ Vector3 bottomNormal = cameraDirection.rotate(cameraLeft,
Math.toRadians(verticalFieldOfView / 2 + 90));
+
+ // Find a point on the plane
+ Vector3 bottomSamplePosition =
cameraUp.multiply(Math.tan(Math.toRadians(verticalFieldOfView) / 2) *
-zNear).plus(nearCenterPoint);
+ double bottomParameterD =
-bottomNormal.dot(bottomSamplePosition);
+ bottom.set(bottomNormal, bottomParameterD);
}
}
Modified:
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/rendering/RenderNodeLabelsProcedure.java
===================================================================
---
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/rendering/RenderNodeLabelsProcedure.java
2012-02-29 22:45:50 UTC (rev 28405)
+++
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/rendering/RenderNodeLabelsProcedure.java
2012-02-29 23:45:01 UTC (rev 28406)
@@ -71,7 +71,7 @@
String text;
Color textColor;
-
+
gl.glPushMatrix();
textRenderer.beginRendering(graphicsData.getScreenWidth(),
graphicsData.getScreenHeight(), true);
// textRenderer.drawString3D(arg0, arg1, arg2, arg3, arg4, arg5)
@@ -100,7 +100,7 @@
// Only draw the text if the front side
of the camera faces it
if (offsetFromCamera.magnitudeSquared()
> Double.MIN_NORMAL
- &&
graphicsData.getCamera().getDirection().angle(offsetFromCamera) <= Math.PI / 2)
{
+ &&
graphicsData.getViewingVolume().inside(text3dPosition, graphicsData.getNearZ()
/ 2)) {
// TODO: Check if there is a
way around this cast
textColor = (Color)
nodeView.getVisualProperty(BasicVisualLexicon.NODE_LABEL_COLOR);
@@ -128,7 +128,6 @@
}
textRenderer.endRendering();
-
gl.glPopMatrix();
}
Modified:
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/rendering/RenderNodesProcedure.java
===================================================================
---
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/rendering/RenderNodesProcedure.java
2012-02-29 22:45:50 UTC (rev 28405)
+++
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/rendering/RenderNodesProcedure.java
2012-02-29 23:45:01 UTC (rev 28406)
@@ -14,6 +14,7 @@
import org.cytoscape.model.CyEdge;
import org.cytoscape.model.CyNode;
import org.cytoscape.paperwing.internal.data.GraphicsData;
+import org.cytoscape.paperwing.internal.geometric.Vector3;
import org.cytoscape.paperwing.internal.rendering.shapes.ScalableShapeDrawer;
import
org.cytoscape.paperwing.internal.rendering.shapes.ScalableShapeDrawer.ShapeType;
import org.cytoscape.paperwing.internal.tools.NetworkToolkit;
@@ -94,7 +95,9 @@
// gl.glLoadName(33);
// Draw it only if the visual property says it is
visible
- if
(nodeView.getVisualProperty(BasicVisualLexicon.NODE_VISIBLE)) {
+ if
(nodeView.getVisualProperty(BasicVisualLexicon.NODE_VISIBLE)
+ &&
graphicsData.getViewingVolume().inside(new Vector3(x, y, z),
graphicsData.getNearZ() / 2)) {
+
gl.glPushMatrix();
gl.glTranslatef(x, y, z);
gl.glLoadName(index);
Modified:
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/tools/GeometryToolkit.java
===================================================================
---
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/tools/GeometryToolkit.java
2012-02-29 22:45:50 UTC (rev 28405)
+++
csplugins/trunk/toronto/yuedong/paperwing-impl/src/main/java/org/cytoscape/paperwing/internal/tools/GeometryToolkit.java
2012-02-29 23:45:01 UTC (rev 28406)
@@ -195,8 +195,22 @@
return Math.abs(Math.cos(angle) * hypotenuse);
}
- /*
- public static double findHorizontalFieldOfView(double
verticalFieldOfView, int screenWidth, int screenHeight) {
+
+ /**
+ * Given the fixed vertical field of view and screen dimensions,
calculate the horizontal field of view assuming that
+ * it varies according to the current aspect ratio. If the screen
dimensions are equal, the returned horizontal field of view
+ * would be equal to the vertical field of view.
+ *
+ * @param verticalFieldOfView The vertical field of view, in degrees
+ * @param screenWidth The width of the screen
+ * @param screenHeight The height of the screen
+ * @return The calculated horizontal field of view, in degrees
+ */
+ public static double findHorizontalFieldOfView(double
verticalFieldOfView, int screenWidth, int screenHeight) {
+ double screenDistance = (screenHeight / 2) /
Math.tan(verticalFieldOfView / 2 * Math.PI / 180);
+
+ double horizontalFieldOfView = Math.atan(screenWidth / 2 /
screenDistance);
+
+ return (horizontalFieldOfView * 180 / Math.PI);
}
- */
}
--
You received this message because you are subscribed to the Google Groups
"cytoscape-cvs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/cytoscape-cvs?hl=en.