Class: Ray::GL::Vertex
- Inherits:
-
Object
- Object
- Ray::GL::Vertex
- Includes:
- PP
- Defined in:
- lib/ray/gl/vertex.rb,
ext/gl_vertex.c
Defined Under Namespace
Classes: Instance
Constant Summary collapse
- TypeMap =
ray_gl_vertex_types
Class Method Summary collapse
- .default_for(type) ⇒ Object
- .define_layout(on, layout, vtype, instance = false) ⇒ Object
- .instance_size(vtype) ⇒ Object
- .layout ⇒ Object
-
.make(layout) ⇒ Object
Creates a new Vertex class with a custom layout.
- .make_type(types) ⇒ Object
- .offset_of(vtype, elem_id) ⇒ Object
- .size(vtype) ⇒ Object
Instance Method Summary collapse
Methods included from PP
Class Method Details
.default_for(type) ⇒ Object
117 118 119 120 121 122 123 124 125 |
# File 'lib/ray/gl/vertex.rb', line 117 def self.default_for(type) case type when :float, :int, :ubyte then 0 when :bool then true when :vector2 then Ray::Vector2[0, 0] when :vector3 then Ray::Vector3[0, 0, 0] when :color then Ray::Color.white end end |
.define_layout(on, layout, vtype, instance = false) ⇒ Object
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/ray/gl/vertex.rb', line 127 def self.define_layout(on, layout, vtype, instance = false) argument_layout = layout.reject do |_, _, _, per_instance| per_instance ^ instance end on.class_eval do define_method :initialize do |*args| if args.size > layout.size msg = "wrong number of arguments: #{args.size} for" << " #{layout.size}" raise ArgumentError, msg end argument_layout.each_with_index do |(attr, _, type, _), i| send("#{attr}=", args[i] || Vertex.default_for(type)) end end layout.each_with_index do |(attr, _, type, per_instance), i| next if per_instance ^ instance offset = Vertex.offset_of(vtype, i) # Faster than define_method. module_eval(<<-eom, __FILE__, __LINE__) def #{attr} element(#{offset}, #{type.inspect}) end def #{attr}=(val) set_element(#{offset}, #{type.inspect}, val) end eom alias_method "#{attr}?", attr if type == :bool end end end |
.instance_size(vtype) ⇒ Object
128 129 130 131 132 |
# File 'ext/gl_vertex.c', line 128
static
VALUE ray_gl_vertex_instance_size(VALUE self, VALUE vtype) {
say_vertex_type *type = say_get_vertex_type(NUM2ULONG(vtype));
return INT2FIX(say_vertex_type_get_instance_size(type));
}
|
.layout ⇒ Object
113 114 115 |
# File 'lib/ray/gl/vertex.rb', line 113 def self.layout @vertex_type_layout end |
.make(layout) ⇒ Object
Creates a new Vertex class with a custom layout. Layout is an array of arrays, where each row contains 3 or 4 elements:
-
Attribute name in Ruby
-
Attribute name in GLSL shaders
-
Attribute type, one of the following symbols: float, int, ubyte, bool, color, vector2, vector3.
-
Whether the attribute is only accessibel on a per-instance basis (as opposed to per-vertex, which is the default)
Getters and setters are created for all of the attributes.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/ray/gl/vertex.rb', line 67 def self.make(layout) layout.each do |_, _, type, _| unless TypeMap.has_key? type raise ArgumentError, "unknown type in a vertex: #{type.inspect}" end end vtype = make_type layout.map { |_, *rest| rest } @vertex_classes[vtype] = Class.new self do # Be *very* careful with those values. @vertex_type_id = vtype @vertex_type_size = Vertex.size(vtype) @vertex_type_layout = layout if layout.any? { |_, _, _, per_instance| per_instance } const_set :Instance, Class.new(Ray::GL::Vertex::Instance) { @vertex_instance_type_id = vtype @vertex_instance_size = Vertex.instance_size(vtype) @vertex_instance_layout = layout class << self undef instance_classes end Vertex.define_layout self, layout, vtype, true } end class << self undef make undef make_type undef size undef offset_of end Vertex.define_layout self, layout, vtype, false end if @vertex_classes[vtype].const_defined? :Instance Instance.instance_classes[vtype] = @vertex_classes[vtype]::Instance end @vertex_classes[vtype] end |
.make_type(types) ⇒ Object
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'ext/gl_vertex.c', line 87
static
VALUE ray_gl_vertex_make_type(VALUE self, VALUE types) {
size_t size = RARRAY_LEN(types);
if (size == 0) {
rb_raise(rb_eArgError, "can't create empty vertex type");
}
size_t vtype_id = say_vertex_type_make_new();
say_vertex_type *vtype = say_get_vertex_type(vtype_id);
for (size_t i = 0; i < size; i++) {
VALUE element = RAY_ARRAY_AT(types, i);
VALUE name = RAY_ARRAY_AT(element, 0);
VALUE type = RAY_ARRAY_AT(element, 1);
VALUE per_instance = RAY_ARRAY_AT(element, 2);
char *c_name = say_strdup(StringValuePtr(name));
say_vertex_elem_type c_type = NUM2INT(rb_hash_aref(ray_gl_vertex_types,
type));
say_vertex_elem c_elem = {c_type, c_name, RTEST(per_instance)};
say_vertex_type_push(vtype, c_elem);
}
return INT2FIX(vtype_id);
}
|
.offset_of(vtype, elem_id) ⇒ Object
116 117 118 119 120 |
# File 'ext/gl_vertex.c', line 116
static
VALUE ray_gl_vertex_offset_of(VALUE self, VALUE vtype, VALUE elem_id) {
say_vertex_type *type = say_get_vertex_type(NUM2ULONG(vtype));
return INT2FIX(say_vertex_type_get_offset(type, NUM2INT(elem_id)));
}
|
.size(vtype) ⇒ Object
122 123 124 125 126 |
# File 'ext/gl_vertex.c', line 122
static
VALUE ray_gl_vertex_size(VALUE self, VALUE vtype) {
say_vertex_type *type = say_get_vertex_type(NUM2ULONG(vtype));
return INT2FIX(say_vertex_type_get_size(type));
}
|
Instance Method Details
#pretty_print(q) ⇒ Object
175 176 177 178 179 180 181 182 |
# File 'lib/ray/gl/vertex.rb', line 175 def pretty_print(q) attr = [] self.class.layout.each do |key, _, _, per_instance| attr << key unless per_instance end pretty_print_attributes q, attr end |
#to_s ⇒ Object
166 167 168 169 170 171 172 173 |
# File 'lib/ray/gl/vertex.rb', line 166 def to_s pairs = [] self.class.layout.each do |key, _, _, per_instance| pairs << "#{key}=#{send(key)}" unless per_instance end "#<#{self.class} #{pairs.join " "}>" end |