- Timestamp:
- 06/28/16 21:09:19 (9 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/nv/core/random.hh
r487 r503 15 15 { 16 16 17 class random 18 { 19 public: 20 static constexpr uint32 mersenne_n = 624; 21 static constexpr uint32 mersenne_m = 397; 22 static constexpr uint32 mersenne_static_seed = 5489; 23 24 typedef uint32 result_type; // mt19937::result_type 17 class random_base 18 { 19 public: 20 typedef uint32 result_type; 25 21 typedef uint32 seed_type; 26 22 27 random( seed_type seed = 0 ); 28 seed_type randomize() { return set_seed( 0 ); } 29 seed_type set_seed( seed_type seed = 0 ); 30 static random& get(); 31 result_type rand(); 32 uint32 urand( uint32 val ); 23 virtual seed_type set_seed( seed_type seed = 0 ) = 0; 24 virtual result_type rand() = 0; 25 26 seed_type randomize() 27 { 28 return set_seed( randomized_seed() ); 29 } 30 31 uint32 urand( uint32 val ) 32 { 33 uint32 x, max = 0xFFFFFFFFUL - ( 0xFFFFFFFFUL % val ); 34 while ( ( x = rand() ) >= max ); 35 return x / ( max / val ); 36 } 33 37 34 38 sint32 srand( sint32 val ) 35 39 { 36 40 NV_ASSERT( val >= 0, "Bad srand range!" ); 37 return static_cast< sint32 >( urand( static_cast< uint32>( val ) ) );41 return static_cast<sint32>( urand( static_cast<uint32>( val ) ) ); 38 42 } 39 43 … … 53 57 // this method probably reduces range // 54 58 uint32 roll = urand( static_cast<uint32>( max - min ) + 1 ); 55 return static_cast< sint32>( roll ) + min;59 return static_cast<sint32>( roll ) + min; 56 60 } 57 61 … … 83 87 { 84 88 return math::tvec2<T>( 85 range_impl( min.x, max.x, is_floating_point<T>() ), 89 range_impl( min.x, max.x, is_floating_point<T>() ), 86 90 range_impl( min.y, max.y, is_floating_point<T>() ) 87 91 ); … … 92 96 { 93 97 return math::tvec3<T>( 94 range_impl( min.x, max.x, is_floating_point<T>() ), 98 range_impl( min.x, max.x, is_floating_point<T>() ), 95 99 range_impl( min.y, max.y, is_floating_point<T>() ), 96 100 range_impl( min.z, max.z, is_floating_point<T>() ) … … 102 106 { 103 107 return math::tvec4<T>( 104 range_impl( min.x, max.x, is_floating_point<T>() ), 108 range_impl( min.x, max.x, is_floating_point<T>() ), 105 109 range_impl( min.y, max.y, is_floating_point<T>() ), 106 range_impl( min.z, max.z, is_floating_point<T>() ), 107 range_impl( min.w, max.w, is_floating_point<T>() ) 110 range_impl( min.z, max.z, is_floating_point<T>() ), 111 range_impl( min.w, max.w, is_floating_point<T>() ) 108 112 ); 109 113 } 110 114 115 116 111 117 vec3 unit_vec3( bool = false ) 112 118 { 113 119 return precise_unit_vec3(); 114 // return precise ? precise_unit_vec3() : fast_unit_vec3();120 // return precise ? precise_unit_vec3() : fast_unit_vec3(); 115 121 } 116 122 vec2 unit_vec2( bool = false ) 117 123 { 118 124 return precise_unit_vec2(); 119 // return precise ? precise_unit_vec2() : fast_unit_vec2();125 // return precise ? precise_unit_vec2() : fast_unit_vec2(); 120 126 } 121 127 … … 174 180 //vec3 fast_unit_vec3(); 175 181 vec3 precise_unit_vec3(); 176 182 177 183 vec2 fast_disk_point(); 178 184 vec2 precise_disk_point(); … … 203 209 vec3 precise_hollow_ellipsoid_point( const vec3& iradii, const vec3& oradii ); 204 210 205 206 private: 211 protected: 207 212 static seed_type randomized_seed(); 208 213 … … 218 223 return srange( min, max ); 219 224 } 225 }; 226 227 class random_mersenne : public random_base 228 { 229 public: 230 static constexpr uint32 mersenne_n = 624; 231 static constexpr uint32 mersenne_m = 397; 232 static constexpr uint32 mersenne_static_seed = 5489; 233 234 explicit random_mersenne( seed_type seed = randomized_seed() ); 235 virtual seed_type set_seed( seed_type seed = 0 ); 236 virtual result_type rand(); 220 237 private: 221 238 void mt_init( uint32 seed ); 222 239 void mt_update(); 223 f64 mt_double();224 240 uint32 mt_uint32(); 225 241 226 uint32 m_state[ mersenne_n];242 uint32 m_state[mersenne_n]; 227 243 uint32* m_next; 228 244 uint32 m_remaining; 229 245 uint32 m_seeded : 1; 230 246 uint32 m_static_system_seed : 1; 231 232 // temporary solution until we get rid of ::random 233 char m_data[16 * 1024]; 247 }; 248 249 class random_xor128 : public random_base 250 { 251 public: 252 explicit random_xor128( seed_type seed = randomized_seed() ); 253 virtual seed_type set_seed( seed_type seed = 0 ); 254 virtual result_type rand(); 255 private: 256 uint32 m_state[4]; // xyzw 257 }; 258 259 260 class random : public random_mersenne 261 { 262 public: 263 explicit random( seed_type seed = randomized_seed() ) : random_mersenne( seed ) {}; 264 static random& get(); 234 265 }; 235 266 -
trunk/nv/core/types.hh
r487 r503 78 78 uint32 flags; //!< flags 79 79 uint32 offset; //!< offset into parent 80 type_field* control; //!< pointer to field control (in unions)80 sint32 control; //!< index to field control (in unions), -1 otherwise 81 81 sint32 enumidx; //!< field index (in unions) 82 82 }; … … 91 91 { 92 92 type_database* type_db; //!< Parent type database 93 thash64 hash; //!< type hash 93 94 shash64 name; //!< Scoped C++ name of the type 94 95 constructor_t constructor; //!< Pointers to the constructor … … 98 99 vector<type_field> field_list; //!< Field list 99 100 vector<type_enum> enum_list; //!< Enum list 100 hash_store< shash64, type_field*> field_names;101 hash_store< shash64, type_enum* >enum_names;101 hash_store< shash64, uint32 > field_names; 102 hash_store< shash64, uint32 > enum_names; 102 103 }; 103 104 … … 146 147 type_entry* i_type = new type_entry; 147 148 i_type->type_db = this; 149 i_type->hash = thash64::create< TYPE >(); 148 150 i_type->name = m_names.insert( name ); 149 151 i_type->size = sizeof( TYPE ); … … 151 153 i_type->constructor = raw_construct_object < TYPE >; 152 154 i_type->destructor = raw_destroy_object < TYPE >; 153 m_index_by_type[ thash64::create< TYPE >()] = i_type;155 m_index_by_type[ i_type->hash ] = i_type; 154 156 m_index_by_name[ i_type->name ] = i_type; 155 157 m_type_list.push_back( i_type ); … … 176 178 } 177 179 178 string_view resolve_name( shash64 name_hash ) 180 template< typename T > 181 const type_entry* get_type() const 182 { 183 auto it = m_index_by_type.find( thash64::create< T >() ); 184 return it != m_index_by_type.end() ? it->second : nullptr; 185 } 186 187 string_view resolve_name( shash64 name_hash ) const 179 188 { 180 189 return m_names[name_hash]; 190 } 191 192 string_view resolve_name( const type_entry* entry ) const 193 { 194 return m_names[entry->name]; 181 195 } 182 196 … … 211 225 ( is_pod<field_type>::value ? TF_SIMPLETYPE : 0 ); 212 226 f.offset = uint32( offset_of( field ) ); 213 f.control = nullptr;227 f.control = -1; 214 228 f.enumidx = 0; 215 229 m_entry->field_list.push_back( f ); 216 m_entry->field_names[f.name] = &m_entry->field_list.back();230 m_entry->field_names[f.name] = m_entry->field_list.size() - 1; 217 231 return *this; 218 232 } … … 229 243 ( is_pod<TFIELD>::value ? TF_SIMPLETYPE : 0 ); 230 244 f.offset = uint32( offset_of( field ) ); 231 f.control = nullptr;245 f.control = -1; 232 246 f.enumidx = 0; 233 247 m_entry->field_list.push_back( f ); 234 m_entry->field_names[f.name] = &m_entry->field_list.back();248 m_entry->field_names[f.name] = m_entry->field_list.size() - 1; 235 249 return *this; 236 250 } … … 248 262 ( is_pod<field_type>::value ? TF_SIMPLETYPE : 0 ); 249 263 f.offset = uint32( offset_of( field ) ); 250 f.control = m_entry->field_names[ control_name ];264 f.control = sint32( m_entry->field_names[ control_name ] ); 251 265 f.enumidx = static_cast< sint32 >( control_value ); 252 266 m_entry->field_list.push_back( f ); 253 m_entry->field_names[f.name] = &m_entry->field_list.back();267 m_entry->field_names[f.name] = m_entry->field_list.size() - 1; 254 268 return *this; 255 269 } … … 266 280 ( is_pod<TFIELD>::value ? TF_SIMPLETYPE : 0 ); 267 281 f.offset = uint32( offset_of( field ) ); 268 f.control = m_entry->field_names[control_name];282 f.control = sint32( m_entry->field_names[control_name] ); 269 283 f.enumidx = static_cast<sint32>( control_value ); 270 284 m_entry->field_list.push_back( f ); 271 m_entry->field_names[f.name] = &m_entry->field_list.back();285 m_entry->field_names[f.name] = m_entry->field_list.size() - 1; 272 286 return *this; 273 287 } … … 280 294 e.value = value; 281 295 m_entry->enum_list.push_back( e ); 282 m_entry->enum_names[e.name] = &m_entry->enum_list.back(); 283 return *this; 284 } 296 m_entry->enum_names[e.name] = m_entry->enum_list.size() - 1; 297 return *this; 298 } 299 300 void register_core_types( type_database* db ); 285 301 286 302 } -
trunk/nv/gfx/mesh_creator.hh
r482 r503 24 24 25 25 // assumes that position and normal is vec3, tangent is vec4 26 void transform( float scale, const mat3& r33 ); 26 void transform( const vec3& pos, const mat3& r33, float scale = 1.0f ); 27 // assumes that position and normal is vec3, tangent is vec4 28 void transform( const vec3& pos, const quat& r, float scale = 1.0f ) 29 { 30 transform( pos, mat3_cast(r), scale ); 31 } 32 // assumes that position and normal is vec3, tangent is vec4 33 void transform( const nv::transform& tr, float scale = 1.0f ) 34 { 35 transform( tr.get_position(), tr.get_orientation(), scale ); 36 } 37 // assumes that position and normal is vec3, tangent is vec4 38 void transform( float scale, const mat3& r33 ) 39 { 40 // remove this 41 transform( vec3(), r33, scale ); 42 } 27 43 // TODO: this could generate normals too 28 44 void generate_tangents(); -
trunk/nv/gl/gl_context.hh
r502 r503 53 53 virtual void set_draw_buffer( output_slot slot ); 54 54 virtual void set_read_buffer( output_slot slot ); 55 virtual void blit( framebuffer f, clear_state::buffers_typemask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 );56 virtual void blit( framebuffer from, framebuffer to, clear_state::buffers_typemask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 );55 virtual void blit( framebuffer f, buffer_mask mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 ); 56 virtual void blit( framebuffer from, framebuffer to, buffer_mask mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 ); 57 57 58 58 virtual void attach( framebuffer f, output_slot slot, texture t, int layer = -1 ); -
trunk/nv/gl/gl_enum.hh
r499 r503 24 24 25 25 unsigned int texture_type_to_enum( texture_type type ); 26 unsigned int clear_state_buffers_to_mask( clear_state::buffers_typetype );26 unsigned int clear_state_buffers_to_mask( buffer_mask type ); 27 27 unsigned int depth_state_function_to_enum( depth_test::function_type type ); 28 28 unsigned int polygon_mode_fill_to_enum( polygon_mode::fill_type type ); -
trunk/nv/interface/clear_state.hh
r395 r503 53 53 }; 54 54 55 enum buffer_mask 56 { 57 NO_BUFFER = 0, 58 COLOR_BUFFER = 1, 59 DEPTH_BUFFER = 2, 60 STENCIL_BUFFER = 4, 61 COLOR_AND_DEPTH_BUFFER = COLOR_BUFFER | DEPTH_BUFFER, 62 ALL_BUFFERS = COLOR_BUFFER | DEPTH_BUFFER | STENCIL_BUFFER 63 }; 64 55 65 struct clear_state 56 66 { 57 enum buffers_type58 {59 NONE = 0,60 COLOR_BUFFER = 1,61 DEPTH_BUFFER = 2,62 STENCIL_BUFFER = 4,63 COLOR_AND_DEPTH_BUFFER = COLOR_BUFFER | DEPTH_BUFFER,64 ALL = COLOR_BUFFER | DEPTH_BUFFER | STENCIL_BUFFER65 };66 67 67 nv::scissor_test scissor_test; 68 68 nv::color_mask color_mask; … … 71 71 uint32 back_stencil_mask; 72 72 73 buffer s_typebuffers;73 buffer_mask buffers; 74 74 vec4 color; 75 75 float depth; … … 79 79 : scissor_test(), color_mask(), depth_mask( true ), 80 80 front_stencil_mask( uint32(-1) ), back_stencil_mask( uint32(-1) ), 81 buffers( ALL ), color( vec4(0,0,0,1) ), depth( 1.0f ), stencil( 0 ) {}81 buffers( ALL_BUFFERS ), color( vec4(0,0,0,1) ), depth( 1.0f ), stencil( 0 ) {} 82 82 }; 83 83 84 84 } // namespace nv 85 85 86 NV_RTTI_DECLARE( nv::color_mask ) 87 NV_RTTI_DECLARE( nv::scissor_test ) 88 NV_RTTI_DECLARE( nv::clear_state ) 89 NV_RTTI_DECLARE( nv::buffer_mask ) 90 86 91 87 92 #endif // NV_INTERFACE_CLEAR_STATE_HH -
trunk/nv/interface/context.hh
r502 r503 185 185 virtual void set_draw_buffer( output_slot slot ) = 0; 186 186 virtual void set_read_buffer( output_slot slot ) = 0; 187 virtual void blit( framebuffer f, clear_state::buffers_typemask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 ) = 0;188 virtual void blit( framebuffer from, framebuffer to, clear_state::buffers_typemask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 ) = 0;187 virtual void blit( framebuffer f, buffer_mask mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 ) = 0; 188 virtual void blit( framebuffer from, framebuffer to, buffer_mask mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 ) = 0; 189 189 190 190 virtual void attach( framebuffer f, output_slot slot, texture t, int layer = -1 ) = 0; -
trunk/nv/interface/render_state.hh
r492 r503 206 206 } // namespace nv 207 207 208 NV_RTTI_DECLARE( nv::depth_test ) 209 NV_RTTI_DECLARE( nv::depth_test::function_type ) 210 NV_RTTI_DECLARE( nv::polygon_mode ) 211 NV_RTTI_DECLARE( nv::polygon_mode::fill_type ) 212 NV_RTTI_DECLARE( nv::blending ) 213 NV_RTTI_DECLARE( nv::blending::factor ) 214 NV_RTTI_DECLARE( nv::blending::equation ) 215 NV_RTTI_DECLARE( nv::stencil_test_face ) 216 NV_RTTI_DECLARE( nv::stencil_test_face::operation ) 217 NV_RTTI_DECLARE( nv::stencil_test_face::function_type ) 218 NV_RTTI_DECLARE( nv::stencil_test ) 219 NV_RTTI_DECLARE( nv::culling ) 220 NV_RTTI_DECLARE( nv::culling::face_type ) 221 NV_RTTI_DECLARE( nv::culling::order_type ) 222 NV_RTTI_DECLARE( nv::depth_range ) 223 NV_RTTI_DECLARE( nv::render_state ) 208 224 209 225 #endif // NV_INTERFACE_RENDER_STATE_HH -
trunk/nv/lua/lua_area.hh
r452 r503 18 18 namespace lua 19 19 { 20 void register_area( lua _State* L);20 void register_area( lua::state* state ); 21 21 22 22 template<> -
trunk/nv/lua/lua_aux.hh
r395 r503 14 14 namespace lua 15 15 { 16 void register_aux( lua _State* L);16 void register_aux( lua::state* state ); 17 17 } 18 18 } -
trunk/nv/lua/lua_map_area.hh
r395 r503 20 20 namespace lua 21 21 { 22 void register_map_area( lua _State* L);23 void register_map_area_interface( lua _State* L, int index );24 void register_map_area_instance( lua _State* L, ref object_index, map_area* area );22 void register_map_area( lua::state* state ); 23 void register_map_area_interface( lua::state* state, int index ); 24 void register_map_area_instance( lua::state* state, ref object_index, map_area* area ); 25 25 26 26 namespace detail -
trunk/nv/lua/lua_map_tile.hh
r395 r503 20 20 namespace lua 21 21 { 22 void register_map_tile( lua _State* L);22 void register_map_tile( lua::state* state ); 23 23 } 24 24 } -
trunk/nv/lua/lua_math.hh
r452 r503 10 10 #include <nv/common.hh> 11 11 #include <nv/stl/math.hh> 12 #include <nv/lua/lua_state.hh> 12 13 #include <nv/lua/lua_values.hh> 13 14 … … 16 17 namespace lua 17 18 { 18 void register_math( lua _State* L);19 void register_math( lua::state* state ); 19 20 20 21 template<> struct pass_traits< vec2 > : metatable_pass_traits< vec2 > { static const char* metatable() { return "vec2"; } }; -
trunk/nv/lua/lua_state.hh
r486 r503 13 13 14 14 #include <nv/common.hh> 15 #include <nv/core/types.hh> 15 16 #include <nv/stl/flags.hh> 16 17 #include <nv/stl/handle.hh> … … 34 35 namespace lua 35 36 { 37 36 38 class state; 37 39 40 using lua_rtti_read_function = bool(*)( state*, const type_entry*, void*, int index ); 41 using lua_rtti_push_function = void(*)( state*, const type_entry*, void* ); 42 43 44 class type_data 45 { 46 class entry 47 { 48 49 }; 50 public: 51 explicit type_data( type_database* db ) : m_type_database( db ) 52 { 53 register_standard_types(); 54 } 55 const type_database* get_type_database() const { return m_type_database; } 56 57 template < typename T > 58 void insert( lua_rtti_push_function p, lua_rtti_read_function r ) 59 { 60 insert( thash64::create<T>(), p, r ); 61 } 62 void insert( thash64 tid, lua_rtti_push_function p, lua_rtti_read_function r ); 63 64 template < typename T > 65 lua_rtti_read_function* get_push() const 66 { 67 return get_read( thash64::create<T>() ); 68 } 69 70 template < typename T > 71 lua_rtti_push_function* get_push() const 72 { 73 return get_push( thash64::create<T>() ); 74 } 75 76 const lua_rtti_read_function* get_read( thash64 h ) const 77 { 78 auto f = m_type_read.find( h ); 79 return f != m_type_read.end() ? &f->second : nullptr; 80 } 81 const lua_rtti_push_function* get_push( thash64 h ) const 82 { 83 auto f = m_type_push.find( h ); 84 return f != m_type_push.end() ? &f->second : nullptr; 85 } 86 protected: 87 void register_standard_types(); 88 89 hash_store< thash64, lua_rtti_read_function > m_type_read; 90 hash_store< thash64, lua_rtti_push_function > m_type_push; 91 type_database* m_type_database; 92 }; 93 38 94 const int ret_multi = -1; 39 95 … … 41 97 { 42 98 public: 43 state_wrapper( lua_State* a_state, bool a_owner ) : m_state( a_state), m_owner( a_owner ), m_global( true ) {}99 state_wrapper( lua_State* a_state, type_data* types, bool a_owner ) : m_state( a_state ), m_lua_types( types ), m_owner( a_owner ), m_global( true ) {} 44 100 virtual ~state_wrapper(); 45 101 … … 143 199 register_native_function( detail::object_method_wrapper< C, F, f >, name ); 144 200 } 201 202 const type_data* get_type_data() const { return m_lua_types; } 145 203 146 204 protected: … … 155 213 protected: 156 214 lua_State* m_state; 215 type_data* m_lua_types; 157 216 bool m_owner; 158 217 bool m_global; … … 191 250 192 251 public: 193 explicit state( bool load_libs = false );194 explicit state( lua_State* state );252 explicit state( bool load_libs = false, type_database* types = nullptr ); 253 explicit state( lua_State* state, type_database* types = nullptr ); 195 254 bool do_string( string_view code, string_view name, int rvalues = 0 ); 196 255 bool do_file( string_view filename ); … … 279 338 } 280 339 340 virtual ~state(); 341 342 template < typename T > 343 void register_rtti_type( lua_rtti_push_function p, lua_rtti_read_function r ) 344 { 345 register_rtti_type( thash64::create< T >(), p, r ); 346 } 347 281 348 private: 349 void register_rtti_type( thash64 tid, lua_rtti_push_function p, lua_rtti_read_function r ); 282 350 ref register_handle_component_impl( string_view id, bool empty ); 283 351 void unregister_handle_component_impl( string_view id ); … … 313 381 bool is_boolean( string_view element ); 314 382 bool is_string( string_view element ); 383 template < typename T > 384 bool read( const string_view& element, T& t ) 385 { 386 NV_ASSERT( m_lua_types, "table_guard::read - type database not created!" ); 387 NV_ASSERT( m_lua_types->get_type_database(), "table_guard::read - type database not set!" ); 388 const type_entry* entry = m_lua_types->get_type_database()->get_type<T>(); 389 return read( element, entry, &t ); 390 } 391 bool read( const string_view& element, const type_entry* entry, void* object ); 392 315 393 private: 394 state* m_parent; 316 395 int m_level; 317 396 }; -
trunk/src/core/random.cc
r487 r503 19 19 #define NV_MT_TWIST(u, v) ( (NV_MT_MIXBITS(u, v) >> 1) ^ ( (v) & 1UL ? mt_matrix_a : 0UL) ) 20 20 21 void random::mt_init( uint32 seed ) 21 nv::random& random::get() 22 { 23 static random default_rng; 24 return default_rng; 25 } 26 27 void random_mersenne::mt_init( uint32 seed ) 22 28 { 23 29 m_state[0] = static_cast<uint32>( seed & mt_full_mask ); … … 34 40 35 41 36 void random ::mt_update()42 void random_mersenne::mt_update() 37 43 { 38 44 uint32 *p = m_state; … … 51 57 52 58 53 uint32 random ::mt_uint32()59 uint32 random_mersenne::mt_uint32() 54 60 { 55 61 uint32 r; … … 70 76 } 71 77 72 random ::random( random::seed_type seed /*= 0 */ )78 random_mersenne::random_mersenne( random_mersenne::seed_type seed /*= 0 */ ) 73 79 : m_next( nullptr ), m_remaining( 0 ), m_seeded( 0 ) 74 80 { 75 mt_init( seed == 0 ? randomized_seed() : seed ); 76 } 77 78 random::seed_type random::set_seed( random::seed_type seed /*= 0 */ ) 79 { 80 if ( seed == 0 ) seed = randomized_seed(); 81 mt_init( seed ); 82 } 83 84 random_mersenne::seed_type random_mersenne::set_seed( random_mersenne::seed_type seed /*= 0 */ ) 85 { 81 86 mt_init( seed ); 82 87 return seed; 83 88 } 84 89 85 nv::random& random::get() 86 { 87 static random default_rng; 88 return default_rng; 89 } 90 91 random::result_type random::rand() 90 random_mersenne::result_type random_mersenne::rand() 92 91 { 93 92 return mt_uint32(); 94 93 } 95 94 96 uint32 random::urand( uint32 val ) 97 { 98 uint32 x, max = mt_full_mask - ( mt_full_mask % val ); 99 while ( ( x = rand() ) >= max ); 100 return x / ( max / val ); 101 } 102 103 random::seed_type random::randomized_seed() 95 random_base::seed_type random_base::randomized_seed() 104 96 { 105 97 // TODO: this seems off, as it might often seed the same, use general time … … 108 100 } 109 101 110 nv::vec2 nv::random ::precise_unit_vec2()102 nv::vec2 nv::random_base::precise_unit_vec2() 111 103 { 112 104 f32 angle = frand( math::pi<f32>() * 2.f ); … … 114 106 } 115 107 116 nv::vec3 nv::random ::precise_unit_vec3()108 nv::vec3 nv::random_base::precise_unit_vec3() 117 109 { 118 110 f32 cos_theta = frange( -1.0f, 1.0f ); … … 126 118 } 127 119 128 nv::vec2 nv::random ::fast_disk_point()120 nv::vec2 nv::random_base::fast_disk_point() 129 121 { 130 122 f32 r1 = frand(); … … 135 127 } 136 128 137 nv::vec2 nv::random ::precise_disk_point()129 nv::vec2 nv::random_base::precise_disk_point() 138 130 { 139 131 f32 r = sqrt( frand() ); … … 142 134 } 143 135 144 nv::vec3 nv::random ::fast_sphere_point()136 nv::vec3 nv::random_base::fast_sphere_point() 145 137 { 146 138 f32 rad = frand(); … … 156 148 } 157 149 158 nv::vec3 nv::random ::precise_sphere_point()150 nv::vec3 nv::random_base::precise_sphere_point() 159 151 { 160 152 f32 radius = pow( frand(), 1.f/3.f ); … … 169 161 } 170 162 171 nv::vec2 nv::random ::precise_ellipse_point( const vec2& radii )163 nv::vec2 nv::random_base::precise_ellipse_point( const vec2& radii ) 172 164 { 173 165 vec2 p = range( -radii, radii ); … … 184 176 } 185 177 186 nv::vec3 nv::random ::precise_ellipsoid_point( const vec3& radii )178 nv::vec3 nv::random_base::precise_ellipsoid_point( const vec3& radii ) 187 179 { 188 180 vec3 p = range( -radii, radii ); … … 199 191 } 200 192 201 nv::vec2 nv::random ::fast_hollow_disk_point( f32 iradius, f32 oradius )193 nv::vec2 nv::random_base::fast_hollow_disk_point( f32 iradius, f32 oradius ) 202 194 { 203 195 f32 idist2 = iradius * iradius; … … 207 199 } 208 200 209 nv::vec2 nv::random ::precise_hollow_disk_point( f32 iradius, f32 oradius )201 nv::vec2 nv::random_base::precise_hollow_disk_point( f32 iradius, f32 oradius ) 210 202 { 211 203 return fast_hollow_disk_point( iradius, oradius ); 212 204 } 213 205 214 nv::vec3 nv::random ::fast_hollow_sphere_point( f32 iradius, f32 oradius )206 nv::vec3 nv::random_base::fast_hollow_sphere_point( f32 iradius, f32 oradius ) 215 207 { 216 208 f32 idist3 = iradius * iradius * iradius; … … 220 212 } 221 213 222 nv::vec3 nv::random ::precise_hollow_sphere_point( f32 iradius, f32 oradius )214 nv::vec3 nv::random_base::precise_hollow_sphere_point( f32 iradius, f32 oradius ) 223 215 { 224 216 return fast_hollow_sphere_point( iradius, oradius ); … … 226 218 227 219 228 nv::vec2 nv::random ::fast_hollow_ellipse_point( const vec2& iradii, const vec2& oradii )220 nv::vec2 nv::random_base::fast_hollow_ellipse_point( const vec2& iradii, const vec2& oradii ) 229 221 { 230 222 vec2 iradii2 = iradii * iradii; … … 241 233 } 242 234 243 nv::vec2 nv::random ::precise_hollow_ellipse_point( const vec2& iradii, const vec2& oradii )235 nv::vec2 nv::random_base::precise_hollow_ellipse_point( const vec2& iradii, const vec2& oradii ) 244 236 { 245 237 return fast_hollow_ellipse_point( iradii, oradii ); 246 238 } 247 239 248 nv::vec3 nv::random ::fast_hollow_ellipsoid_point( const vec3& iradii, const vec3& oradii )240 nv::vec3 nv::random_base::fast_hollow_ellipsoid_point( const vec3& iradii, const vec3& oradii ) 249 241 { 250 242 vec3 iradii2 = iradii * iradii; … … 267 259 } 268 260 269 nv::vec3 nv::random ::precise_hollow_ellipsoid_point( const vec3& iradii, const vec3& oradii )261 nv::vec3 nv::random_base::precise_hollow_ellipsoid_point( const vec3& iradii, const vec3& oradii ) 270 262 { 271 263 return fast_hollow_ellipsoid_point( iradii, oradii ); 272 264 } 273 265 266 nv::random_xor128::random_xor128( seed_type seed /*= randomized_seed() */ ) 267 { 268 set_seed( seed ); 269 } 270 271 nv::random_base::seed_type nv::random_xor128::set_seed( seed_type seed /*= 0 */ ) 272 { 273 uint32 s = 4294967296 - seed; 274 m_state[0] = 123456789 * s; 275 m_state[1] = 362436069 * s; 276 m_state[2] = 521288629 * s; 277 m_state[3] = 88675123 * s; 278 return seed; 279 } 280 281 nv::random_base::result_type nv::random_xor128::rand() 282 { 283 uint32 t = m_state[0]; 284 t ^= t << 11; 285 t ^= t >> 8; 286 m_state[0] = m_state[1]; m_state[1] = m_state[2]; m_state[2] = m_state[3]; 287 m_state[3] ^= m_state[3] >> 19; 288 m_state[3] ^= t; 289 return m_state[3]; 290 } -
trunk/src/gfx/mesh_creator.cc
r491 r503 88 88 89 89 90 void nv::mesh_data_creator::transform( float scale, const mat3& r33)91 { 92 vec3 vertex_offset = vec3();93 mat3 vertex_transform 94 mat3 normal_transform 90 void nv::mesh_data_creator::transform( const vec3& pos, const mat3& r33, float scale /*= 1.0f */ ) 91 { 92 vec3 vertex_offset = pos; 93 mat3 vertex_transform = scale * r33; 94 mat3 normal_transform = r33; 95 95 96 96 for ( uint32 c = 0; c < m_data->size(); ++c ) 97 97 { 98 98 raw_data_channel_access channel( m_data, c ); 99 const data_descriptor& desc 99 const data_descriptor& desc = channel.descriptor(); 100 100 uint8* raw_data = channel.raw_data(); 101 101 uint32 vtx_size = desc.element_size(); … … 103 103 int n_offset = -1; 104 104 int t_offset = -1; 105 for ( const auto& cslot : desc 105 for ( const auto& cslot : desc ) 106 106 switch ( cslot.vslot ) 107 107 { 108 case slot::POSITION: if ( cslot.etype == FLOAT_VECTOR_3 ) p_offset = int( cslot.offset ); break;109 case slot::NORMAL: if ( cslot.etype == FLOAT_VECTOR_3 ) n_offset = int( cslot.offset ); break;110 case slot::TANGENT: if ( cslot.etype == FLOAT_VECTOR_4 ) t_offset = int( cslot.offset ); break;111 default: break;108 case slot::POSITION: if ( cslot.etype == FLOAT_VECTOR_3 ) p_offset = int( cslot.offset ); break; 109 case slot::NORMAL: if ( cslot.etype == FLOAT_VECTOR_3 ) n_offset = int( cslot.offset ); break; 110 case slot::TANGENT: if ( cslot.etype == FLOAT_VECTOR_4 ) t_offset = int( cslot.offset ); break; 111 default: break; 112 112 } 113 113 114 114 if ( p_offset != -1 ) 115 for ( uint32 i = 0; i < channel.size(); i++ )115 for ( uint32 i = 0; i < channel.size(); i++ ) 116 116 { 117 117 vec3& p = *reinterpret_cast<vec3*>( raw_data + vtx_size*i + p_offset ); … … 120 120 121 121 if ( n_offset != -1 ) 122 for ( uint32 i = 0; i < channel.size(); i++ )122 for ( uint32 i = 0; i < channel.size(); i++ ) 123 123 { 124 124 vec3& n = *reinterpret_cast<vec3*>( raw_data + vtx_size*i + n_offset ); … … 126 126 } 127 127 if ( t_offset != -1 ) 128 for ( uint32 i = 0; i < channel.size(); i++) 129 { 130 vec4& t = *reinterpret_cast<vec4*>(raw_data + vtx_size*i + t_offset ); 131 t = vec4( math::normalize( normal_transform * vec3(t) ), t[3] ); 132 } 133 } 134 } 128 for ( uint32 i = 0; i < channel.size(); i++ ) 129 { 130 vec4& t = *reinterpret_cast<vec4*>( raw_data + vtx_size*i + t_offset ); 131 t = vec4( math::normalize( normal_transform * vec3( t ) ), t[3] ); 132 } 133 } 134 } 135 135 136 136 137 struct vertex_g -
trunk/src/gl/gl_context.cc
r502 r503 201 201 } 202 202 203 void nv::gl_context::blit( framebuffer f, clear_state::buffers_typemask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 )203 void nv::gl_context::blit( framebuffer f, buffer_mask mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 ) 204 204 { 205 205 gl_framebuffer_info* info = m_framebuffers.get( f ); … … 207 207 { 208 208 glBindFramebuffer( GL_FRAMEBUFFER, info->glid ); 209 unsigned filter = mask == clear_state::COLOR_BUFFER ? GL_LINEAR : GL_NEAREST;209 unsigned filter = mask == buffer_mask::COLOR_BUFFER ? GL_LINEAR : GL_NEAREST; 210 210 glBlitFramebuffer( src1.x, src1.y, src2.x, src2.y, dst1.x, dst1.y, dst2.x, dst2.y, clear_state_buffers_to_mask( mask ), filter ); 211 211 } … … 213 213 214 214 215 void nv::gl_context::blit( framebuffer from, framebuffer to, clear_state::buffers_typemask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 )215 void nv::gl_context::blit( framebuffer from, framebuffer to, buffer_mask mask, ivec2 src1, ivec2 src2, ivec2 dst1, ivec2 dst2 ) 216 216 { 217 217 gl_framebuffer_info* finfo = m_framebuffers.get( from ); … … 221 221 glBindFramebuffer( GL_READ_FRAMEBUFFER, finfo->glid ); 222 222 glBindFramebuffer( GL_DRAW_FRAMEBUFFER, tinfo ? tinfo->glid : 0 ); 223 unsigned filter = mask == clear_state::COLOR_BUFFER ? GL_LINEAR : GL_NEAREST;223 unsigned filter = mask == buffer_mask::COLOR_BUFFER ? GL_LINEAR : GL_NEAREST; 224 224 glBlitFramebuffer( src1.x, src1.y, src2.x, src2.y, dst1.x, dst1.y, dst2.x, dst2.y, clear_state_buffers_to_mask( mask ), filter ); 225 225 glBindFramebuffer( GL_READ_FRAMEBUFFER, 0 ); -
trunk/src/gl/gl_enum.cc
r500 r503 28 28 } 29 29 30 unsigned int nv::clear_state_buffers_to_mask( clear_state::buffers_typetype )30 unsigned int nv::clear_state_buffers_to_mask( buffer_mask type ) 31 31 { 32 32 unsigned int mask = 0; 33 if ( (type & clear_state::COLOR_BUFFER) != 0 ) mask |= GL_COLOR_BUFFER_BIT;34 if ( (type & clear_state::DEPTH_BUFFER) != 0 ) mask |= GL_DEPTH_BUFFER_BIT;35 if ( (type & clear_state::STENCIL_BUFFER) != 0 ) mask |= GL_STENCIL_BUFFER_BIT;33 if ( (type & buffer_mask::COLOR_BUFFER) != 0 ) mask |= GL_COLOR_BUFFER_BIT; 34 if ( (type & buffer_mask::DEPTH_BUFFER) != 0 ) mask |= GL_DEPTH_BUFFER_BIT; 35 if ( (type & buffer_mask::STENCIL_BUFFER) != 0 ) mask |= GL_STENCIL_BUFFER_BIT; 36 36 return mask; 37 37 } -
trunk/src/lua/lua_area.cc
r491 r503 459 459 } 460 460 461 void nv::lua::register_area( lua _State* L)462 { 463 int stack = lua_gettop( L);464 nlua_requiref( L, "area", luaopen_area, 1);465 lua_settop( L, stack );466 } 467 461 void nv::lua::register_area( lua::state* state ) 462 { 463 int stack = lua_gettop( state->get_raw() ); 464 nlua_requiref( state->get_raw(), "area", luaopen_area, 1); 465 lua_settop( state->get_raw(), stack ); 466 } 467 -
trunk/src/lua/lua_aux.cc
r490 r503 137 137 }; 138 138 139 void nv::lua::register_aux( lua _State* L)139 void nv::lua::register_aux( lua::state* state ) 140 140 { 141 nlua_register( L, "table", nluaaux_table_aux_f );142 nlua_register( L, "math", nluaaux_math_aux_f );141 nlua_register( state->get_raw(), "table", nluaaux_table_aux_f ); 142 nlua_register( state->get_raw(), "math", nluaaux_math_aux_f ); 143 143 } 144 144 -
trunk/src/lua/lua_map_area.cc
r490 r503 223 223 } 224 224 225 void nv::lua::register_map_area_interface( lua_State* L, int index ) 226 { 227 nlua_register( L, nlua_map_area_f, index ); 228 } 229 230 void nv::lua::register_map_area( lua_State* L ) 231 { 232 luaopen_map_area(L); 233 } 234 235 void nv::lua::register_map_area_instance( lua_State* L, ref object_index, map_area* area ) 236 { 225 void nv::lua::register_map_area_interface( lua::state* state, int index ) 226 { 227 nlua_register( state->get_raw(), nlua_map_area_f, index ); 228 } 229 230 void nv::lua::register_map_area( lua::state* state ) 231 { 232 luaopen_map_area( state->get_raw() ); 233 } 234 235 void nv::lua::register_map_area_instance( lua::state* state, ref object_index, map_area* area ) 236 { 237 lua_State* L = state->get_raw(); 237 238 lua_rawgeti( L, LUA_REGISTRYINDEX, object_index.get() ); 238 239 lua_pushliteral( L, "__map_area_ptr" ); -
trunk/src/lua/lua_map_tile.cc
r490 r503 366 366 }; 367 367 368 void nv::lua::register_map_tile( lua _State * L)368 void nv::lua::register_map_tile( lua::state* state ) 369 369 { 370 370 // TODO: check if __gc is used! 371 lua_State* L = state->get_raw(); 371 372 luaL_newmetatable( L, NLUA_MAP_TILE_METATABLE ); 372 373 lua_pushvalue( L, -1 ); -
trunk/src/lua/lua_math.cc
r490 r503 359 359 } 360 360 361 void nv::lua::register_math( lua_State* L ) 361 template < typename T > 362 void nlua_rtti_vec_push( nv::lua::state* state, const nv::type_entry*, void* object ) 363 { 364 T* value = reinterpret_cast<T*>( object ); 365 push_vec<T>( state->get_raw(), *value ); 366 } 367 368 template < typename T > 369 bool nlua_rtti_vec_read( nv::lua::state* state, const nv::type_entry*, void* object, int index ) 370 { 371 T* value = reinterpret_cast<T*>( object ); 372 int type = lua_type( state->get_raw(), index ); 373 if ( type == LUA_TUSERDATA ) 374 { 375 T* from = to_pvec<T>( state->get_raw(), index ); 376 if ( !from ) return false; 377 *value = *from; 378 } 379 // else if ( type == LUA_TTABLE ) 380 // { 381 // 382 // } 383 else 384 return false; 385 int todo; int table_constructor; 386 return true; 387 } 388 389 void nv::lua::register_math( lua::state* state ) 362 390 { 363 391 for (size_t i = 0; i < 256; ++i ) nlua_swizzel_lookup[i] = 255; … … 379 407 nlua_swizzel_lookup[uchar8( 'v' )] = 0; 380 408 nlua_swizzel_lookup[uchar8( '3' )] = 3; 409 410 lua_State* L = state->get_raw(); 381 411 int stack = lua_gettop( L ); 382 412 … … 389 419 nlua_requiref(L, "vec4", luaopen_vec<nv::vec4>, 1); 390 420 lua_settop( L, stack ); 391 } 392 421 422 state->register_rtti_type< nv::ivec2 >( nlua_rtti_vec_push<nv::ivec2>, nlua_rtti_vec_read<nv::ivec2> ); 423 state->register_rtti_type< nv::ivec3 >( nlua_rtti_vec_push<nv::ivec3>, nlua_rtti_vec_read<nv::ivec3> ); 424 state->register_rtti_type< nv::ivec4 >( nlua_rtti_vec_push<nv::ivec4>, nlua_rtti_vec_read<nv::ivec4> ); 425 state->register_rtti_type< nv::vec2 > ( nlua_rtti_vec_push<nv::vec2>, nlua_rtti_vec_read<nv::vec2> ); 426 state->register_rtti_type< nv::vec3 > ( nlua_rtti_vec_push<nv::vec3>, nlua_rtti_vec_read<nv::vec3> ); 427 state->register_rtti_type< nv::vec4 > ( nlua_rtti_vec_push<nv::vec4>, nlua_rtti_vec_read<nv::vec4> ); 428 } 429 -
trunk/src/lua/lua_state.cc
r490 r503 9 9 #include "nv/lua/lua_raw.hh" 10 10 #include "nv/lua/lua_nova.hh" 11 #include "nv/lua/lua_types.hh" 11 12 #include "nv/core/logging.hh" 12 13 #include "nv/stl/string.hh" … … 143 144 144 145 lua::table_guard::table_guard( lua::state* lstate, const path& p, bool global ) 145 : state_wrapper( lstate->get_raw(), false ), m_level(0)146 : state_wrapper( lstate->get_raw(), lstate->m_lua_types, false ), m_parent( lstate ), m_level(0) 146 147 { 147 148 m_global = false; … … 155 156 156 157 lua::table_guard::table_guard( const table_guard& parent, const path& p ) 157 : state_wrapper( parent.m_state, false), m_level(0)158 : state_wrapper( parent.m_state, parent.m_lua_types, false ), m_parent( parent.m_parent ), m_level(0) 158 159 { 159 160 m_global = false; … … 350 351 351 352 353 bool nv::lua::table_guard::read( const string_view& element, const type_entry* entry, void* object ) 354 { 355 NV_ASSERT_ALWAYS( m_lua_types->get_type_database() == entry->type_db, "Type database mismatch between Lua and entry!" ); 356 lua_getfield( m_state, -1, element.data() ); 357 if ( lua_type( m_state, -1 ) != LUA_TTABLE ) 358 { 359 lua_pop( m_state, 1 ); 360 return false; 361 } 362 if ( !nv::lua::read_rtti_type( m_parent, entry, object, -1 ) ) 363 { 364 lua_pop( m_state, 1 ); 365 return false; 366 } 367 lua_pop( m_state, 1 ); 368 return true; 369 } 370 352 371 // state 353 372 354 lua::state::state( lua_State* state ) : state_wrapper( state, false ) 355 { 356 357 } 358 359 lua::state::state( bool load_libs /*= false*/ ) : state_wrapper( nullptr, true ) 373 lua::state::state( lua_State* state, type_database* types ) 374 : state_wrapper( state, new type_data( types ), false ) 375 { 376 377 } 378 379 lua::state::state( bool load_libs /*= false*/, type_database* types ) 380 : state_wrapper( nullptr, new type_data( types ), true ) 360 381 { 361 382 load_lua_library(); … … 575 596 } 576 597 598 void nv::lua::state::register_rtti_type( thash64 tid, lua_rtti_push_function p, lua_rtti_read_function r ) 599 { 600 m_lua_types->insert( tid, p, r ); 601 } 602 577 603 nv::lua::ref nv::lua::state::register_handle_component_impl( string_view id, bool empty ) 578 604 { … … 626 652 } 627 653 654 nv::lua::state::~state() 655 { 656 delete m_lua_types; 657 m_lua_types = nullptr; 658 } 659 660 template < typename T > 661 void nlua_rtti_signed_push( nv::lua::state* state, const type_entry*, void* object ) 662 { 663 T* value = reinterpret_cast<T*>( object ); 664 lua_pushinteger( state->get_raw(), lua_Integer( *value ) ); 665 } 666 667 template < typename T > 668 void nlua_rtti_unsigned_push( nv::lua::state* state, const type_entry*, void* object ) 669 { 670 T* value = reinterpret_cast<T*>( object ); 671 lua_pushinteger( state->get_raw(), lua_Unsigned( *value ) ); 672 } 673 674 template < typename T > 675 void nlua_rtti_floating_push( nv::lua::state* state, const type_entry*, void* object ) 676 { 677 T* value = reinterpret_cast< T* >( object ); 678 lua_pushnumber( state->get_raw(), lua_Number( *value ) ); 679 } 680 681 static void nlua_rtti_boolean_push( nv::lua::state* state, const type_entry*, void* object ) 682 { 683 bool* value = reinterpret_cast<bool*>( object ); 684 lua_pushboolean( state->get_raw(), *value ); 685 } 686 687 template < typename T > 688 bool nlua_rtti_signed_read( nv::lua::state* state, const type_entry*, void* object, int index ) 689 { 690 T* value = reinterpret_cast<T*>( object ); 691 if ( lua_type( state->get_raw(), index ) == LUA_TNUMBER ) 692 { 693 *value = T( lua_tointeger( state->get_raw(), index ) ); 694 return true; 695 } 696 return false; 697 } 698 699 template < typename T > 700 bool nlua_rtti_unsigned_read( nv::lua::state* state, const type_entry*, void* object, int index ) 701 { 702 T* value = reinterpret_cast<T*>( object ); 703 if ( lua_type( state->get_raw(), index ) == LUA_TNUMBER ) 704 { 705 *value = T( lua_tointeger( state->get_raw(), index ) ); 706 return true; 707 } 708 return false; 709 } 710 711 template < typename T > 712 bool nlua_rtti_floating_read( nv::lua::state* state, const type_entry*, void* object, int index ) 713 { 714 T* value = reinterpret_cast<T*>( object ); 715 if ( lua_type( state->get_raw(), index ) == LUA_TNUMBER ) 716 { 717 *value = T( lua_tonumber( state->get_raw(), index ) ); 718 return true; 719 } 720 return false; 721 } 722 723 static bool nlua_rtti_boolean_read( nv::lua::state* state, const type_entry*, void* object, int index ) 724 { 725 bool* value = reinterpret_cast<bool*>( object ); 726 if ( lua_type( state->get_raw(), index ) == LUA_TBOOLEAN ) 727 { 728 *value = bool( lua_toboolean( state->get_raw(), index ) ); 729 return true; 730 } 731 return false; 732 } 733 734 735 void nv::lua::type_data::insert( thash64 tid, lua_rtti_push_function p, lua_rtti_read_function r ) 736 { 737 m_type_read.assign( tid, r ); 738 m_type_push.assign( tid, p ); 739 } 740 741 void nv::lua::type_data::register_standard_types() 742 { 743 insert<bool>( nlua_rtti_boolean_push, nlua_rtti_boolean_read ); 744 insert<nv::sint8> ( nlua_rtti_signed_push<nv::sint8>, nlua_rtti_signed_read<nv::sint8> ); 745 insert<nv::sint16>( nlua_rtti_signed_push<nv::sint16>, nlua_rtti_signed_read<nv::sint16> ); 746 insert<nv::sint32>( nlua_rtti_signed_push<nv::sint32>, nlua_rtti_signed_read<nv::sint32> ); 747 insert<nv::uint8> ( nlua_rtti_unsigned_push<nv::uint8>, nlua_rtti_unsigned_read<nv::uint8> ); 748 insert<nv::uint16>( nlua_rtti_unsigned_push<nv::uint16>, nlua_rtti_unsigned_read<nv::uint16> ); 749 insert<nv::uint32>( nlua_rtti_unsigned_push<nv::uint32>, nlua_rtti_unsigned_read<nv::uint32> ); 750 insert<nv::f32> ( nlua_rtti_floating_push<nv::f32>, nlua_rtti_floating_read<nv::f32> ); 751 insert<nv::f64> ( nlua_rtti_floating_push<nv::f64>, nlua_rtti_floating_read<nv::f64> ); 752 // insert<nv::sint64>( nlua_rtti_floating_push<nv::sint64>, nlua_rtti_floating_read<nv::sint64> ); 753 // insert<nv::uint64>( nlua_rtti_floating_push<nv::uint64>, nlua_rtti_floating_read<nv::uint64> ); 754 }
Note: See TracChangeset
for help on using the changeset viewer.