Просмотр исходного кода

Added trackball camera class to IDE, switched the mesh editor and entity editor to use it

Ivan Safrin 12 лет назад
Родитель
Сommit
32a32234b3

+ 2 - 0
Core/Contents/Include/PolyEntity.h

@@ -439,6 +439,8 @@ namespace Polycode {
 			*/																									
 			void setRotationQuat(Number w, Number x, Number y, Number z);
 			
+			void setRotationByQuaternion(const Quaternion &quaternion);
+			
 			/**
 			* Returns the current rotation as a quaternion.
 			* @return Current rotation value.

+ 9 - 0
Core/Contents/Include/PolyVector3.h

@@ -152,6 +152,15 @@ namespace Polycode {
 				return sqrtf( x * x + y * y + z * z );
 			}
 			
+			inline Vector3 setLength(const Number newLength) {
+				Number oldLength = length();
+				if(oldLength != 0 && newLength != oldLength) {
+					(*this) = (*this) * (newLength / oldLength);
+				}
+				return (*this);
+				
+			}
+			
 			/**
 			* Returns the dot product with another vector.
 			* @return Dor product with the vector.

+ 5 - 0
Core/Contents/Source/PolyEntity.cpp

@@ -593,6 +593,11 @@ void Entity::setRotationQuat(Number w, Number x, Number y, Number z) {
 	matrixDirty = true;
 }
 
+void Entity::setRotationByQuaternion(const Quaternion &quaternion) {
+	rotationQuat = quaternion;
+	matrixDirty = true;
+}
+
 Quaternion Entity::getRotationQuat() const {
 	return rotationQuat;
 }

+ 22 - 0
IDE/Build/Mac OS X/Polycode.xcodeproj/project.pbxproj

@@ -37,6 +37,7 @@
 		6DC825791648571E006AFC03 /* ExportProjectWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DC825781648571E006AFC03 /* ExportProjectWindow.cpp */; };
 		6DCAFD4314B519C900039F34 /* ExampleBrowserWindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DCAFD4214B519C900039F34 /* ExampleBrowserWindow.cpp */; };
 		6DCB6026181F1F4B006701AF /* PolycodeEntityEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DCB6025181F1F4B006701AF /* PolycodeEntityEditor.cpp */; };
+		6DCB602B18219FF1006701AF /* TrackballCamera.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DCB602A18219FF1006701AF /* TrackballCamera.cpp */; };
 		6DCE857A12AE018800566FAE /* PolycodeEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DCE857812AE018800566FAE /* PolycodeEditor.cpp */; };
 		6DCE857B12AE018800566FAE /* PolycodeEditorManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DCE857912AE018800566FAE /* PolycodeEditorManager.cpp */; };
 		6DCE85B712AE082B00566FAE /* PolycodeImageEditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6DCE85B612AE082B00566FAE /* PolycodeImageEditor.cpp */; };
@@ -133,6 +134,8 @@
 		6DCAFD4614B51A2D00039F34 /* ExampleBrowserWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExampleBrowserWindow.h; sourceTree = "<group>"; };
 		6DCB6023181F1F44006701AF /* PolycodeEntityEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeEntityEditor.h; sourceTree = "<group>"; };
 		6DCB6025181F1F4B006701AF /* PolycodeEntityEditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolycodeEntityEditor.cpp; sourceTree = "<group>"; };
+		6DCB602818219FDF006701AF /* TrackballCamera.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TrackballCamera.h; path = utils/TrackballCamera.h; sourceTree = "<group>"; };
+		6DCB602A18219FF1006701AF /* TrackballCamera.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TrackballCamera.cpp; path = utils/TrackballCamera.cpp; sourceTree = "<group>"; };
 		6DCE857612AE018000566FAE /* PolycodeEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeEditor.h; sourceTree = "<group>"; };
 		6DCE857712AE018000566FAE /* PolycodeEditorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolycodeEditorManager.h; sourceTree = "<group>"; };
 		6DCE857812AE018800566FAE /* PolycodeEditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolycodeEditor.cpp; sourceTree = "<group>"; };
@@ -280,6 +283,7 @@
 		6D80E91212AB53FB0037A708 /* Include */ = {
 			isa = PBXGroup;
 			children = (
+				6DCB602718219FD5006701AF /* utils */,
 				6DCB6023181F1F44006701AF /* PolycodeEntityEditor.h */,
 				6D0F6B5F18170C0400C5327F /* PolycodeMeshEditor.h */,
 				6D8A845A16F593C800F3BA08 /* PolycodeClipboard.h */,
@@ -316,6 +320,7 @@
 		6D80E91812AB53FB0037A708 /* Source */ = {
 			isa = PBXGroup;
 			children = (
+				6DCB602918219FE7006701AF /* utils */,
 				6DCB6025181F1F4B006701AF /* PolycodeEntityEditor.cpp */,
 				6D0F6B6118170C1000C5327F /* PolycodeMeshEditor.cpp */,
 				6D128ABC174A9940007B0375 /* SettingsWindow.cpp */,
@@ -348,6 +353,22 @@
 			path = ../../Contents/Source;
 			sourceTree = SOURCE_ROOT;
 		};
+		6DCB602718219FD5006701AF /* utils */ = {
+			isa = PBXGroup;
+			children = (
+				6DCB602818219FDF006701AF /* TrackballCamera.h */,
+			);
+			name = utils;
+			sourceTree = "<group>";
+		};
+		6DCB602918219FE7006701AF /* utils */ = {
+			isa = PBXGroup;
+			children = (
+				6DCB602A18219FF1006701AF /* TrackballCamera.cpp */,
+			);
+			name = utils;
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
@@ -462,6 +483,7 @@
 				6D128ABD174A9940007B0375 /* SettingsWindow.cpp in Sources */,
 				6D0F6B6218170C1000C5327F /* PolycodeMeshEditor.cpp in Sources */,
 				6DCB6026181F1F4B006701AF /* PolycodeEntityEditor.cpp in Sources */,
+				6DCB602B18219FF1006701AF /* TrackballCamera.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 5 - 2
IDE/Contents/Include/PolycodeEntityEditor.h

@@ -26,6 +26,7 @@
 #include "PolyUIElement.h"
 #include <Polycode.h>
 #include "PolycodeUI.h"
+#include "utils/TrackballCamera.h"
 
 using namespace Polycode;
 
@@ -46,8 +47,8 @@ class EntityEditorMainView : public UIElement {
 			void Resize(Number width, Number height);
 			void Update();
 			
-		protected:
-		
+		protected:		
+			
 			Entity *sideBar;
 			UIRect *headerBg;	
 			
@@ -56,6 +57,8 @@ class EntityEditorMainView : public UIElement {
 			UIRect *renderTextureShape;			
 
 			TransformGizmo *transformGizmo;
+			TrackballCamera *trackballCamera;
+			
 };
 
 class PolycodeEntityEditor : public PolycodeEditor {

+ 4 - 9
IDE/Contents/Include/PolycodeMeshEditor.h

@@ -24,6 +24,7 @@
 
 #include "PolycodeEditor.h"
 #include "PolyUIElement.h"
+#include "TrackballCamera.h"
 #include "PolycodeUI.h"
 #include <Polycode.h>
 
@@ -50,23 +51,17 @@ class PolycodeMeshEditor : public PolycodeEditor {
 		SceneLight *secondLight;		
 		SceneRenderTexture *renderTexture;
 		UIRect *previewShape;
-		UIRect *bgShape;		
 		SceneMesh *previewMesh;
 		Entity *previewBase;
 		
 		Material *currentMaterial;
-		
-		bool rotating;
-		Vector2 baseMousePosition;		
-		
+				
 		UIComboBox *materialDropDown;
 		UIRect *headerBg;
 		
 		UIHSlider *lightsSlider;
-		
-		Vector3 baseModelPosition;
-		Number baseYaw;
-		Number basePitch;
+		TrackballCamera *trackballCamera;
+
 };
 
 class PolycodeMeshEditorFactory : public PolycodeEditorFactory {

+ 69 - 0
IDE/Contents/Include/utils/TrackballCamera.h

@@ -0,0 +1,69 @@
+/*
+ Copyright (C) 2013 by Ivan Safrin
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+#pragma once
+
+#include "Polycode.h"
+#include "OSBasics.h"
+
+using namespace Polycode;
+
+class TrackballCamera : public EventHandler {
+	public:
+		TrackballCamera(Camera *targetCamera, Entity *trackballShape);
+		~TrackballCamera();
+		
+		void handleEvent(Event *event);		
+		void setOrbitingCenter(const Vector3 &newCenter);
+		void setCameraDistance(Number cameraDistance);
+		Camera *getTargetCamera();
+		
+		static const int MOUSE_MODE_IDLE = 0;
+		static const int MOUSE_MODE_ORBITING = 1;
+		static const int MOUSE_MODE_PANNING = 2;
+		static const int MOUSE_MODE_ZOOMING = 3;				
+		
+		Number trackballPanSpeed;
+		Number trackballZoomSpeed;	
+		Number trackballRotateSpeed;
+		
+	private:
+	
+		int mouseMode;
+	
+		Vector3 getMouseProjectionOnBall(const Vector2 &mousePosition);
+		void updateCamera();	
+		void processMouseMovement(const Vector2 &newPosition);
+		
+		Camera *targetCamera;
+		Entity *trackballShape;
+		
+		Vector2 trackBallMouseStart;
+		Vector2 trackBallMouseEnd;			
+		Vector3 orbitingCenter;
+		Vector3 trackballRotateStart;
+		Vector3 trackballRotateEnd;	
+		Vector3 trackballEye;		
+		Number cameraDistance;
+		CoreInput *coreInput;		
+		
+};

+ 11 - 3
IDE/Contents/Source/PolycodeEntityEditor.cpp

@@ -57,18 +57,21 @@ TransformGizmo::TransformGizmo() : Entity() {
 	ScenePrimitive *yArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
 	yArrow->setColor(0.0, 1.0, 0.0, 1.0);
 	yArrow->setPosition(0.0, 1.0, 0.0);
+	yArrow->depthTest = false;
 	addChild(yArrow);
 	
 	ScenePrimitive *xArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
 	xArrow->setColor(1.0, 0.0, 0.0, 1.0);
 	xArrow->setPosition(1.0, 0.0, 0.0);
 	xArrow->Roll(-90);
+	xArrow->depthTest = false;
 	addChild(xArrow);
 
 	ScenePrimitive *zArrow = new ScenePrimitive(ScenePrimitive::TYPE_CONE, 0.2, 0.05, 12);
 	zArrow->setColor(0.0, 0.0, 1.0, 1.0);
 	zArrow->setPosition(0.0, 0.0, 1.0);
 	zArrow->Pitch(90);
+	zArrow->depthTest = false;	
 	addChild(zArrow);
 	
 }
@@ -91,7 +94,7 @@ EntityEditorMainView::EntityEditorMainView() {
 	renderTextureShape->setTexture(renderTexture->getTargetTexture());
 	addChild(renderTextureShape);
 	renderTextureShape->setPosition(0, 30);
-	
+				
 	sideBar = new Entity();
 	addChild(sideBar);
 	sideBar->setPosition(0, 30);
@@ -120,7 +123,9 @@ EntityEditorMainView::EntityEditorMainView() {
 	
 	transformGizmo = new TransformGizmo();
 	mainScene->addChild(transformGizmo);
+	transformGizmo->visible = false;
 	
+	trackballCamera = new TrackballCamera(mainScene->getDefaultCamera(), renderTextureShape);
 }
 
 void EntityEditorMainView::Update() {
@@ -129,13 +134,16 @@ void EntityEditorMainView::Update() {
 }
 
 void EntityEditorMainView::handleEvent(Event *event) {
+
 	if(event->getEventCode() == InputEvent::EVENT_MOUSEDOWN ) {
 		InputEvent *inputEvent = (InputEvent*) event;
-		if(inputEvent->mouseButton == CoreInput::MOUSE_BUTTON1) {
+
+		if(inputEvent->mouseButton == CoreInput::MOUSE_BUTTON2) {
 			Entity* targetEntity = (Entity*) event->getDispatcher();
 			
 			transformGizmo->setPosition(targetEntity->getConcatenatedMatrix().getPosition());
-			
+			transformGizmo->visible = true;
+				
 			SceneMesh *sceneMesh = dynamic_cast<SceneMesh*>(targetEntity);
 			if(sceneMesh) {
 				sceneMesh->overlayWireframe = true;

+ 8 - 63
IDE/Contents/Source/PolycodeMeshEditor.cpp

@@ -29,7 +29,7 @@ PolycodeMeshEditor::PolycodeMeshEditor() : PolycodeEditor(true){
 	previewScene = new Scene(Scene::SCENE_3D, true);		
 	renderTexture = new SceneRenderTexture(previewScene, previewScene->getDefaultCamera(), 512, 512);
 
-	previewScene->clearColor.setColor(0.0, 0.0, 0.0, 0.0);	
+	previewScene->clearColor.setColor(0.2, 0.2, 0.2, 1.0);	
 	previewScene->useClearColor = true;
 	
 //	previewScene->ambientColor.setColor(0.0, 0.0, 0.0, 1.0);
@@ -46,21 +46,7 @@ PolycodeMeshEditor::PolycodeMeshEditor() : PolycodeEditor(true){
 	addChild(headerBg);
 	headerBg->setAnchorPoint(-1.0, -1.0, 0.0);
 	headerBg->color.setColorHexFromString(CoreServices::getInstance()->getConfig()->getStringValue("Polycode", "uiHeaderBgColor"));		
-
-	bgShape = new UIRect("Images/editorGrid.png");
-	bgShape->setAnchorPoint(-1.0, -1.0, 0.0);	
-	addChild(bgShape);	
-	bgShape->getTexture()->clamp = false;
-    bgShape->getTexture()->recreateFromImageData();     	
-	bgShape->color.setColorHexFromString(CoreServices::getInstance()->getConfig()->getStringValue("Polycode", "uiBgColor"));	
-	bgShape->processInputEvents = true;
-	bgShape->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
-	bgShape->addEventListener(this, InputEvent::EVENT_MOUSEUP);
-	bgShape->addEventListener(this, InputEvent::EVENT_MOUSEUP_OUTSIDE);
-	bgShape->addEventListener(this, InputEvent::EVENT_MOUSEMOVE);
-	bgShape->addEventListener(this, InputEvent::EVENT_MOUSEWHEEL_UP);
-	bgShape->addEventListener(this, InputEvent::EVENT_MOUSEWHEEL_DOWN);
-				
+	
 	previewShape = new UIRect(256, 256);
 	previewShape->setAnchorPoint(-1.0, -1.0, 0.0);	
 	previewShape->setTexture(renderTexture->getTargetTexture());
@@ -95,8 +81,9 @@ PolycodeMeshEditor::PolycodeMeshEditor() : PolycodeEditor(true){
 	CoreServices::getInstance()->getResourceManager()->dispatchChangeEvents = true;	
 	CoreServices::getInstance()->getResourceManager()->addEventListener(this, Event::CHANGE_EVENT);
 	
-	rotating = false;
-	previewMesh = NULL;
+	previewMesh = NULL;	
+	trackballCamera = new TrackballCamera(previewScene->getDefaultCamera(), previewShape);
+	
 }
 
 void PolycodeMeshEditor::reloadMaterials() {
@@ -132,40 +119,6 @@ void PolycodeMeshEditor::handleEvent(Event *event) {
 		}
 	} else if(event->getDispatcher() == CoreServices::getInstance()->getResourceManager()) {
 		reloadMaterials();
-	} else if(event->getDispatcher() == bgShape) {
-		InputEvent *inputEvent = (InputEvent*) event;
-		switch(event->getEventCode()) {
-			case InputEvent::EVENT_MOUSEDOWN:
-				rotating = true;
-				baseMousePosition = inputEvent->mousePosition;
-				baseYaw = previewBase->getYaw();
-				basePitch = previewBase->getPitch();
-				baseModelPosition = previewMesh->getPosition();
-			break;
-			case InputEvent::EVENT_MOUSEUP:
-				rotating = false;
-			break;
-			case InputEvent::EVENT_MOUSEUP_OUTSIDE:
-				rotating = false;			
-			break;
-			case InputEvent::EVENT_MOUSEMOVE:
-				if(rotating && previewMesh) {
-					if(CoreServices::getInstance()->getCore()->getInput()->getKeyState(KEY_LALT)) {
-						previewMesh->setPosition(baseModelPosition.x - ((baseMousePosition.x -inputEvent->mousePosition.x) * 0.01), baseModelPosition.y + ((baseMousePosition.y -inputEvent->mousePosition.y) * 0.01));
-						
-					} else {
-						previewBase->setYaw(baseYaw - ((baseMousePosition.x-inputEvent->mousePosition.x) * 0.3));
-						previewBase->setPitch(basePitch - ((baseMousePosition.y-inputEvent->mousePosition.y) * 0.3));
-					}
-				}
-			break;
-			case InputEvent::EVENT_MOUSEWHEEL_UP:
-				previewBase->Scale(1.01, 1.01, 1.01);
-			break;
-			case InputEvent::EVENT_MOUSEWHEEL_DOWN:
-				previewBase->Scale(0.99, 0.99, 0.99);			
-			break;			
-		}
 	}
 }
 
@@ -182,27 +135,19 @@ bool PolycodeMeshEditor::openFile(OSFileEntry filePath) {
 	CoreServices::getInstance()->getRenderer()->alphaTestValue = 0.9;
 	
 	Number radius = previewMesh->getBBoxRadius();
-	
-	previewScene->getDefaultCamera()->setPosition(0,0,radius*3);
-	previewScene->getDefaultCamera()->lookAt(Vector3());
-	
-		
+				
 	mainLight->setPosition(-(radius*3),(radius*3),(radius*3));
 	secondLight->setPosition((radius*3),-(radius*3),(radius*3));
 	
+	trackballCamera->setCameraDistance(radius*3);
 	return true;
 }
 
 void PolycodeMeshEditor::Resize(int x, int y) {
-
-	headerBg->Resize(x, 30);
-	
+	headerBg->Resize(x, 30);	
 	renderTexture->resizeRenderTexture(x, y-30);
 	previewShape->setTexture(renderTexture->getTargetTexture());	
 	previewShape->Resize(x, y-30);	
-	bgShape->setImageCoordinates(0,0,x,y-30);
-	
-	bgShape->setPosition(0, 30);
 	previewShape->setPosition(0, 30);
 }
 

+ 213 - 0
IDE/Contents/Source/utils/TrackballCamera.cpp

@@ -0,0 +1,213 @@
+/*
+ Copyright (C) 2013 by Ivan Safrin
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+ 
+#include "TrackballCamera.h"
+
+
+TrackballCamera::TrackballCamera(Camera *targetCamera, Entity *trackballShape) : EventHandler() {
+	mouseMode = MOUSE_MODE_IDLE;
+	
+	this->targetCamera = targetCamera;
+	this->trackballShape = trackballShape;
+	
+	trackballShape->addEventListener(this, InputEvent::EVENT_MOUSEDOWN);
+	trackballShape->addEventListener(this, InputEvent::EVENT_MOUSEUP);
+	trackballShape->addEventListener(this, InputEvent::EVENT_MOUSEMOVE);	
+	trackballShape->addEventListener(this, InputEvent::EVENT_MOUSEUP_OUTSIDE);
+	trackballShape->processInputEvents = true;
+	
+	trackballRotateSpeed = 1.0;
+	trackballPanSpeed = 0.6;
+	trackballZoomSpeed = 1.0;
+	cameraDistance = 10.0;
+	
+	coreInput = CoreServices::getInstance()->getCore()->getInput();
+	
+	targetCamera->setPosition(cameraDistance, cameraDistance, cameraDistance);
+	trackballRotateEnd = getMouseProjectionOnBall(Vector2(trackballShape->getWidth()/2.0, trackballShape->getHeight()/2.0));
+	trackballRotateStart = trackballRotateEnd;
+	
+	updateCamera();	
+}
+
+TrackballCamera::~TrackballCamera() {
+	trackballShape->removeAllHandlersForListener(this);
+}
+
+void TrackballCamera::setCameraDistance(Number cameraDistance) {
+	this->cameraDistance = cameraDistance;
+	updateCamera();
+}
+
+Camera *TrackballCamera::getTargetCamera() {
+	return targetCamera;
+}
+
+void TrackballCamera::handleEvent(Event *event) {
+
+	if(event->getDispatcher() == trackballShape) {
+		InputEvent *inputEvent = (InputEvent*) event;
+		switch(event->getEventCode()) {
+			case InputEvent::EVENT_MOUSEDOWN:
+				if(coreInput->getKeyState(KEY_LALT) || coreInput->getKeyState(KEY_RALT)) {		
+					if(coreInput->getKeyState(KEY_LSHIFT) || coreInput->getKeyState(KEY_RSHIFT)) {
+						mouseMode = MOUSE_MODE_PANNING;
+						trackBallMouseStart = Vector2(
+							inputEvent->getMousePosition().x / trackballShape->getWidth(),
+							inputEvent->getMousePosition().y / trackballShape->getHeight()
+						);
+						trackBallMouseEnd = trackBallMouseStart;
+					} else if(coreInput->getKeyState(KEY_LCTRL) || coreInput->getKeyState(KEY_RCTRL)) {
+						mouseMode = MOUSE_MODE_ZOOMING;
+						trackBallMouseStart = Vector2(
+							inputEvent->getMousePosition().x / trackballShape->getWidth(),
+							inputEvent->getMousePosition().y / trackballShape->getHeight()
+						);
+						trackBallMouseEnd = trackBallMouseStart;												
+					} else {
+						mouseMode = MOUSE_MODE_ORBITING;
+						trackballRotateStart = trackballRotateEnd = getMouseProjectionOnBall(inputEvent->getMousePosition());
+					}
+				}
+			break;
+			case InputEvent::EVENT_MOUSEUP:
+			case InputEvent::EVENT_MOUSEUP_OUTSIDE:
+				mouseMode = MOUSE_MODE_IDLE;
+			break;
+			case InputEvent::EVENT_MOUSEMOVE:
+				processMouseMovement(inputEvent->getMousePosition());
+			break;						
+		}		
+		return;
+	}
+}
+
+void TrackballCamera::setOrbitingCenter(const Vector3 &newCenter) {
+	orbitingCenter = newCenter;
+	updateCamera();	
+}
+
+void TrackballCamera::processMouseMovement(const Vector2 &newPosition) {
+	switch(mouseMode) {
+		case MOUSE_MODE_ORBITING:
+		{
+			trackballRotateEnd = getMouseProjectionOnBall(newPosition);
+			updateCamera();
+		}	
+		break;
+		case MOUSE_MODE_PANNING:
+		{
+			trackBallMouseEnd  = Vector2(
+							newPosition.x / trackballShape->getWidth(),
+							newPosition.y / trackballShape->getHeight()
+						);
+
+			
+			Vector2 mouseChange = trackBallMouseEnd - trackBallMouseStart;
+			Number mouseChangeLength = mouseChange.length() * mouseChange.length();
+			if(mouseChangeLength) {
+				mouseChange = mouseChange * trackballEye.length() * trackballPanSpeed;
+								
+				Vector3 pan = trackballEye.crossProduct(Vector3(0.0, 1.0, 0.0)).setLength(mouseChange.x);
+				
+				pan = pan + (Vector3(0.0, 1.0, 0.0).setLength(mouseChange.y));
+				
+				targetCamera->Translate(pan);
+				orbitingCenter += pan;
+				trackBallMouseStart = trackBallMouseEnd;
+			}
+		}	
+		break;		
+		case MOUSE_MODE_ZOOMING:
+		{
+			trackBallMouseEnd  = Vector2(
+							newPosition.x / trackballShape->getWidth(),
+							newPosition.y / trackballShape->getHeight()
+						);
+								
+			Number factor = 1.0 + ( trackBallMouseEnd.y - trackBallMouseStart.y ) * trackballZoomSpeed;			
+			if(factor != 1.0 && factor > 0.0 ) {
+				cameraDistance *= factor;
+			}
+			trackBallMouseStart = trackBallMouseEnd;			
+			updateCamera();
+		}
+		break;
+		default:
+		break;
+	}
+}
+
+
+
+void TrackballCamera::updateCamera() {
+
+	trackballEye = targetCamera->getPosition() - orbitingCenter;
+	trackballEye.setLength(cameraDistance);
+	
+	
+	Number angle = acos(trackballRotateStart.dot(trackballRotateEnd) / trackballRotateStart.length() / trackballRotateEnd.length());
+	
+	if(angle == angle) {
+		Vector3 axis = trackballRotateStart.crossProduct(trackballRotateEnd);
+		axis.Normalize();
+		Quaternion q;
+		
+		angle *= trackballRotateSpeed;	
+		q.fromAngleAxis(angle, axis);
+		
+		trackballEye = q.applyTo(trackballEye);
+		trackballRotateEnd = q.applyTo(trackballRotateEnd);
+		
+		trackballRotateStart = trackballRotateEnd;
+	}
+		
+	targetCamera->setPosition(orbitingCenter + trackballEye);	
+	targetCamera->lookAt(orbitingCenter);
+	
+}
+
+Vector3 TrackballCamera::getMouseProjectionOnBall(const Vector2 &mousePosition) {
+
+	Vector3 mouseOnBall = Vector3((mousePosition.x - (trackballShape->getWidth() * 0.5)) / (trackballShape->getWidth() * 0.5),(mousePosition.y - (trackballShape->getHeight() * 0.5)) / (trackballShape->getHeight() * 0.5), 0.0);
+	mouseOnBall.x *= -1;	
+	
+	Number length = mouseOnBall.length();
+	
+
+	if (length < sqrt(0.5)) {
+		mouseOnBall.z = sqrt(1.0 - length*length);
+	} else {
+		mouseOnBall.z = 0.5 / length;
+	}
+
+	trackballEye = targetCamera->getPosition() - orbitingCenter;
+	
+	Vector3 projection = Vector3(0.0, 1.0, 0.0).setLength(mouseOnBall.y);		
+	
+	projection = projection + (Vector3(0.0, 1.0, 0.0).crossProduct(trackballEye).setLength(mouseOnBall.x));				
+	
+	trackballEye.setLength(mouseOnBall.z);
+	projection = projection + (trackballEye);
+	
+	return projection;	
+}