From e8901f0a13aa7a58c5abd4e755e30598df3b3f35 Mon Sep 17 00:00:00 2001 From: Florian Hoelzl <hoelzl@fortiss.org> Date: Thu, 5 Jul 2012 14:56:31 +0000 Subject: [PATCH] --- .../trunk/.classpath | 9 + .../trunk/.project | 28 ++ .../trunk/META-INF/MANIFEST.MF | 30 ++ .../trunk/build.properties | 12 + .../trunk/lib/slick-util.jar | Bin 0 -> 96136 bytes .../trunk/plugin.xml | 21 ++ .../ui/ToolingGraphics3DUIActivator.java | 64 ++++ .../tooling/graphics3D/ui/camera/Camera.java | 75 +++++ .../camera/MovingCameraWithPitchAndYaw.java | 121 +++++++ .../graphics3D/ui/draw/Lwjgl3DCanvas.java | 103 ++++++ .../ui/draw/Lwjgl3DRenderThread.java | 86 +++++ .../ui/editor/EditorStatusBarItem.java | 59 ++++ .../ui/editor/Graphical3DEditorBase.java | 264 +++++++++++++++ .../tooling/graphics3D/ui/light/Light.java | 96 ++++++ .../graphics3D/ui/light/Light3DLight.java | 56 ++++ .../ui/objects/CompositeViewObject.java | 53 +++ .../ui/objects/Graph3DViewObject.java | 133 ++++++++ .../ui/objects/Object3DViewObject.java | 46 +++ .../ui/objects/PickableObjectBase.java | 54 +++ .../graphics3D/ui/objects/RotatedObject.java | 60 ++++ .../graphics3D/ui/objects/ScaledObject.java | 56 ++++ .../graphics3D/ui/objects/ViewObjectBase.java | 46 +++ .../ui/objects/WrappedViewObjectBase.java | 51 +++ .../ui/picker/ModelObjectPicker.java | 140 ++++++++ .../graphics3D/ui/util/FloatBufferUtils.java | 89 +++++ .../graphics3D/ui/util/GLPrimitives.java | 308 ++++++++++++++++++ .../tooling/graphics3D/ui/Test3DEditor.java | 213 ++++++++++++ .../graphics3D/ui/Test3DEditorBinding.java | 51 +++ 28 files changed, 2324 insertions(+) create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/.classpath create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/.project create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/META-INF/MANIFEST.MF create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/build.properties create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/lib/slick-util.jar create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/plugin.xml create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/ToolingGraphics3DUIActivator.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/camera/Camera.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/camera/MovingCameraWithPitchAndYaw.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/draw/Lwjgl3DCanvas.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/draw/Lwjgl3DRenderThread.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/editor/EditorStatusBarItem.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/editor/Graphical3DEditorBase.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/light/Light.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/light/Light3DLight.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/CompositeViewObject.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/Graph3DViewObject.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/Object3DViewObject.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/PickableObjectBase.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/RotatedObject.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/ScaledObject.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/ViewObjectBase.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/WrappedViewObjectBase.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/picker/ModelObjectPicker.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/util/FloatBufferUtils.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/util/GLPrimitives.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/test-src/test/org/fortiss/tooling/graphics3D/ui/Test3DEditor.java create mode 100644 org.fortiss.tooling.graphicsGL.ui/trunk/test-src/test/org/fortiss/tooling/graphics3D/ui/Test3DEditorBinding.java diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/.classpath b/org.fortiss.tooling.graphicsGL.ui/trunk/.classpath new file mode 100644 index 000000000..afc0beec3 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/.classpath @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> + <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> + <classpathentry kind="src" path="src"/> + <classpathentry kind="src" path="test-src"/> + <classpathentry exported="true" kind="lib" path="lib/slick-util.jar"/> + <classpathentry kind="output" path="build"/> +</classpath> diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/.project b/org.fortiss.tooling.graphicsGL.ui/trunk/.project new file mode 100644 index 000000000..b792e83d1 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/.project @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.fortiss.tooling.graphics3D.ui</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.ManifestBuilder</name> + <arguments> + </arguments> + </buildCommand> + <buildCommand> + <name>org.eclipse.pde.SchemaBuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.pde.PluginNature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/META-INF/MANIFEST.MF b/org.fortiss.tooling.graphicsGL.ui/trunk/META-INF/MANIFEST.MF new file mode 100644 index 000000000..3b27e1df7 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/META-INF/MANIFEST.MF @@ -0,0 +1,30 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Fortiss Tooling Graphics 3D UI +Bundle-SymbolicName: org.fortiss.tooling.graphics3D.ui;singleton:=true +Bundle-Version: 2.1.0.qualifier +Bundle-Activator: org.fortiss.tooling.graphics3D.ui.ToolingGraphics3DUIActivator +Require-Bundle: org.fortiss.tooling.graphics3D;bundle-version="2.1.0";visibility:=reexport, + org.fortiss.tooling.base.ui;bundle-version="2.1.0";visibility:=reexport, + org.lwjgl;bundle-version="2.8.4";visibility:=reexport, + org.fortiss.af3.expression.ui;bundle-version="2.1.0" +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-Vendor: fortiss GmbH +Export-Package: org.fortiss.tooling.graphics3D.ui, + org.fortiss.tooling.graphics3D.ui.camera, + org.fortiss.tooling.graphics3D.ui.draw, + org.fortiss.tooling.graphics3D.ui.editor, + org.fortiss.tooling.graphics3D.ui.light, + org.fortiss.tooling.graphics3D.ui.objects, + org.fortiss.tooling.graphics3D.ui.picker, + org.fortiss.tooling.graphics3D.ui.util, + org.newdawn.slick, + org.newdawn.slick.loading, + org.newdawn.slick.openal, + org.newdawn.slick.opengl, + org.newdawn.slick.opengl.renderer, + org.newdawn.slick.tests, + org.newdawn.slick.util +Bundle-ClassPath: lib/slick-util.jar, + . diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/build.properties b/org.fortiss.tooling.graphicsGL.ui/trunk/build.properties new file mode 100644 index 000000000..773364883 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/build.properties @@ -0,0 +1,12 @@ +# <copyright> +# </copyright> +# +# $Id$ + +bin.includes = .,\ + META-INF/,\ + plugin.xml,\ + lib/slick-util.jar +source.. = src/,\ + test-src/ +output.. = build/ diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/lib/slick-util.jar b/org.fortiss.tooling.graphicsGL.ui/trunk/lib/slick-util.jar new file mode 100644 index 0000000000000000000000000000000000000000..9e20b22adf3522640ff9bf79956c2258720c90e2 GIT binary patch literal 96136 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 Jp9OOz$p19n3<>}M literal 0 HcmV?d00001 diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/plugin.xml b/org.fortiss.tooling.graphicsGL.ui/trunk/plugin.xml new file mode 100644 index 000000000..269753fc3 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/plugin.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.0"?> + +<!-- + <copyright> + </copyright> + + $Id$ +--> +<plugin> + <extension + point="org.fortiss.tooling.kernel.ui.modelEditorBinding"> + <modelEditorBinding + binding="test.org.fortiss.tooling.graphics3D.ui.Test3DEditorBinding"> + <modelElementClass + modelElementClass="org.fortiss.af3.expression.model.DataDictionary"> + </modelElementClass> + </modelEditorBinding> + </extension> + +</plugin> diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/ToolingGraphics3DUIActivator.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/ToolingGraphics3DUIActivator.java new file mode 100644 index 000000000..d7fa06981 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/ToolingGraphics3DUIActivator.java @@ -0,0 +1,64 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2011 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: E9B79759E2C0C013BE2B19DE87749838 + */ +public class ToolingGraphics3DUIActivator extends AbstractUIPlugin { + + /** The plug-in ID. */ + public static final String PLUGIN_ID = ToolingGraphics3DUIActivator.class.getPackage() + .getName(); //$NON-NLS-1$ + + /** The shared instance. */ + private static ToolingGraphics3DUIActivator plugin; + + /** {@inheritDoc} */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /** {@inheritDoc} */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** Returns the shared instance. */ + public static ToolingGraphics3DUIActivator getDefault() { + return plugin; + } + + /** Returns the image descriptor for the given icon file. */ + public static ImageDescriptor getImageDescriptor(String path) { + return imageDescriptorFromPlugin(PLUGIN_ID, path); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/camera/Camera.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/camera/Camera.java new file mode 100644 index 000000000..bf05dbb81 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/camera/Camera.java @@ -0,0 +1,75 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.camera; + +import static org.lwjgl.util.glu.GLU.gluLookAt; + +import org.lwjgl.util.vector.Vector3f; + +/** + * Class representing the camera with the Z axis as up vector. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 6DFDC1792DF675AF5ED360810E3635D7 + */ +public class Camera { + + /** The camera position. */ + protected Vector3f pos = new Vector3f(10.0f, 10.0f, 10.0f); + + /** The camera target. */ + private Vector3f target = new Vector3f(); + + /** Constructor. */ + public Camera() { + } + + /** Sets the camera position. */ + public void setPosition(float cx, float cy, float cz) { + pos = new Vector3f(cx, cy, cz); + } + + /** Alters the camera position with the given deltas. */ + public void alterPosition(float dx, float dy, float dz) { + setPosition(pos.x + dx, pos.y + dy, pos.z + dz); + } + + /** Sets the camera target. */ + public void setTarget(float tx, float ty, float tz) { + target = new Vector3f(tx, ty, tz); + } + + /** Alters the camera target with the given deltas. */ + public void alterTarget(float dx, float dy, float dz) { + target.x = target.x + dx; + target.y = target.y + dy; + target.z = target.z + dz; + } + + /** Applies the camera position and view target to GL before rendering starts. */ + public void applyForRendering() { + gluLookAt(pos.x, pos.y, pos.z, target.x, target.y, target.z, 0, 0, 1.0f); + } + + /** Applies the camera position and view target to GL before picking starts. */ + public void applyForPicking() { + gluLookAt(pos.x, pos.y, pos.z, target.x, target.y, target.z, 0, 0, 1.0f); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/camera/MovingCameraWithPitchAndYaw.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/camera/MovingCameraWithPitchAndYaw.java new file mode 100644 index 000000000..852cba96d --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/camera/MovingCameraWithPitchAndYaw.java @@ -0,0 +1,121 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.camera; + +import static java.lang.Math.cos; +import static java.lang.Math.sin; +import static java.lang.Math.toRadians; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.X_UNIT_VECTOR; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.Z_UNIT_VECTOR; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.rotate; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.translate; +import static org.lwjgl.util.glu.GLU.gluLookAt; + +/** + * A {@link Camera} which can be configured with pitch and yaw angle. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 8D71137B475BD3A8ECD299C288D95E15 + */ +public class MovingCameraWithPitchAndYaw extends Camera { + + /** The yaw angle. */ + private float yawAngle = 0.0f; + + /** The pitch angle. */ + private float pitchAngle = 0.0f; + + /** Alter the pitch angle. */ + public void pitch(float amount) { + pitchAngle += amount; + if(pitchAngle >= 85.0f) { + pitchAngle = 85.0f; + } else if(pitchAngle <= -85.0) { + pitchAngle = -85.0f; + } + } + + /** Alter the yaw angle. */ + public void yaw(float amount) { + yawAngle += amount; + } + + /** Move forward for the given distance. */ + public void forward(float distance) { + float dx = distance * (float)sin(toRadians(yawAngle)); + float dy = distance * (float)cos(toRadians(yawAngle)); + super.alterPosition(dx, dy, 0); + } + + /** Move backward for the given distance. */ + public void backward(float distance) { + forward(-distance); + } + + /** Move left for the given distance. */ + public void left(float distance) { + float dx = distance * (float)sin(toRadians(yawAngle - 90)); + float dy = distance * (float)cos(toRadians(yawAngle - 90)); + super.alterPosition(dx, dy, 0); + } + + /** Move right for the given distance. */ + public void right(float distance) { + left(-distance); + } + + /** Move up for the given distance. */ + public void up(float distance) { + super.alterPosition(0, 0, distance); + } + + /** Move down for the given distance. */ + public void down(float distance) { + up(-distance); + } + + /** {@inheritDoc} */ + @Override + public void applyForRendering() { + // from origin look at Y axis + gluLookAt(0, 0, 0, 0, 1.0f, 0, 0, 0, 1.0f); + rotate(pitchAngle, X_UNIT_VECTOR); + rotate(yawAngle, Z_UNIT_VECTOR); + translate(-pos.x, -pos.y, -pos.z); + } + + /** {@inheritDoc} */ + @Override + public void applyForPicking() { + applyForRendering(); + } + + /** {@inheritDoc} */ + @Override + public void setTarget(float tx, float ty, float tz) { + throw new UnsupportedOperationException(); + } + + /** {@inheritDoc} */ + @Override + public void alterTarget(float dx, float dy, float dz) { + throw new UnsupportedOperationException(); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/draw/Lwjgl3DCanvas.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/draw/Lwjgl3DCanvas.java new file mode 100644 index 000000000..118f54736 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/draw/Lwjgl3DCanvas.java @@ -0,0 +1,103 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.draw; + +import static org.fortiss.tooling.graphics3D.ui.ToolingGraphics3DUIActivator.getDefault; +import static org.fortiss.tooling.kernel.utils.LoggingUtils.error; +import static org.lwjgl.opengl.GL11.GL_MODELVIEW; +import static org.lwjgl.opengl.GL11.GL_PROJECTION; +import static org.lwjgl.opengl.GL11.glLoadIdentity; +import static org.lwjgl.opengl.GL11.glMatrixMode; +import static org.lwjgl.opengl.GL11.glViewport; +import static org.lwjgl.opengl.GLContext.useContext; +import static org.lwjgl.util.glu.GLU.gluPerspective; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.opengl.GLCanvas; +import org.eclipse.swt.opengl.GLData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Listener; +import org.lwjgl.LWJGLException; + +/** + * Canvas for drawing LWJGL content onto a SWT widget. It uses double buffer, dpeth buffer and four + * sample buffers. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 83ECFD2B231D8EC0A50D3D363571A870 + */ +public class Lwjgl3DCanvas extends GLCanvas { + + /** Constructor. */ + public Lwjgl3DCanvas(Composite parent, GLData data) { + super(parent, SWT.NONE, data); + } + + /** Constructor. */ + public Lwjgl3DCanvas(Composite parent) { + this(parent, createDefaultGLData()); + } + + /** Creates the default {@link GLData}. */ + private static GLData createDefaultGLData() { + GLData data = new GLData(); + // use double buffering + data.doubleBuffer = true; + // allow depth buffering + data.depthSize = 1; + // enable four sample buffers for anti-aliasing + data.sampleBuffers = 1; + data.samples = 4; + return data; + } + + /** Adds the given listener to handle the canvas resize events. */ + public void addResizeHandler(Listener handler) { + addListener(SWT.Resize, handler); + } + + /** Sets this canvas as the current canvas and tells OGL to use it. */ + public void setCurrentAndUseContext() { + try { + setCurrent(); + useContext(this); + } catch(LWJGLException ex) { + error(getDefault(), ex.getMessage(), ex); + } + } + + /** Sets the view port and perspective projection matrix. */ + public void setViewportAndPerspective(int width, int height, float fieldOfViewAngle, + float nearDistance, float farDistance) { + if(nearDistance <= 0 || farDistance <= 0) { + throw new IllegalArgumentException("Z distances of perspective must be greater 0."); + } + float aspect = (float)width / (float)height; + setCurrentAndUseContext(); + // set viewport and alter set projection matrix + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(fieldOfViewAngle, aspect, nearDistance, farDistance); + // return GL state to model matrix + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/draw/Lwjgl3DRenderThread.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/draw/Lwjgl3DRenderThread.java new file mode 100644 index 000000000..99779213e --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/draw/Lwjgl3DRenderThread.java @@ -0,0 +1,86 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.draw; + +import static org.eclipse.ui.PlatformUI.getWorkbench; + +/** + * Thread class for the render thread with a default sleep period of 40ms (i.e. about 25fps). + * The thread executes a refresh of the canvas using a Display async execution and dies as soon as + * the canvas is disposed. Note that the refresh is only performed if the canvas is not disposed and + * is visible. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 6CD38411345BE68238AF29F9A98D9CC5 + */ +public class Lwjgl3DRenderThread extends Thread { + + /** The GLCanvas to be rendered by this thread. */ + private final Lwjgl3DCanvas canvas; + + /** The render thread sleep period. */ + private int sleepPeriod = 40; + + /** The content renderer runnable. */ + private final Runnable contentRenderer; + + /** Constructor. */ + public Lwjgl3DRenderThread(Lwjgl3DCanvas canvas, Runnable contentRenderer) { + if(canvas == null) { + throw new IllegalArgumentException("Canvas may not be null."); + } + if(contentRenderer == null) { + throw new IllegalArgumentException("Content render may not be null."); + } + this.canvas = canvas; + this.contentRenderer = contentRenderer; + } + + /** Sets the sleep period of the render thread in milliseconds. */ + public void setSleepPeriod(int sleepPeriod) { + this.sleepPeriod = sleepPeriod; + } + + /** {@inheritDoc} */ + @Override + public void run() { + try { + sleep(sleepPeriod); + while(!canvas.isDisposed()) { + getWorkbench().getDisplay().asyncExec(refresher); + sleep(sleepPeriod); + } + } catch(InterruptedException e) { + e.printStackTrace(); + } + } + + /** The refresher display runner. */ + private Runnable refresher = new Runnable() { + @Override + public void run() { + if(!canvas.isDisposed() && canvas.isVisible()) { + canvas.setCurrentAndUseContext(); + contentRenderer.run(); + canvas.swapBuffers(); + } + } + }; +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/editor/EditorStatusBarItem.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/editor/EditorStatusBarItem.java new file mode 100644 index 000000000..9eb05e32e --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/editor/EditorStatusBarItem.java @@ -0,0 +1,59 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.editor; + +import org.eclipse.jface.action.ContributionItem; +import org.eclipse.jface.action.StatusLineLayoutData; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.CLabel; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; + +/** + * Status bar for the {@link Graphical3DEditorBase}. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 3CBE8094441E5D8E420FC65504AFEE20 + */ +public class EditorStatusBarItem extends ContributionItem { + + /** The status bar label. */ + private CLabel label; + + /** {@inheritDoc} */ + @Override + public void fill(Composite i_parent) { + Label sep = new Label(i_parent, SWT.SEPARATOR); + label = new CLabel(i_parent, SWT.SHADOW_NONE); + + StatusLineLayoutData data = new StatusLineLayoutData(); + data.widthHint = 400; + label.setLayoutData(data); + + data = new StatusLineLayoutData(); + data.heightHint = 32; + sep.setLayoutData(data); + } + + /** Sets the status line text. */ + public void setText(String text) { + label.setText(text); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/editor/Graphical3DEditorBase.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/editor/Graphical3DEditorBase.java new file mode 100644 index 000000000..7a554efd9 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/editor/Graphical3DEditorBase.java @@ -0,0 +1,264 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.editor; + +import static org.fortiss.tooling.graphics3D.ui.ToolingGraphics3DUIActivator.getDefault; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.clearCanvasAndLoadIdentity; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.initializeGL; +import static org.fortiss.tooling.kernel.utils.LoggingUtils.error; +import static org.newdawn.slick.Color.black; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.action.IStatusLineManager; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.MouseTrackListener; +import org.eclipse.swt.events.MouseWheelListener; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.fortiss.tooling.graphics3D.ui.camera.Camera; +import org.fortiss.tooling.graphics3D.ui.draw.Lwjgl3DCanvas; +import org.fortiss.tooling.graphics3D.ui.draw.Lwjgl3DRenderThread; +import org.fortiss.tooling.graphics3D.ui.objects.ViewObjectBase; +import org.fortiss.tooling.graphics3D.ui.picker.ModelObjectPicker; +import org.fortiss.tooling.kernel.ui.extension.base.EditorBase; +import org.lwjgl.LWJGLException; +import org.lwjgl.util.vector.Vector3f; + +/** + * Base class for 3D graphics editors. Sub-classes must provide a {@link Camera} and a + * {@link ViewObjectBase}, which are used to render the editor content. Sub-classes may react on + * mouse and key events by overriding the respective methods. + * <P> + * The rendering process is started by calling {@link #beginRenderLoop()}, which allows sub-classes + * to apply additional GL setup commands. Sub-classes maya change the perspective by overriding + * {@link #getPerspective()} and return a vector with the field of view, Z near distance, and Z far + * distance. Note that all three must be greater zero. + * <P> + * After the rendering is done the picking process starts if both {@link #pickX} and {@link #pickY} + * are greater or equal to zero and smaller than the widget width and height, respectively. + * Sub-classes should update these variables when they want to pick an object from the scene. The + * {@link #pickTargetChanged()} method is called whenever the picked object changes. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 908A7E484514F2EC6D3126014A55B7E9 + */ +public abstract class Graphical3DEditorBase<T extends EObject> extends EditorBase<T> implements + MouseListener, MouseTrackListener, MouseMoveListener, MouseWheelListener, KeyListener, + Listener { + + /** The 3D canvas. */ + protected Lwjgl3DCanvas canvas; + + /** The status line for simple text feedback. */ + protected EditorStatusBarItem statusBarItem; + + /** The render thread. */ + private Lwjgl3DRenderThread renderThread; + + /** The object picker. */ + private ModelObjectPicker picker = new ModelObjectPicker(); + + /** The current X position to be used during picking. */ + protected int pickX = -1; + + /** The current Y position to be used during picking. */ + protected int pickY = -1; + + /** The current picked object or {@code null} if no pickable object is at the picking location. */ + protected Object pickTarget; + + /** {@inheritDoc} */ + @Override + public final void handleEvent(Event event) { + Rectangle b = canvas.getBounds(); + Vector3f p = getPerspective(); + canvas.setViewportAndPerspective(b.width, b.height, p.x, p.y, p.z); + } + + /** Callback from render thread. */ + private Runnable renderCallback = new Runnable() { + @Override + public void run() { + try { + performRendering(); + performPicking(); + } catch(LWJGLException ex) { + error(getDefault(), ex.getMessage(), ex); + } + } + }; + + /** + * Called when the render loop starts, but after the camera was applied for rendering. + * Sub-classes should make GL calls to setup rendering. The default does nothing. + */ + @SuppressWarnings("unused") + protected void beginRenderLoop() throws LWJGLException { + // do nothing + } + + /** Returns the current camera to be used. */ + protected abstract Camera getCamera(); + + /** + * Sub-classes should provide the scene object here. The model object will be used for rendering + * and picking using {@link ViewObjectBase}'s respective methods. + */ + protected abstract ViewObjectBase getSceneModelObject(); + + /** Notification about the change of the pick target. The default does nothing. */ + protected void pickTargetChanged() { + // do nothing + } + + /** + * Returns the perspective projection (field of view, near distance, far distance). The default + * uses {@code 45.0f, 0.5f, 400.0f}. + */ + protected Vector3f getPerspective() { + return new Vector3f(45.0f, 0.5f, 400.0f); + } + + /** Performs the object picking operation. */ + private void performPicking() { + // avoid unnecessary picking if mouse is outside the canvas + if(pickX < 0 || pickX > canvas.getBounds().width || pickY < 0 || + pickY > canvas.getBounds().height) { + return; + } + Object p = picker.pickModelObject(pickX, pickY, getPerspective(), getSceneModelObject()); + if(pickTarget != p) { + pickTarget = p; + pickTargetChanged(); + } + } + + /** Performs the object rendering operation. */ + private void performRendering() throws LWJGLException { + clearCanvasAndLoadIdentity(black); + getCamera().applyForRendering(); + beginRenderLoop(); + getSceneModelObject().renderObject(); + } + + /** {@inheritDoc} */ + @Override + public void createPartControl(Composite parent) { + IStatusLineManager statusLine = getEditorSite().getActionBars().getStatusLineManager(); + statusBarItem = new EditorStatusBarItem(); + statusLine.add(statusBarItem); + + Composite c = new Composite(parent, SWT.NONE); + c.setLayout(new FillLayout()); + + canvas = new Lwjgl3DCanvas(c); + canvas.addResizeHandler(this); + canvas.addMouseListener(this); + canvas.addMouseMoveListener(this); + canvas.addMouseTrackListener(this); + canvas.addMouseWheelListener(this); + canvas.addKeyListener(this); + + canvas.setCurrentAndUseContext(); + initializeGL(); + + renderThread = new Lwjgl3DRenderThread(canvas, renderCallback); + renderThread.start(); + } + + /** {@inheritDoc} */ + @Override + public void setFocus() { + canvas.setFocus(); + } + + /** {@inheritDoc} */ + @Override + public void mouseDoubleClick(MouseEvent e) { + // ignore + } + + /** {@inheritDoc} */ + @Override + public void mouseDown(MouseEvent e) { + // ignore + } + + /** {@inheritDoc} */ + @Override + public void mouseUp(MouseEvent e) { + // ignore + } + + /** {@inheritDoc} */ + @Override + public void mouseEnter(MouseEvent e) { + // ignore + } + + /** + * {@inheritDoc} + * <P> + * Resets the picking position to (-1, -1). + */ + @Override + public void mouseExit(MouseEvent e) { + pickX = -1; + pickY = -1; + } + + /** {@inheritDoc} */ + @Override + public void mouseHover(MouseEvent e) { + // ignore + } + + /** {@inheritDoc} */ + @Override + public void mouseMove(MouseEvent e) { + // ignore + } + + /** {@inheritDoc} */ + @Override + public void mouseScrolled(MouseEvent e) { + // ignore + } + + /** {@inheritDoc} */ + @Override + public void keyPressed(KeyEvent e) { + // ignore + } + + /** {@inheritDoc} */ + @Override + public void keyReleased(KeyEvent e) { + // ignore + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/light/Light.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/light/Light.java new file mode 100644 index 000000000..f8155d2c9 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/light/Light.java @@ -0,0 +1,96 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.light; + +import static org.fortiss.tooling.graphics3D.ui.util.FloatBufferUtils.toFloatBuffer; +import static org.fortiss.tooling.graphics3D.util.Graphics3DModelElementFactory.color; +import static org.lwjgl.opengl.GL11.GL_DIFFUSE; +import static org.lwjgl.opengl.GL11.GL_LIGHT0; +import static org.lwjgl.opengl.GL11.GL_POSITION; +import static org.lwjgl.opengl.GL11.GL_SPECULAR; +import static org.lwjgl.opengl.GL11.glDisable; +import static org.lwjgl.opengl.GL11.glEnable; +import static org.lwjgl.opengl.GL11.glLight; + +import java.nio.FloatBuffer; + +import org.fortiss.tooling.graphics3D.model.Color3D; + +/** + * Class representing a light source. It is initialized with a GL light number (GL_LIGHT0, ..., + * GL_LIGHT7) and a {@link Color3D}, which determines the light color for ambient and diffuse. + * Specular light is set to white. The default position is (10,10,10). + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: E66B9A1E36BB0871D1F6B8C171070154 + */ +public class Light { + + /** The GL_LIGHTx to be used. */ + private final int glLightNumber; + + /** Constructor. */ + public Light(int glLight, Color3D color) { + glLightNumber = glLight; + setLightColor(color); + setPosition(10.0f, 10.0f, 10.0f); + } + + /** Constructor using GL_LIGHT0 and white light color. */ + public Light() { + this(GL_LIGHT0, color(1.0f, 1.0f, 1.0f)); + } + + /** Constructor using GL_LIGHT0 and the given light color. */ + public Light(Color3D color) { + this(GL_LIGHT0, color); + } + + /** Sets the light color. */ + public final void setLightColor(Color3D color) { + diffuseColor = toFloatBuffer(color.getRed(), color.getGreen(), color.getBlue(), 1.0f); + specularColor = toFloatBuffer(1.0f, 1.0f, 1.0f, 1.0f); + } + + /** The position. */ + private FloatBuffer lightPosition; + /** The diffuse color. */ + private FloatBuffer diffuseColor; + /** The specular color. */ + private FloatBuffer specularColor; + + /** Enables the light in GL. */ + public void enableLight() { + glEnable(glLightNumber); + glLight(glLightNumber, GL_POSITION, lightPosition); + glLight(glLightNumber, GL_DIFFUSE, diffuseColor); + glLight(glLightNumber, GL_SPECULAR, specularColor); + } + + /** Disables the light in GL. */ + public void disableLight() { + glDisable(glLightNumber); + } + + /** Sets the light position. */ + public void setPosition(float x, float y, float z) { + lightPosition = toFloatBuffer(new float[] {x, y, z, 1.0f}); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/light/Light3DLight.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/light/Light3DLight.java new file mode 100644 index 000000000..0d15cb367 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/light/Light3DLight.java @@ -0,0 +1,56 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.light; + +import static org.lwjgl.opengl.GL11.glDisable; + +import org.fortiss.tooling.graphics3D.model.scene.Light3D; +import org.fortiss.tooling.graphics3D.ui.util.GLPrimitives; + +/** + * Class representing a light source based on the model object of class {@link Light3D}. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 9F494319806A2DB44419BB8D51E0B430 + */ +public class Light3DLight { + + /** The GL_LIGHTx to be used. */ + private final int glLightNumber; + + /** The light model. */ + private final Light3D lightModel; + + /** Constructor. */ + public Light3DLight(int glLight, Light3D lightModel) { + this.glLightNumber = glLight; + this.lightModel = lightModel; + } + + /** Enables the light in GL. */ + public void enableLight() { + GLPrimitives.enableLight(glLightNumber, lightModel); + } + + /** Disables the light in GL. */ + public void disableLight() { + glDisable(glLightNumber); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/CompositeViewObject.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/CompositeViewObject.java new file mode 100644 index 000000000..433b0873c --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/CompositeViewObject.java @@ -0,0 +1,53 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.objects; + +import java.util.ArrayList; +import java.util.List; + +import org.fortiss.tooling.graphics3D.ui.picker.ModelObjectPicker; + +/** + * Composite for {@link ViewObjectBase model objects} forwarding rendering and picking calls to + * component objects. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: D3F8BDCBB89A0D376ED987F07023EC68 + */ +public class CompositeViewObject extends ViewObjectBase { + /** The component objects. */ + private final List<ViewObjectBase> objects = new ArrayList<ViewObjectBase>(); + + /** {@inheritDoc} */ + @Override + public void renderObject() { + for(ViewObjectBase o : objects) { + o.renderObject(); + } + } + + /** {@inheritDoc} */ + @Override + public void renderObjectForPicking(ModelObjectPicker picker) { + for(ViewObjectBase o : objects) { + o.renderObjectForPicking(picker); + } + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/Graph3DViewObject.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/Graph3DViewObject.java new file mode 100644 index 000000000..3d31283b6 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/Graph3DViewObject.java @@ -0,0 +1,133 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.objects; + +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.drawLine; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.flushName; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.moveTo; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.prepareName; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.restoreMatrix; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.saveMatrix; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.setColor; +import static org.fortiss.tooling.graphics3D.util.Graphics3DModelElementFactory.RED; +import static org.fortiss.tooling.graphics3D.util.Graphics3DModelElementFactory.WHITE; +import static org.lwjgl.util.glu.GLU.GLU_FILL; + +import org.fortiss.tooling.graphics3D.model.Color3D; +import org.fortiss.tooling.graphics3D.model.graph.Axis3D; +import org.fortiss.tooling.graphics3D.model.graph.CoordinateSystem3D; +import org.fortiss.tooling.graphics3D.model.graph.Graph3D; +import org.fortiss.tooling.graphics3D.model.graph.GraphLine3D; +import org.fortiss.tooling.graphics3D.model.graph.GraphPoint3D; +import org.fortiss.tooling.graphics3D.ui.picker.ModelObjectPicker; +import org.lwjgl.util.glu.Sphere; + +/** + * View object for {@link Graph3D}. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 7EFCEC92BBCFB59C5C1BEA5F9F2ABFD3 + */ +public class Graph3DViewObject extends ViewObjectBase { + /** The graph model. */ + private final Graph3D graph; + + /** The highlighted model object. */ + private GraphPoint3D highlighted; + + /** Constructor. */ + public Graph3DViewObject(Graph3D graph) { + this.graph = graph; + } + + /** Sets the currently highlighted point. */ + public void setHighlightedPoint(GraphPoint3D point) { + highlighted = point; + } + + /** {@inheritDoc} */ + @Override + public void renderObject() { + renderCoordSys(graph.getCoordinateSystem()); + setColor(WHITE); + for(GraphPoint3D p : graph.getPointsList()) { + if(p == highlighted) { + setColor(RED); + renderPoint(p); + setColor(WHITE); + } else { + renderPoint(p); + } + } + for(GraphLine3D l : graph.getLinesList()) { + drawLine(l.getStart().getPosition(), l.getEnd().getPosition()); + } + } + + /** {@inheritDoc} */ + @Override + public void renderObjectForPicking(ModelObjectPicker picker) { + // only points are pickable + for(GraphPoint3D p : graph.getPointsList()) { + prepareName(p, picker); + renderPoint(p); + flushName(); + } + } + + /** The GLU sphere used for {@link GraphPoint3D} rendering. */ + private static Sphere SPHERE = new Sphere(); + + static { + SPHERE.setDrawStyle(GLU_FILL); + } + + /** Renders the given point. */ + private void renderPoint(GraphPoint3D p) { + saveMatrix(); + moveTo(p.getPosition()); + SPHERE.draw(0.2f, 9, 4); + restoreMatrix(); + } + + /** Renders the coordinate system if present. */ + private void renderCoordSys(CoordinateSystem3D coordinateSystem) { + if(coordinateSystem != null) { + if(coordinateSystem.getXAxis() != null) { + Axis3D a = coordinateSystem.getXAxis(); + renderAxis(a.getColor(), a.getLength(), 0, 0); + } + if(coordinateSystem.getYAxis() != null) { + Axis3D a = coordinateSystem.getYAxis(); + renderAxis(a.getColor(), 0, a.getLength(), 0); + } + if(coordinateSystem.getZAxis() != null) { + Axis3D a = coordinateSystem.getZAxis(); + renderAxis(a.getColor(), 0, 0, a.getLength()); + } + } + } + + /** Renders the axis. */ + private void renderAxis(Color3D color, float x, float y, float z) { + setColor(color); + drawLine(0, 0, 0, x, y, z); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/Object3DViewObject.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/Object3DViewObject.java new file mode 100644 index 000000000..ccfe23e7c --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/Object3DViewObject.java @@ -0,0 +1,46 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.objects; + +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.drawMaterialGroups; + +import org.fortiss.tooling.graphics3D.model.scene.Object3D; + +/** + * {@link ViewObjectBase} instance for {@link Object3D} models. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 277D271D3EED34F7CEBDA245836C1528 + */ +public class Object3DViewObject extends ViewObjectBase { + /** The model object. */ + private final Object3D model; + + /** Constructor. */ + public Object3DViewObject(Object3D model) { + this.model = model; + } + + /** {@inheritDoc} */ + @Override + public void renderObject() { + drawMaterialGroups(model.getMesh().getMaterialGroupsList()); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/PickableObjectBase.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/PickableObjectBase.java new file mode 100644 index 000000000..7530b3fd2 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/PickableObjectBase.java @@ -0,0 +1,54 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.objects; + +import static org.lwjgl.opengl.GL11.glPopName; +import static org.lwjgl.opengl.GL11.glPushName; + +import org.fortiss.tooling.graphics3D.ui.picker.ModelObjectPicker; + +/** + * Base class for {@link ViewObjectBase view objects}, which become pickable by the + * {@link ModelObjectPicker}. Sub-classes may override {@link #renderSimplifiedPickableObject()} to + * provide a simpler shape during the picking render process. The default renders the same object as + * {@link #renderObject()}. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: DD1E015FD10F45DD24F4A92F67902F33 + */ +public abstract class PickableObjectBase extends ViewObjectBase { + + /** {@inheritDoc} */ + @Override + public final void renderObjectForPicking(ModelObjectPicker picker) { + int name = picker.registerPickableObject(this); + glPushName(name); + renderSimplifiedPickableObject(); + glPopName(); + } + + /** + * Renders this object in a simplified version for picking. The default just renders the object + * as usual. Sub-classes may override to provide simpler shapes. + */ + protected void renderSimplifiedPickableObject() { + renderObject(); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/RotatedObject.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/RotatedObject.java new file mode 100644 index 000000000..72841c6fc --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/RotatedObject.java @@ -0,0 +1,60 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.objects; + +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.restoreMatrix; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.rotate; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.saveMatrix; + +import org.lwjgl.util.vector.Vector3f; + +/** + * Rotates the wrapped object by the given angle at the origin. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: A447FB4D5DC5307470D36A7347352A16 + */ +public class RotatedObject extends WrappedViewObjectBase { + /** The rotation angle. */ + private float angle; + + /** The rotation axis. */ + private final Vector3f axis; + + /** Constructor. */ + public RotatedObject(ViewObjectBase wrapped, float angle, Vector3f axis) { + super(wrapped); + this.angle = angle; + this.axis = axis; + } + + /** {@inheritDoc} */ + @Override + protected void preRendering() { + saveMatrix(); + rotate(angle, axis); + } + + /** {@inheritDoc} */ + @Override + protected void postRendering() { + restoreMatrix(); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/ScaledObject.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/ScaledObject.java new file mode 100644 index 000000000..9d41cf8cb --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/ScaledObject.java @@ -0,0 +1,56 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.objects; + +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.restoreMatrix; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.saveMatrix; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.scale; + +import org.lwjgl.util.vector.Vector3f; + +/** + * Scales the wrapped object by the given factor. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 57BE199D8FDF27A1D0F615CD53FCD32F + */ +public class ScaledObject extends WrappedViewObjectBase { + /** The scale factor. */ + private Vector3f scaleFactor; + + /** Constructor. */ + public ScaledObject(ViewObjectBase wrapped, Vector3f factor) { + super(wrapped); + this.scaleFactor = factor; + } + + /** {@inheritDoc} */ + @Override + protected void preRendering() { + saveMatrix(); + scale(scaleFactor); + } + + /** {@inheritDoc} */ + @Override + protected void postRendering() { + restoreMatrix(); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/ViewObjectBase.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/ViewObjectBase.java new file mode 100644 index 000000000..e9dc2856b --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/ViewObjectBase.java @@ -0,0 +1,46 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.objects; + +import org.fortiss.tooling.graphics3D.ui.picker.ModelObjectPicker; + +/** + * Base class for 3D view objects. View objects support two methods for rendering in view and in + * picking mode. The default does not render the object in picking mode. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: C970B9D2F1FF5088B0E7494BE10DA692 + */ +public abstract class ViewObjectBase { + + /** Renders the object. */ + public abstract void renderObject(); + + /** + * Renders the object in picking mode using the given picker. The default renders nothing. + * Sub-classes should override if they represent a pickable object. + * + * @param picker + * the picker requesting a picker rendering run + */ + public void renderObjectForPicking(ModelObjectPicker picker) { + // render nothing + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/WrappedViewObjectBase.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/WrappedViewObjectBase.java new file mode 100644 index 000000000..0820e9757 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/objects/WrappedViewObjectBase.java @@ -0,0 +1,51 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.objects; + +/** + * View object that wraps another object and can provide pre- and post-processing. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 95B8591C26D12367FE0E12C01183EA7B + */ +public abstract class WrappedViewObjectBase extends ViewObjectBase { + + /** The wrapped model object. */ + protected final ViewObjectBase wrapped; + + /** Constructor. */ + public WrappedViewObjectBase(ViewObjectBase wrapped) { + this.wrapped = wrapped; + } + + /** Called before rendering the wrapped object. */ + protected abstract void preRendering(); + + /** Called after rendering the wrapped object. */ + protected abstract void postRendering(); + + /** {@inheritDoc} */ + @Override + public final void renderObject() { + preRendering(); + wrapped.renderObject(); + postRendering(); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/picker/ModelObjectPicker.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/picker/ModelObjectPicker.java new file mode 100644 index 000000000..ddfb17360 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/picker/ModelObjectPicker.java @@ -0,0 +1,140 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.picker; + +import static org.lwjgl.BufferUtils.createIntBuffer; +import static org.lwjgl.opengl.GL11.GL_LIGHTING; +import static org.lwjgl.opengl.GL11.GL_MODELVIEW; +import static org.lwjgl.opengl.GL11.GL_PROJECTION; +import static org.lwjgl.opengl.GL11.GL_RENDER; +import static org.lwjgl.opengl.GL11.GL_SELECT; +import static org.lwjgl.opengl.GL11.GL_TEXTURE; +import static org.lwjgl.opengl.GL11.GL_VIEWPORT; +import static org.lwjgl.opengl.GL11.glDisable; +import static org.lwjgl.opengl.GL11.glGetInteger; +import static org.lwjgl.opengl.GL11.glInitNames; +import static org.lwjgl.opengl.GL11.glLoadIdentity; +import static org.lwjgl.opengl.GL11.glMatrixMode; +import static org.lwjgl.opengl.GL11.glPopMatrix; +import static org.lwjgl.opengl.GL11.glPushMatrix; +import static org.lwjgl.opengl.GL11.glRenderMode; +import static org.lwjgl.opengl.GL11.glSelectBuffer; +import static org.lwjgl.util.glu.GLU.gluPerspective; +import static org.lwjgl.util.glu.GLU.gluPickMatrix; + +import java.nio.IntBuffer; +import java.util.HashMap; +import java.util.Map; + +import org.fortiss.tooling.graphics3D.ui.camera.Camera; +import org.fortiss.tooling.graphics3D.ui.objects.ViewObjectBase; +import org.lwjgl.util.vector.Vector3f; + +/** + * Picker implementation for model objects using GL select mode rendering. + * {@link #pickModelObject(int, int, Vector3f, ViewObjectBase)} returns the nearest object. All + * others are discarded. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 4F5B62FD35DFAAEAE994F1C76A03CA27 + */ +public final class ModelObjectPicker { + /** The buffer size for pickable objects. */ + private static final int BUFFER_SIZE = 1024; + + /** The selection buffer. */ + private final IntBuffer selectBuffer = createIntBuffer(BUFFER_SIZE); + /** The viewport buffer. */ + private final IntBuffer viewport = createIntBuffer(16); + + /** The pickable object registry. */ + private final Map<Integer, Object> objectRegistry = new HashMap<Integer, Object>(); + + /** The registry counter. */ + private int registryCounter = 1; + + /** Registers the given object for the current picker run. */ + public int registerPickableObject(Object object) { + int name = registryCounter; + objectRegistry.put(name, object); + registryCounter++; + return name; + } + + /** + * Performs the picking process for the given {@link ViewObjectBase} from the given + * {@link Camera}s view at the given location and returns the picking result or {@code null} if + * nothing was hit. + */ + public Object pickModelObject(int x, int y, Vector3f perspective, ViewObjectBase scene) { + // reset picker + objectRegistry.clear(); + registryCounter = 1; + viewport.clear(); + selectBuffer.clear(); + + glGetInteger(GL_VIEWPORT, viewport); + float aspect = + (float)(viewport.get(2) - viewport.get(0)) / + (float)(viewport.get(3) - viewport.get(1)); + + glSelectBuffer(selectBuffer); + glRenderMode(GL_SELECT); + glInitNames(); + + // setup perspective + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + gluPickMatrix(x, viewport.get(3) - y, 5.0f, 5.0f, viewport); + gluPerspective(perspective.x, aspect, perspective.y, perspective.z); + + // render objects in picking mode + glMatrixMode(GL_MODELVIEW); + glDisable(GL_TEXTURE); + glDisable(GL_LIGHTING); + scene.renderObjectForPicking(this); + + // restore projection matrix + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + + // return to render mode to count hits + int hits = glRenderMode(GL_RENDER); + if(hits > 0) { + int name = selectBuffer.get(3); + int depth = selectBuffer.get(1); + + for(int i = 1; i < hits; i++) { + int idx = i * 4; + int nDepth = selectBuffer.get(idx + 1); + if(nDepth < depth) { + name = selectBuffer.get(idx + 3); + depth = nDepth; + } + } + if(name > 0) { + return objectRegistry.get(name); + } + } + return null; + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/util/FloatBufferUtils.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/util/FloatBufferUtils.java new file mode 100644 index 000000000..bad80a2d8 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/util/FloatBufferUtils.java @@ -0,0 +1,89 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.util; + +import static org.lwjgl.BufferUtils.createFloatBuffer; + +import java.nio.FloatBuffer; + +import org.fortiss.tooling.graphics3D.model.Color3D; +import org.fortiss.tooling.graphics3D.model.Vector3D; + +/** + * Utility methods for handling {@link FloatBuffer} more easily. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: AFD0F65604F06A6F752C5EEB538EC5A4 + */ +public class FloatBufferUtils { + /** Creates a float buffer for the given value array. */ + public static FloatBuffer toFloatBuffer(float[] f) { + FloatBuffer buf = createFloatBuffer(f.length); + buf.put(f); + buf.flip(); + return buf; + } + + /** Creates a float buffer for the given value array. */ + public static FloatBuffer toFloatBuffer(float x, float y, float z) { + FloatBuffer buf = createFloatBuffer(3); + buf.put(x).put(y).put(z).flip(); + return buf; + } + + /** Creates a float buffer for the given value array. */ + public static FloatBuffer toFloatBuffer(float x, float y, float z, float w) { + FloatBuffer buf = createFloatBuffer(4); + buf.put(x).put(y).put(z).put(w).flip(); + return buf; + } + + /** Creates a 3-element float buffer for the given {@link Vector3D}. */ + public static FloatBuffer toFloatBuffer(Vector3D vec) { + if(vec == null) { + return toFloatBuffer(0, 0, 0); + } + return toFloatBuffer(vec.getX(), vec.getY(), vec.getZ()); + } + + /** Creates a 4-element float buffer for the given {@link Vector3D} and the additional element. */ + public static FloatBuffer toFloatBuffer(Vector3D vec, float w) { + if(vec == null) { + return toFloatBuffer(0, 0, 0, 0); + } + return toFloatBuffer(vec.getX(), vec.getY(), vec.getZ(), w); + } + + /** Creates a 3-element float buffer for the given {@link Vector3D}. */ + public static FloatBuffer toFloatBuffer(Color3D vec) { + if(vec == null) { + return toFloatBuffer(0, 0, 0); + } + return toFloatBuffer(vec.getRed(), vec.getGreen(), vec.getBlue()); + } + + /** Creates a 4-element float buffer for the given {@link Vector3D} and the additional element. */ + public static FloatBuffer toFloatBuffer(Color3D vec, float w) { + if(vec == null) { + return toFloatBuffer(0, 0, 0, 0); + } + return toFloatBuffer(vec.getRed(), vec.getGreen(), vec.getBlue(), w); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/util/GLPrimitives.java b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/util/GLPrimitives.java new file mode 100644 index 000000000..885820342 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/src/org/fortiss/tooling/graphics3D/ui/util/GLPrimitives.java @@ -0,0 +1,308 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.graphics3D.ui.util; + +import static org.fortiss.tooling.graphics3D.ui.util.FloatBufferUtils.toFloatBuffer; +import static org.fortiss.tooling.graphics3D.util.Mesh3DModelElementFactory.DEFAULT_MATERIAL; +import static org.lwjgl.BufferUtils.createFloatBuffer; +import static org.lwjgl.opengl.GL11.GL_AMBIENT; +import static org.lwjgl.opengl.GL11.GL_AMBIENT_AND_DIFFUSE; +import static org.lwjgl.opengl.GL11.GL_BACK; +import static org.lwjgl.opengl.GL11.GL_COLOR_MATERIAL; +import static org.lwjgl.opengl.GL11.GL_CULL_FACE; +import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST; +import static org.lwjgl.opengl.GL11.GL_DIFFUSE; +import static org.lwjgl.opengl.GL11.GL_FLAT; +import static org.lwjgl.opengl.GL11.GL_FRONT; +import static org.lwjgl.opengl.GL11.GL_LIGHTING; +import static org.lwjgl.opengl.GL11.GL_LIGHT_MODEL_AMBIENT; +import static org.lwjgl.opengl.GL11.GL_LINES; +import static org.lwjgl.opengl.GL11.GL_MODELVIEW; +import static org.lwjgl.opengl.GL11.GL_NICEST; +import static org.lwjgl.opengl.GL11.GL_PERSPECTIVE_CORRECTION_HINT; +import static org.lwjgl.opengl.GL11.GL_POSITION; +import static org.lwjgl.opengl.GL11.GL_SHININESS; +import static org.lwjgl.opengl.GL11.GL_SMOOTH; +import static org.lwjgl.opengl.GL11.GL_SPECULAR; +import static org.lwjgl.opengl.GL11.GL_TRIANGLES; +import static org.lwjgl.opengl.GL11.glBegin; +import static org.lwjgl.opengl.GL11.glClear; +import static org.lwjgl.opengl.GL11.glClearColor; +import static org.lwjgl.opengl.GL11.glClearDepth; +import static org.lwjgl.opengl.GL11.glColor3f; +import static org.lwjgl.opengl.GL11.glColorMaterial; +import static org.lwjgl.opengl.GL11.glCullFace; +import static org.lwjgl.opengl.GL11.glDisable; +import static org.lwjgl.opengl.GL11.glEnable; +import static org.lwjgl.opengl.GL11.glEnd; +import static org.lwjgl.opengl.GL11.glGetFloat; +import static org.lwjgl.opengl.GL11.glHint; +import static org.lwjgl.opengl.GL11.glLight; +import static org.lwjgl.opengl.GL11.glLightModel; +import static org.lwjgl.opengl.GL11.glLineWidth; +import static org.lwjgl.opengl.GL11.glLoadIdentity; +import static org.lwjgl.opengl.GL11.glMaterial; +import static org.lwjgl.opengl.GL11.glMaterialf; +import static org.lwjgl.opengl.GL11.glMatrixMode; +import static org.lwjgl.opengl.GL11.glNormal3f; +import static org.lwjgl.opengl.GL11.glPopMatrix; +import static org.lwjgl.opengl.GL11.glPopName; +import static org.lwjgl.opengl.GL11.glPushMatrix; +import static org.lwjgl.opengl.GL11.glPushName; +import static org.lwjgl.opengl.GL11.glRotatef; +import static org.lwjgl.opengl.GL11.glScalef; +import static org.lwjgl.opengl.GL11.glShadeModel; +import static org.lwjgl.opengl.GL11.glTranslatef; +import static org.lwjgl.opengl.GL11.glVertex3f; + +import java.nio.FloatBuffer; +import java.util.List; + +import org.fortiss.tooling.graphics3D.model.Color3D; +import org.fortiss.tooling.graphics3D.model.Vector3D; +import org.fortiss.tooling.graphics3D.model.mesh.Face3D; +import org.fortiss.tooling.graphics3D.model.mesh.Material3D; +import org.fortiss.tooling.graphics3D.model.mesh.MaterialGroup3D; +import org.fortiss.tooling.graphics3D.model.mesh.Normal3D; +import org.fortiss.tooling.graphics3D.model.mesh.Vertex3D; +import org.fortiss.tooling.graphics3D.model.scene.Light3D; +import org.fortiss.tooling.graphics3D.ui.picker.ModelObjectPicker; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.vector.Vector3f; +import org.lwjgl.util.vector.Vector4f; +import org.newdawn.slick.Color; + +/** + * Utility class for GL primitives like setting colors, drawing lines, triangles, quads, etc. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 29BEEFDEA81964C64956C3DF00EEF580 + */ +public class GLPrimitives { + /** The X unit vector. */ + public static Vector3f X_UNIT_VECTOR = new Vector3f(1.0f, 0, 0); + /** The Y unit vector. */ + public static Vector3f Y_UNIT_VECTOR = new Vector3f(0, 1.0f, 0); + /** The Z unit vector. */ + public static Vector3f Z_UNIT_VECTOR = new Vector3f(0, 0, 1.0f); + + /** The GL_LIGHTx array. */ + public static final int[] GL_LIGHT_NUMBER = new int[] {GL11.GL_LIGHT0, GL11.GL_LIGHT1, + GL11.GL_LIGHT2, GL11.GL_LIGHT3, GL11.GL_LIGHT4, GL11.GL_LIGHT5, GL11.GL_LIGHT6, + GL11.GL_LIGHT7}; + + /** Initializes basic GL properties. */ + public static void initializeGL() { + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glColor3f(1.0f, 0.0f, 0.0f); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glClearDepth(1.0); + glLineWidth(2); + glEnable(GL_DEPTH_TEST); + } + + /** Returns the current transformed origin in model view coordinates in the given vector. */ + public static Vector3f getTransformedOrigin() { + FloatBuffer fb = createFloatBuffer(16); + glGetFloat(GL_MODELVIEW, fb); + return new Vector3f(fb.get(12), fb.get(13), fb.get(14)); + } + + /** Sets the current color. */ + public static void setColor(Color color) { + glColor3f(color.r, color.g, color.b); + } + + /** Sets the current color. */ + public static void setColor(Color3D color) { + glColor3f(color.getRed(), color.getGreen(), color.getBlue()); + } + + /** Applies the given translation. */ + public static void translate(Vector3f t) { + glTranslatef(t.getX(), t.getY(), t.getZ()); + } + + /** Applies the given translation. */ + public static void translate(float x, float y, float z) { + glTranslatef(x, y, z); + } + + /** Applies the given scaling factor. */ + public static void scale(Vector3f scale) { + glScalef(scale.x, scale.y, scale.z); + } + + /** Applies the given rotation angle to the axis. */ + public static void rotate(Vector4f axisAndAngle) { + glRotatef(axisAndAngle.w, axisAndAngle.x, axisAndAngle.y, axisAndAngle.z); + } + + /** Applies the given rotation angle to the given axis. */ + public static void rotate(float angle, Vector3f axis) { + glRotatef(angle, axis.x, axis.y, axis.z); + } + + /** Draws a line between the two vertices. */ + public static void drawLine(Vector3f v1, Vector3f v2) { + drawLine(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z); + } + + /** Draws a line between the two points. */ + public static void drawLine(Vector3D p1, Vector3D p2) { + drawLine(p1.getX(), p1.getY(), p1.getZ(), p2.getX(), p2.getY(), p2.getZ()); + } + + /** Draws a line between the two points. */ + public static void drawLine(float x1, float y1, float z1, float x2, float y2, float z2) { + glBegin(GL_LINES); + glVertex3f(x1, y1, z1); + glVertex3f(x2, y2, z2); + glEnd(); + } + + /** Draws the given list of material groups. */ + public static void drawMaterialGroups(List<MaterialGroup3D> groups) { + for(MaterialGroup3D g : groups) { + Material3D mat = g.getMaterial() == null ? DEFAULT_MATERIAL : g.getMaterial(); + setMaterial(mat); + setSmoothShading(g.isSmoothShading()); + drawTriangleFaces(g.getFacesList()); + } + } + + /** Draws the given list of {@link Face3D}s with triangle information. */ + public static void drawTriangleFaces(List<Face3D> faces) { + glBegin(GL_TRIANGLES); + for(Face3D f : faces) { + boolean useNormals = f.getNormalsLength() == 3; + for(int i = 0; i < 3; i++) { + if(useNormals) { + Normal3D n = f.getNormals(i); + glNormal3f(n.getX(), n.getY(), n.getZ()); + } + Vertex3D v = f.getVertices(i); + glVertex3f(v.getX(), v.getY(), v.getZ()); + } + } + glEnd(); + } + + /** Saves the current matrix state. */ + public static void saveMatrix() { + glPushMatrix(); + } + + /** Restores the current matrix state. */ + public static void restoreMatrix() { + glPopMatrix(); + } + + /** Translates the matrix to the given coordinates. */ + public static void moveTo(Vector3f coords) { + glTranslatef(coords.x, coords.y, coords.z); + } + + /** Translates the matrix to the given coordinates. */ + public static void moveTo(Vector3D coords) { + glTranslatef(coords.getX(), coords.getY(), coords.getZ()); + } + + /** Sets the current material data for GL_FRONT faces. */ + public static void setMaterial(FloatBuffer ambient, FloatBuffer diffuse, FloatBuffer specular, + float specularCoeff) { + glDisable(GL_COLOR_MATERIAL); + glMaterial(GL_FRONT, GL_AMBIENT, ambient); + glMaterial(GL_FRONT, GL_DIFFUSE, diffuse); + glMaterial(GL_FRONT, GL_SPECULAR, specular); + glMaterialf(GL_FRONT, GL_SHININESS, specularCoeff); + } + + /** Sets the current material data for GL_FRONT faces. */ + public static void setMaterial(Material3D mat) { + setMaterial(toFloatBuffer(mat.getAmbient(), 1.0f), toFloatBuffer(mat.getDiffuse(), 1.0f), + toFloatBuffer(mat.getSpecular(), 1.0f), mat.getSpecularCoeff()); + } + + /** Enables the light with the given number and properties. */ + public static void enableLight(int glLightNumber, FloatBuffer lightPosition, + FloatBuffer ambient, FloatBuffer diffuse, FloatBuffer specular) { + glEnable(glLightNumber); + glLight(glLightNumber, GL_POSITION, lightPosition); + glLight(glLightNumber, GL_AMBIENT, ambient); + glLight(glLightNumber, GL_DIFFUSE, diffuse); + glLight(glLightNumber, GL_SPECULAR, specular); + } + + /** Enables the given light with the given number and model data. */ + public static void enableLight(int glLightNumber, Light3D light) { + enableLight(glLightNumber, toFloatBuffer(light.getPosition(), 1.0f), + toFloatBuffer(light.getAmbient(), 1.0f), toFloatBuffer(light.getDiffuse(), 1.0f), + toFloatBuffer(light.getSpecular(), 1.0f)); + } + + /** Clears the canvas with the given RGB color. */ + public static void clearCanvasAndLoadIdentity(Color color) { + glMatrixMode(GL_MODELVIEW); + glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); + glClearColor(color.r, color.g, color.b, 1.0f); + loadIdentity(); + } + + /** Loads the identity matrix. */ + public static void loadIdentity() { + glLoadIdentity(); + } + + /** Prepare a name for the given object and picker. */ + public static void prepareName(Object obj, ModelObjectPicker picker) { + int name = picker.registerPickableObject(obj); + glPushName(name); + } + + /** Flushes the last name. */ + public static void flushName() { + glPopName(); + } + + /** Enables culling for back polygons (i.e. only front faces are considered for lighting. */ + public static void enableBackCulling() { + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + } + + /** Enables lighting with the given ambient intensity. */ + public static void enableLighting(Color3D col) { + glEnable(GL_LIGHTING); + FloatBuffer ambient = toFloatBuffer(col.getRed(), col.getGreen(), col.getBlue(), 1.0f); + glLightModel(GL_LIGHT_MODEL_AMBIENT, ambient); + } + + /** Enables color material for front faces and ambient and diffuse light components. */ + public static void enableColorMaterial() { + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); + } + + /** Sets the smoothness shading mode. */ + public static void setSmoothShading(boolean smooth) { + glShadeModel(smooth ? GL_SMOOTH : GL_FLAT); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/test-src/test/org/fortiss/tooling/graphics3D/ui/Test3DEditor.java b/org.fortiss.tooling.graphicsGL.ui/trunk/test-src/test/org/fortiss/tooling/graphics3D/ui/Test3DEditor.java new file mode 100644 index 000000000..c0c837a6a --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/test-src/test/org/fortiss/tooling/graphics3D/ui/Test3DEditor.java @@ -0,0 +1,213 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package test.org.fortiss.tooling.graphics3D.ui; + +import static org.eclipse.swt.SWT.ARROW_DOWN; +import static org.eclipse.swt.SWT.ARROW_LEFT; +import static org.eclipse.swt.SWT.ARROW_RIGHT; +import static org.eclipse.swt.SWT.ARROW_UP; +import static org.eclipse.swt.SWT.PAGE_DOWN; +import static org.eclipse.swt.SWT.PAGE_UP; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.enableColorMaterial; +import static org.fortiss.tooling.graphics3D.ui.util.GLPrimitives.enableLighting; +import static org.fortiss.tooling.graphics3D.util.Graph3DModelElementFactory.axis; +import static org.fortiss.tooling.graphics3D.util.Graph3DModelElementFactory.coordSystem; +import static org.fortiss.tooling.graphics3D.util.Graph3DModelElementFactory.graph; +import static org.fortiss.tooling.graphics3D.util.Graph3DModelElementFactory.graphLine; +import static org.fortiss.tooling.graphics3D.util.Graph3DModelElementFactory.graphPoint; +import static org.fortiss.tooling.graphics3D.util.Graphics3DModelElementFactory.BLUE; +import static org.fortiss.tooling.graphics3D.util.Graphics3DModelElementFactory.GREEN; +import static org.fortiss.tooling.graphics3D.util.Graphics3DModelElementFactory.RED; +import static org.fortiss.tooling.graphics3D.util.Graphics3DModelElementFactory.WHITE; +import static org.fortiss.tooling.graphics3D.util.Graphics3DModelElementFactory.color; +import static org.fortiss.tooling.graphics3D.util.Scene3DModelElementFactory.light3D; +import static org.lwjgl.opengl.GL11.GL_LIGHT0; +import static org.lwjgl.opengl.GL11.GL_LIGHT1; +import static org.lwjgl.opengl.GL11.GL_LIGHT2; +import static org.lwjgl.opengl.GL11.GL_LIGHT3; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.MouseEvent; +import org.fortiss.tooling.graphics3D.model.Color3D; +import org.fortiss.tooling.graphics3D.model.Vector3D; +import org.fortiss.tooling.graphics3D.model.graph.CoordinateSystem3D; +import org.fortiss.tooling.graphics3D.model.graph.Graph3D; +import org.fortiss.tooling.graphics3D.model.graph.GraphLine3D; +import org.fortiss.tooling.graphics3D.model.graph.GraphPoint3D; +import org.fortiss.tooling.graphics3D.ui.camera.Camera; +import org.fortiss.tooling.graphics3D.ui.camera.MovingCameraWithPitchAndYaw; +import org.fortiss.tooling.graphics3D.ui.editor.Graphical3DEditorBase; +import org.fortiss.tooling.graphics3D.ui.light.Light3DLight; +import org.fortiss.tooling.graphics3D.ui.objects.Graph3DViewObject; +import org.fortiss.tooling.graphics3D.ui.objects.ViewObjectBase; +import org.fortiss.tooling.kernel.model.IProjectRootElement; + +/** + * Test editor for 3d canvas display. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: C1DEE860EDFB7F388FEECC831432B425 + */ +public class Test3DEditor extends Graphical3DEditorBase<IProjectRootElement> { + /** The ambient intensity. */ + private static final Color3D AMBIENT_INTENSITY = color(0.8f, 0.8f, 0.8f); + + /** The axis length. */ + private static final float AXIS_LENGTH = 20.0f; + + /** Origin light. */ + private Light3DLight oLight = new Light3DLight(GL_LIGHT0, light3D(0, 0, 0, WHITE)); + + /** X axis light. */ + private Light3DLight xLight = new Light3DLight(GL_LIGHT1, light3D(AXIS_LENGTH, 0, 0, RED)); + + /** Y axis light. */ + private Light3DLight yLight = new Light3DLight(GL_LIGHT2, light3D(0, AXIS_LENGTH, 0, GREEN)); + + /** Z axis light. */ + private Light3DLight zLight = new Light3DLight(GL_LIGHT3, light3D(0, 0, AXIS_LENGTH, BLUE)); + + /** The camera. */ + private MovingCameraWithPitchAndYaw camera = new MovingCameraWithPitchAndYaw(); + + /** The graph model. */ + private Graph3D graphModel; + + /** The graph display. */ + private Graph3DViewObject graphDisplay; + + /** Constructor. */ + public Test3DEditor() { + setupTestData(); + graphDisplay = new Graph3DViewObject(graphModel); + camera.setPosition(1.0f, 1.0f, 1.0f); + } + + /** {@inheritDoc} */ + @Override + protected void beginRenderLoop() { + enableLighting(AMBIENT_INTENSITY); + oLight.enableLight(); + xLight.enableLight(); + yLight.enableLight(); + zLight.enableLight(); + enableColorMaterial(); + } + + /** {@inheritDoc} */ + @Override + protected ViewObjectBase getSceneModelObject() { + return graphDisplay; + } + + /** {@inheritDoc} */ + @Override + protected Camera getCamera() { + return camera; + } + + /** {@inheritDoc} */ + @Override + public void mouseDoubleClick(MouseEvent e) { + // camera.switchLight(); + } + + /** {@inheritDoc} */ + @Override + public void mouseMove(MouseEvent e) { + pickX = e.x; + pickY = e.y; + // statusBarItem.setText("moved to " + pickX + ":" + pickY); + } + + /** {@inheritDoc} */ + @Override + protected void pickTargetChanged() { + if(pickTarget instanceof GraphPoint3D) { + GraphPoint3D p = (GraphPoint3D)pickTarget; + graphDisplay.setHighlightedPoint(p); + Vector3D v = p.getPosition(); + statusBarItem.setText("x:" + v.getX() + ",y:" + v.getY() + ",z:" + v.getZ()); + } + } + + /** {@inheritDoc} */ + @Override + public void keyReleased(KeyEvent e) { + float speed = 0.5f; + switch(e.keyCode) { + case ARROW_UP: + camera.forward(speed); + break; + case ARROW_DOWN: + camera.backward(speed); + break; + case ARROW_RIGHT: + camera.right(speed); + break; + case ARROW_LEFT: + camera.left(speed); + break; + case PAGE_UP: + camera.up(speed); + break; + case PAGE_DOWN: + camera.down(speed); + break; + } + switch(e.character) { + case 'w': + camera.pitch(15.0f); + break; + case 's': + camera.pitch(-15.0f); + break; + case 'a': + camera.yaw(-15.0f); + break; + case 'd': + camera.yaw(15.0f); + break; + } + } + + /** Setup test data for graph. */ + private void setupTestData() { + // setup test data + List<GraphPoint3D> pts = new ArrayList<GraphPoint3D>(); + List<GraphLine3D> lns = new ArrayList<GraphLine3D>(); + GraphPoint3D last = null; + for(float i = 1; i < 10; i++) { + GraphPoint3D current = graphPoint(i, i, i > 5 ? 10 - i : i); + pts.add(current); + if(last != null) { + lns.add(graphLine(last, current)); + } + last = current; + } + CoordinateSystem3D sys = + coordSystem(axis(AXIS_LENGTH, RED), axis(AXIS_LENGTH, GREEN), + axis(AXIS_LENGTH, BLUE)); + graphModel = graph(sys, pts, lns); + } +} diff --git a/org.fortiss.tooling.graphicsGL.ui/trunk/test-src/test/org/fortiss/tooling/graphics3D/ui/Test3DEditorBinding.java b/org.fortiss.tooling.graphicsGL.ui/trunk/test-src/test/org/fortiss/tooling/graphics3D/ui/Test3DEditorBinding.java new file mode 100644 index 000000000..6f19d6ab3 --- /dev/null +++ b/org.fortiss.tooling.graphicsGL.ui/trunk/test-src/test/org/fortiss/tooling/graphics3D/ui/Test3DEditorBinding.java @@ -0,0 +1,51 @@ +/*--------------------------------------------------------------------------+ +$Id$ +| | +| Copyright 2012 ForTISS GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package test.org.fortiss.tooling.graphics3D.ui; + +import org.eclipse.ui.IEditorPart; +import org.fortiss.af3.expression.model.DataDictionary; +import org.fortiss.tooling.kernel.ui.extension.IModelEditorBinding; + +/** + * Editor binding for {@link Test3DEditor}. + * + * @author hoelzl + * @author $Author$ + * @version $Rev$ + * @ConQAT.Rating YELLOW Hash: 92549E564D969E70FD6068582B3F5AE7 + */ +public class Test3DEditorBinding implements IModelEditorBinding<DataDictionary> { + + /** {@inheritDoc} */ + @Override + public Class<? extends IEditorPart> getEditorClass() { + return Test3DEditor.class; + } + + /** {@inheritDoc} */ + @Override + public String getLabel() { + return "Test 3D Editor"; + } + + /** {@inheritDoc} */ + @Override + public int getPriority() { + return 0; + } +} -- GitLab