00001 00005 /* Copyright © 2009, 2010 James Legg. 00006 This program is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 */ 00011 #include "CarCamera.h" 00012 #include <GL/gl.h> 00013 #include <GL/glu.h> 00014 00015 #include <cmath> 00016 00017 #include "../Graphics/Window.h" 00018 #include "Audio.h" 00019 00020 class MyQuaternion : public btQuaternion 00021 { 00022 public: 00023 MyQuaternion(const btQuaternion & quaternion) 00024 : btQuaternion(quaternion) 00025 { 00026 } 00027 00028 // This function is based on code from Bullet, released under this license: 00029 /* Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/ 00030 00031 This software is provided 'as-is', without any express or implied warranty. 00032 In no event will the authors be held liable for any damages arising from the use of this software. 00033 Permission is granted to anyone to use this software for any purpose, 00034 including commercial applications, and to alter it and redistribute it freely, 00035 subject to the following restrictions: 00036 00037 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 00038 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 00039 3. This notice may not be removed or altered from any source distribution. 00040 */ 00042 btVector3 getAxis() const 00043 { 00044 btScalar s_squared = btScalar(1.) - btPow(m_floats[3], btScalar(2.)); 00045 if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero 00046 { 00047 return btVector3(1.0, 0.0, 0.0); // Arbitrary 00048 } 00049 btScalar s = btSqrt(s_squared); 00050 return btVector3(m_floats[0] / s, m_floats[1] / s, m_floats[2] / s); 00051 } 00052 00053 }; 00054 00055 namespace Engine 00056 { 00057 00058 CarCamera::CarCamera(GameObjects::Car & car, Physics::World & world) 00059 : car(car), 00060 world(world) 00061 , m_velocity(btVector3(0.0, 0.0, 0.0)) 00062 { 00063 world.add_tick_observer(this); 00064 00065 // set inital camera position. 00066 btTransform car_transform; 00067 car.get_transform(car_transform); 00068 btTransform car_rotation_transform = car_transform; 00069 car_rotation_transform.setOrigin(btVector3(0, 0, 0)); 00070 location = car_transform(btVector3(0.0, -0.70, car.get_camera_height())); 00071 up = car_rotation_transform(btVector3(0.0, 0.0, 1.0)); 00072 centre = car_transform(btVector3(0.0, 1.0, 0.1)); 00073 // We need the listener set so the sound is right before the game starts. 00074 posttick(); 00075 } 00076 00077 CarCamera::~CarCamera() 00078 { 00079 world.remove_tick_observer(this); 00080 } 00081 00082 void CarCamera::full_transform() 00083 { 00084 gluLookAt(location.x(), location.y(), location.z(), 00085 centre.x(), centre.y(), centre.z(), 00086 up.x(), up.y(), up.z()); 00087 } 00088 00089 void CarCamera::rotation_transform() 00090 { 00091 gluLookAt(0.0, 0.0, 0.0, 00092 centre.x() - location.x(), centre.y() - location.y(), centre.z() - location.z(), 00093 up.x(), up.y(), up.z()); 00094 } 00095 00096 void CarCamera::posttick() 00097 { 00098 const float blend = 0.3; 00099 btTransform car_transform; 00100 car.get_transform(car_transform); 00101 btTransform car_rotation_transform = car_transform; 00102 car_rotation_transform.setOrigin(btVector3(0, 0, 0)); 00103 // find a new place behind the car looking at it. 00104 btVector3 new_position(car_transform(btVector3(0.0, -0.70, car.get_camera_height()))); 00105 btVector3 new_up(car_rotation_transform(btVector3(0.0, 0.0, 1.0))); 00106 btVector3 new_centre = car_transform(btVector3(0.0, 1.0, 0.1)); 00107 00108 // blend new position with the last camera position to soften motion. 00109 m_velocity = location; 00110 location = location.lerp(new_position, blend); 00111 m_velocity -= location; 00112 up = up.lerp(new_up, blend); 00113 up.normalize(); 00114 centre = centre.lerp(new_centre, blend); 00115 00116 // set sound listener to this position, orientation, and velocity. 00117 m_listener.set_velocity(m_velocity * 100.0); 00118 m_listener.set_position(location, centre - location, up); 00119 } 00120 00121 void CarCamera::update_occlusion_tester(Track::OcclusionTester & occlusion_tester, btScalar aspect) const 00122 { 00123 // front plane 00125 00126 btVector3 front_normal = (centre - location).normalized(); 00127 // find the distance to it along this normal. 00128 btScalar front_distance = (-location).dot(front_normal); 00129 occlusion_tester.plane_vectors[0] = front_normal; 00130 occlusion_tester.plane_distances[0] = front_distance; 00131 00132 btVector3 sideways = up.cross(front_normal).normalized(); 00133 btVector3 real_up = sideways.cross(front_normal); 00134 00135 // side planes 00136 // fovy = 65 degrees = 1.134464014 radians. 00137 btScalar half_fovy = 0.567232006; 00138 const Graphics::Window window = Graphics::Window::get_instance(); 00139 btScalar half_fovx = std::atan(std::tan(half_fovy) * aspect); 00140 00141 btVector3 left_normal = real_up.cross(btTransform(btQuaternion(real_up, -half_fovx))(front_normal)).normalized(); 00142 occlusion_tester.plane_vectors[1] = left_normal; 00143 occlusion_tester.plane_distances[1] = (-location).dot(left_normal); 00144 00145 btVector3 right_normal = -real_up.cross(btTransform(btQuaternion(real_up, half_fovx))(front_normal)).normalized(); 00146 occlusion_tester.plane_vectors[2] = right_normal; 00147 occlusion_tester.plane_distances[2] = (-location).dot(right_normal); 00148 00149 btVector3 top_normal = sideways.cross(btTransform(btQuaternion(sideways, -half_fovy))(front_normal)).normalized(); 00150 occlusion_tester.plane_vectors[3] = top_normal; 00151 occlusion_tester.plane_distances[3] = (-location).dot(top_normal); 00152 00153 btVector3 bottom_normal = -sideways.cross(btTransform(btQuaternion(sideways, half_fovy))(front_normal)).normalized(); 00154 occlusion_tester.plane_vectors[4] = bottom_normal; 00155 occlusion_tester.plane_distances[4] = (-location).dot(bottom_normal); 00156 } 00157 00158 const btVector3 & CarCamera::get_location() const 00159 { 00160 return location; 00161 } 00162 00163 const btVector3 & CarCamera::get_velocity() const 00164 { 00165 return m_velocity; 00166 } 00167 00168 }
Generated at Mon Sep 6 00:41:12 2010 by Doxygen version 1.4.7 for Racer version svn335.