/* Copyright (C) 2001-2006, William Joseph. All Rights Reserved. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #if !defined( INCLUDED_ROTATION_H ) #define INCLUDED_ROTATION_H #include "ientity.h" #include "stream/stringstream.h" #include "math/quaternion.h" #include "generic/callback.h" #include "stringio.h" #include "angle.h" typedef float Float9[9]; inline void default_rotation( Float9 rotation ){ rotation[0] = 1; rotation[1] = 0; rotation[2] = 0; rotation[3] = 0; rotation[4] = 1; rotation[5] = 0; rotation[6] = 0; rotation[7] = 0; rotation[8] = 1; } inline void write_rotation( const Float9 rotation, Entity* entity, const char* key = "rotation" ){ if ( rotation[0] == 1 && rotation[1] == 0 && rotation[2] == 0 && rotation[3] == 0 && rotation[4] == 1 && rotation[5] == 0 && rotation[6] == 0 && rotation[7] == 0 && rotation[8] == 1 ) { entity->setKeyValue( key, "" ); } else { StringOutputStream value( 256 ); value << rotation[0] << ' ' << rotation[1] << ' ' << rotation[2] << ' ' << rotation[3] << ' ' << rotation[4] << ' ' << rotation[5] << ' ' << rotation[6] << ' ' << rotation[7] << ' ' << rotation[8]; entity->setKeyValue( key, value.c_str() ); } } inline void read_rotation( Float9 rotation, const char* value ){ if ( !string_parse_vector( value, rotation, rotation + 9 ) ) { default_rotation( rotation ); } } inline Matrix4 rotation_toMatrix( const Float9 rotation ){ return Matrix4( rotation[0], rotation[1], rotation[2], 0, rotation[3], rotation[4], rotation[5], 0, rotation[6], rotation[7], rotation[8], 0, 0, 0, 0, 1 ); } inline void rotation_fromMatrix( Float9 rotation, const Matrix4& matrix ){ rotation[0] = matrix.xx(); rotation[1] = matrix.xy(); rotation[2] = matrix.xz(); rotation[3] = matrix.yx(); rotation[4] = matrix.yy(); rotation[5] = matrix.yz(); rotation[6] = matrix.zx(); rotation[7] = matrix.zy(); rotation[8] = matrix.zz(); } inline void rotation_assign( Float9 rotation, const Float9 other ){ rotation[0] = other[0]; rotation[1] = other[1]; rotation[2] = other[2]; rotation[3] = other[3]; rotation[4] = other[4]; rotation[5] = other[5]; rotation[6] = other[6]; rotation[7] = other[7]; rotation[8] = other[8]; } inline void rotation_rotate( Float9 rotation, const Quaternion& rotate ){ rotation_fromMatrix( rotation, matrix4_multiplied_by_matrix4( rotation_toMatrix( rotation ), matrix4_rotation_for_quaternion_quantised( rotate ) ) ); } inline void read_angle( Float9 rotation, const char* value ){ float angle; if ( !string_parse_float( value, angle ) ) { default_rotation( rotation ); } else { rotation_fromMatrix( rotation, matrix4_rotation_for_z_degrees( angle ) ); } } class RotationKey { Callback m_rotationChanged; public: Float9 m_rotation; RotationKey( const Callback& rotationChanged ) : m_rotationChanged( rotationChanged ){ default_rotation( m_rotation ); } void angleChanged( const char* value ){ read_angle( m_rotation, value ); m_rotationChanged(); } typedef MemberCaller1 AngleChangedCaller; void rotationChanged( const char* value ){ read_rotation( m_rotation, value ); m_rotationChanged(); } typedef MemberCaller1 RotationChangedCaller; void write( Entity* entity ) const { Vector3 euler = matrix4_get_rotation_euler_xyz_degrees( rotation_toMatrix( m_rotation ) ); if ( euler[0] == 0 && euler[1] == 0 ) { entity->setKeyValue( "rotation", "" ); write_angle( euler[2], entity ); } else { entity->setKeyValue( "angle", "" ); write_rotation( m_rotation, entity ); } } }; #endif