diff --git a/modules/testing/include/vkcv/camera/Camera.hpp b/modules/testing/include/vkcv/camera/Camera.hpp
index 588cf18bc3c8c52678e0c0039e4dd1ce4c4bc748..d373e37684d5c02cecd237af088c96fe03a8b8f0 100644
--- a/modules/testing/include/vkcv/camera/Camera.hpp
+++ b/modules/testing/include/vkcv/camera/Camera.hpp
@@ -27,7 +27,7 @@ namespace vkcv {
 
         ~Camera();
 
-        virtual void update(GLFWwindow* window);
+        virtual void update(GLFWwindow* window) {};
 
         void setPerspective(float fov, float ratio, float near, float far);
 
diff --git a/modules/testing/include/vkcv/camera/TrackballCamera.hpp b/modules/testing/include/vkcv/camera/TrackballCamera.hpp
index 8fb41dd3a65ee127c096a0fc3c7ab963e89828c6..e9143e873de38ac470f8df6da10af6ba37854ec8 100644
--- a/modules/testing/include/vkcv/camera/TrackballCamera.hpp
+++ b/modules/testing/include/vkcv/camera/TrackballCamera.hpp
@@ -7,6 +7,8 @@ namespace vkcv {
     class TrackballCamera : public vkcv::Camera {
     public:
 
+        TrackballCamera( int width, int height, glm::mat4 projection);
+
         TrackballCamera(int width, int height);
 
         ~TrackballCamera();
diff --git a/modules/testing/src/vkcv/camera/Camera.cpp b/modules/testing/src/vkcv/camera/Camera.cpp
index ba651f7fcdb2cc74f30ecc719804cc3da8ba6f5b..4039550d767a549e200d633abc51a201ab03a576 100644
--- a/modules/testing/src/vkcv/camera/Camera.cpp
+++ b/modules/testing/src/vkcv/camera/Camera.cpp
@@ -1,4 +1,5 @@
 #include "vkcv/camera/Camera.hpp"
+#include <iostream>
 
 namespace vkcv {
 
@@ -8,6 +9,7 @@ namespace vkcv {
 
     void Camera::lookAt(glm::vec3 position, glm::vec3 center, glm::vec3 up){
         m_view = glm::lookAt(position, center, up);
+        m_position = position;
     }
 
     void Camera::getView(glm::vec3 &x, glm::vec3 &y, glm::vec3 &z, glm::vec3 &pos){
@@ -66,4 +68,12 @@ namespace vkcv {
         setPerspective(m_fov, m_ratio, m_near, m_far);
     }
 
+    void Camera::setPerspective(float fov, float ratio, float near, float far){
+        m_fov = fov;
+        m_ratio = ratio;
+        m_near = near;
+        m_far = far;
+        m_projection = glm::perspective( m_fov, ratio, m_near, m_far);
+    }
+
 }
\ No newline at end of file
diff --git a/modules/testing/src/vkcv/camera/TrackballCamera.cpp b/modules/testing/src/vkcv/camera/TrackballCamera.cpp
index 1c51be9dd9c8038fbb1bcda300d46e19657311cd..6e2323da17db2a83be1f8bcaf957fd677c4dc3a8 100644
--- a/modules/testing/src/vkcv/camera/TrackballCamera.cpp
+++ b/modules/testing/src/vkcv/camera/TrackballCamera.cpp
@@ -2,6 +2,29 @@
 
 namespace vkcv{
 
+    TrackballCamera::TrackballCamera( int width, int height, glm::mat4 projection)
+    {
+        m_position = glm::vec3(0.0f, 0.0f, 5.0);
+        m_center = glm::vec3( 0.0f, 0.0f, 0.0f);
+        m_up = glm::vec3(0.0f, 1.0f, 0.0f);
+
+        m_width = width;
+        m_height = height;
+
+        m_sensitivity = 0.010f;
+        m_stepSize = 0.1f;
+        m_theta = glm::pi<float>() / 2.0f;
+        m_phi = 0.f;
+        m_radius = 1.5;
+
+        m_view = glm::lookAt( m_center + m_position, m_center, m_up);
+
+        m_oldX = width/2.f;
+        m_oldY = height/2.f;
+
+        setProjection(projection);
+    }
+
 
     TrackballCamera::TrackballCamera(int width, int height)
     {
@@ -32,8 +55,45 @@ namespace vkcv{
         setProjection(projection);
     }
 
+    TrackballCamera::~TrackballCamera()
+    {
+    }
+
+
     void TrackballCamera::update( GLFWwindow* window) {
 
+        double x, y;
+
+        glfwGetCursorPos( window, &x, &y);
+        if (glfwGetMouseButton( window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS)
+        {
+            float changeX = ((float) x - m_oldX) * m_sensitivity;
+            float changeY = ((float) y - m_oldY) * m_sensitivity;
+
+            m_theta -= changeY;
+            if (m_theta < 0.01f) m_theta = 0.01f;
+            else if (m_theta > glm::pi<float>() - 0.01f) m_theta = glm::pi<float>() - 0.01f;
+
+            m_phi -= changeX;
+            if (m_phi < 0) m_phi += 2*glm::pi<float>();
+            else if (m_phi > 2*glm::pi<float>()) m_phi -= 2*glm::pi<float>();
+        }
+
+        m_oldX = (float) x;
+        m_oldY = (float) y;
+
+        if (glfwGetKey( window, GLFW_KEY_UP) == GLFW_PRESS)
+            m_radius -= m_stepSize;
+        if (glfwGetKey( window, GLFW_KEY_DOWN) == GLFW_PRESS)
+            m_radius += m_stepSize;
+        if (m_radius < 0.1f) m_radius = 0.1f;
+
+        m_position.x = m_center.x + m_radius * sin(m_theta) * sin(m_phi);
+        m_position.y = m_center.y + m_radius * cos(m_theta);
+        m_position.z = m_center.z + m_radius * sin(m_theta) * cos(m_phi);
+
+        m_view = glm::lookAt( m_position, m_center, m_up);
+
     }
 
     float TrackballCamera::getSensitivity() const {
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index da2c45ab4675ceb86d60c829ae15c48d37cbe9df..2981e566c7c21d856c46fd636910508f3f47e7a0 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -4,6 +4,7 @@
 #include <vkcv/ShaderProgram.hpp>
 #include <GLFW/glfw3.h>
 #include <vkcv/camera/Camera.hpp>
+#include <vkcv/camera/TrackballCamera.hpp>
 
 int main(int argc, const char** argv) {
     const char* applicationName = "First Triangle";
@@ -17,24 +18,66 @@ int main(int argc, const char** argv) {
 		false
     );
 
+    // TODO: this code will be put in a camera controller class
+    vkcv::Camera camera;
+    std::shared_ptr<vkcv::TrackballCamera> trackball;
+    camera.setPerspective( glm::radians(60.0f), windowWidth / (float)windowHeight, 0.1f, 10.f);
+    glm::vec3 up(0.0f, 1.0f, 0.0f);
+    glm::vec3 position(1.0f, 0.0f, 0.0f);
+    glm::vec3 front(0.0f, 0.0f, -1.0f);
+    glm::vec3 center = position + front;
+    camera.lookAt(position, center, up);
+    const float radius = 10.0f;
+    const float cameraSpeed = 0.05f;
+    float roll = 0.0;
+    float pitch = 0.0;
+    float yaw = 0.0;
+    // TODO: need scrolling event callback to set yoffset
+    float yoffset = 10;
+
+    // scroll callback
+    float fov = camera.getFov();
+    fov -= yoffset;
+    if (fov < 1.0f)
+        fov = 1.0f;
+    if (fov > 45.0f)
+        fov = 45.0f;
+    camera.setFov(fov);
+
+    //TODO? should the standard camera support rotation?
+
     // showing basic usage lambda events of window
     window.e_mouseMove.add([&](double x, double y){
         std::cout << "movement: " << x << " , " << y << std::endl;
     });
 
+    // TODO: need event for press mouse button
+
     window.e_key.add([&](int key, int scancode, int action, int mods){
         switch (key) {
             case GLFW_KEY_W:
                 std::cout << "Move forward" << std::endl;
+                position += cameraSpeed * front;
+                center = position + front;
+                camera.lookAt(position, center, up);
                 break;
-            case GLFW_KEY_A:
+            case GLFW_KEY_S:
                 std::cout << "Move left" << std::endl;
+                position -= cameraSpeed * front;
+                center = position + front;
+                camera.lookAt(position, center, up);
                 break;
-            case GLFW_KEY_S:
+            case GLFW_KEY_A:
                 std::cout << "Move backward" << std::endl;
+                position -= glm::normalize(glm::cross(front, up)) * cameraSpeed;
+                center = position + front;
+                camera.lookAt(position, center, up);
                 break;
             case GLFW_KEY_D:
                 std::cout << "Move right" << std::endl;
+                position += glm::normalize(glm::cross(front, up)) * cameraSpeed;
+                center = position + front;
+                camera.lookAt(position, center, up);
                 break;
             default:
                 std::cout << "this key is not supported yet: " << std::endl;