.doc/ext/rays/matrix.cpp in rays-0.1.12 vs .doc/ext/rays/matrix.cpp in rays-0.1.13

- old
+ new

@@ -1,17 +1,14 @@ #include "rays/ruby/matrix.h" -#include <rucy.h> +#include "rays/ruby/point.h" #include "defs.h" -using namespace Rucy; +RUCY_DEFINE_VALUE_OR_ARRAY_FROM_TO(Rays::Matrix) - -RUCY_DEFINE_VALUE_FROM_TO(Rays::Matrix) - #define THIS to<Rays::Matrix*>(self) #define CHECK RUCY_CHECK_OBJ(Rays::Matrix, self) @@ -25,27 +22,13 @@ VALUE initialize(VALUE self) { CHECK; check_arg_count(__FILE__, __LINE__, "Matrix#initialize", argc, 0, 1, 16); - if (argc == 0) return self; + if (argc > 0) + *THIS = to<Rays::Matrix>(argc, argv); - switch (argc) - { - case 1: - *THIS = Rays::Matrix(to<float>(argv[0])); - break; - - case 16: - *THIS = Rays::Matrix( - to<float>(argv[0]), to<float>(argv[1]), to<float>(argv[2]), to<float>(argv[3]), - to<float>(argv[4]), to<float>(argv[5]), to<float>(argv[6]), to<float>(argv[7]), - to<float>(argv[8]), to<float>(argv[9]), to<float>(argv[10]), to<float>(argv[11]), - to<float>(argv[12]), to<float>(argv[13]), to<float>(argv[14]), to<float>(argv[15])); - break; - } - return self; } static VALUE initialize_copy(VALUE self, VALUE obj) @@ -54,27 +37,27 @@ *THIS = to<Rays::Matrix&>(obj); return self; } static -VALUE set(VALUE self) +VALUE reset(VALUE self) { CHECK; - check_arg_count(__FILE__, __LINE__, "Matrix#initialize", argc, 0, 1, 16); + check_arg_count(__FILE__, __LINE__, "Matrix#reset", argc, 0, 1, 16); switch (argc) { case 0: - *THIS = Rays::Matrix(); + THIS->reset(); break; case 1: - *THIS = Rays::Matrix(to<float>(argv[0])); + THIS->reset(to<float>(argv[0])); break; case 16: - *THIS = Rays::Matrix( + THIS->reset( to<float>(argv[0]), to<float>(argv[1]), to<float>(argv[2]), to<float>(argv[3]), to<float>(argv[4]), to<float>(argv[5]), to<float>(argv[6]), to<float>(argv[7]), to<float>(argv[8]), to<float>(argv[9]), to<float>(argv[10]), to<float>(argv[11]), to<float>(argv[12]), to<float>(argv[13]), to<float>(argv[14]), to<float>(argv[15])); break; @@ -82,17 +65,133 @@ return self; } static -VALUE at(VALUE self, VALUE row, VALUE column) +VALUE translate(VALUE self) { CHECK; + check_arg_count(__FILE__, __LINE__, "Matrix#translate", argc, 1, 2, 3); + + THIS->translate(to<Rays::Point>(argc, argv)); + return self; +} + +static +VALUE scale(VALUE self) +{ + CHECK; + check_arg_count(__FILE__, __LINE__, "Matrix#scale", argc, 1, 2, 3); + + THIS->scale(to<Rays::Point>(argc, argv)); + return self; +} + +static +VALUE rotate(VALUE self) +{ + CHECK; + check_arg_count(__FILE__, __LINE__, "Matrix#rotate", argc, 1, 2, 4); + + float degree = to<float>(argv[0]); + + if (argc == 1) + THIS->rotate(degree); + else + THIS->rotate(degree, to<Rays::Point>(argc - 1, argv + 1)); + + return self; +} + +static +VALUE to_a(VALUE self) +{ + CHECK; + return array( + THIS->x0, THIS->y0, THIS->z0, THIS->w0, + THIS->x1, THIS->y1, THIS->z1, THIS->w1, + THIS->x2, THIS->y2, THIS->z2, THIS->w2, + THIS->x3, THIS->y3, THIS->z3, THIS->w3); +} + +static +VALUE mult(VALUE self, VALUE val) +{ + CHECK; + + if (val.is_kind_of(Rays::matrix_class())) + return value(*THIS * to<Rays::Matrix&>(val)); + + if (val.is_kind_of(Rays::point_class())) + return value(*THIS * to<Rays::Point&>(val)); + + if (val.is_array()) + { + if (val.size() == 16) + return value(*THIS * to<Rays::Matrix>(val)); + else + return value(*THIS * to<Rays::Point>(val)); + } + + argument_error(__FILE__, __LINE__); +} + +static +VALUE set_at(VALUE self, VALUE row, VALUE column, VALUE val) +{ + CHECK; + return value(THIS->at(row.as_i(), column.as_i()) = to<float>(val)); +} + +static +VALUE get_at(VALUE self, VALUE row, VALUE column) +{ + CHECK; return value(THIS->at(row.as_i(), column.as_i())); } +static +VALUE compare(VALUE self, VALUE other) +{ + CHECK; + const Rays::Matrix& a = *THIS; + const Rays::Matrix& b = to<const Rays::Matrix&>(other); + for (int i = 0; i < Rays::Matrix::NELEM; ++i) + { + if (a[i] == b[i]) continue; + return value(a[i] < b[i] ? -1 : +1); + } + return value(0); +} + +static +VALUE inspect(VALUE self) +{ + CHECK; + return value(Xot::stringf("#<Rays::Matrix %s>", THIS->inspect().c_str())); +} + +static +VALUE s_translate(VALUE self) +{ + return translate(argc, argv, value(Rays::Matrix())); +} + +static +VALUE s_scale(VALUE self) +{ + return scale(argc, argv, value(Rays::Matrix())); +} + +static +VALUE s_rotate(VALUE self) +{ + return rotate(argc, argv, value(Rays::Matrix())); +} + + static Class cMatrix; void Init_matrix () { @@ -100,12 +199,70 @@ cMatrix = rb_define_class_under(mRays, "Matrix", rb_cObject); rb_define_alloc_func(cMatrix, alloc); rb_define_private_method(cMatrix, "initialize", RUBY_METHOD_FUNC(initialize), -1); rb_define_private_method(cMatrix, "initialize_copy", RUBY_METHOD_FUNC(initialize_copy), 1); - rb_define_method(cMatrix, "set", RUBY_METHOD_FUNC(set), -1); - rb_define_method(cMatrix, "at", RUBY_METHOD_FUNC(at), 2); + rb_define_method(cMatrix, "reset", RUBY_METHOD_FUNC(reset), -1); + rb_define_method(cMatrix, "translate", RUBY_METHOD_FUNC(translate), -1); + rb_define_method(cMatrix, "scale", RUBY_METHOD_FUNC(scale), -1); + rb_define_method(cMatrix, "rotate", RUBY_METHOD_FUNC(rotate), -1); + rb_define_method(cMatrix, "to_a", RUBY_METHOD_FUNC(to_a), 0); + cMatrix.define_method("*", mult); + cMatrix.define_method("[]=", set_at); + cMatrix.define_method("[]", get_at); + cMatrix.define_method("<=>", compare); + rb_define_method(cMatrix, "inspect", RUBY_METHOD_FUNC(inspect), 0); + + rb_define_singleton_method(cMatrix, "translate", RUBY_METHOD_FUNC(s_translate), -1); + rb_define_singleton_method(cMatrix, "scale", RUBY_METHOD_FUNC(s_scale), -1); + rb_define_singleton_method(cMatrix, "rotate", RUBY_METHOD_FUNC(s_rotate), -1); } + + +namespace Rucy +{ + + + template <> Rays::Matrix + value_to<Rays::Matrix> (int argc, const Value* argv, bool convert) + { + if (argc == 1 && argv->is_array()) + { + argc = argv->size(); + argv = argv->as_array(); + } + + assert(argc == 0 || (argc > 0 && argv)); + + if (convert) + { + if (argc == 0) + return Rays::Matrix(); + else if (argv->is_num()) + { + switch (argc) + { + #define V(i) argv[i].as_f(true) + case 1: return Rays::Matrix(V(0)); + case 16: return Rays::Matrix( + V(0), V(1), V(2), V(3), + V(4), V(5), V(6), V(7), + V(8), V(9), V(10), V(11), + V(12), V(13), V(14), V(15)); + #undef V + default: argument_error(__FILE__, __LINE__); + } + } + } + + if (argc != 1) + argument_error(__FILE__, __LINE__); + + return value_to<Rays::Matrix&>(*argv, convert); + } + + +}// Rucy namespace Rays {