Hi !
I use rbSFML in my project. It works like a charm but I can't figure out how to get VertexArray to work properly.
My code :
require 'sfml'
include SFML
class MainWindow
def initialize(width, height)
@window = RenderWindow.new([width, height], "VertexArray")
@vertices = VertexArray.new(Triangles, 3)
@vertices[0].position = [100, 100]
@vertices[1].position = [200, 100]
@vertices[2].position = [200, 200]
@vertices[0].color = Color::Red
@vertices[1].color = Color::Green
@vertices[2].color = Color::Blue
update
end
def update
while @window.open?
@window.each_event do |event|
@window.close if event.type == Event::Closed
end
@window.clear
@window.draw(@vertices)
@window.display
end
end
end
MainWindow.new(640, 480)
But the triangle isn't drawn :/
I've done some testing and it seems that "@vertices[id]" return a new Vertex so I can't modify the Vertex of VertexArray.
For example, if I do something like that :
@vertices = VertexArray.new(Triangles, 3)
vertex = @vertices[0]
vertex.position = [100, 100]
p @vertices[0].position == vertex.position #=> false
The vertex in the VertexArray doesn't have the new position.
The only way I've find to do what I want is to clear the VertexArray and fill it with new Vertex (by using the "append" function) each time I want to modify a Vertex.
I've tried with a ruby array instead of a VertexArray. Works well but it's pretty slow.
So how can I easily change the Vertex position/color/texture of a VertexArray ?
I use the latest version of rbSFML on github and SFML2.0.
Thanks in advance ;)
Ah this is something on my todo list I have to remember to fix.
The VertexArray returns a copy of the Vertex and not a reference. Getting it to return a reference won't be an easy task though.
You can do something like this:
vertex = SFML::Vertex.new
# do changes
array[0] = vertex
# do changes
array[1] = vertex
SFML::Vertex is a pure Ruby object itself, so it's really lightweight so this should not perform any performances issues for you.
Edit: Also #append is super fast actually. The vertex array in SFML is just a wrapper above a std::vector, so the size is cached and even if you clear the array the memory won't be free'd.
Thanks for the answer !
You can do something like this:
vertex = SFML::Vertex.new
# do changes
array[0] = vertex
# do changes
array[1] = vertex
But in this example, array is a "ruby array" ? Because I don't know how to do that with a VertexArray.
And I really can't use a ruby array in my project :
I draw a tilemap with 8x8 tiles on a window of 640x480, so 4800 quads.
This code with a VertexArray :
require 'sfml'
include SFML
class MainWindow
QUAD_SIZE = 8
def initialize(width, height)
@window = RenderWindow.new([width, height], "VertexArray")
@window.framerate_limit = 60
@vertices = VertexArray.new(Quads, 0)
for x in 0...@window.get_size.x/QUAD_SIZE
for y in 0...@window.get_size.y/QUAD_SIZE
color = [Color::Red, Color::Green, Color::Blue].sample
@vertices.append(Vertex.new([x*QUAD_SIZE, y*QUAD_SIZE], color))
@vertices.append(Vertex.new([(x+1)*QUAD_SIZE, y*QUAD_SIZE], color))
@vertices.append(Vertex.new([(x+1)*QUAD_SIZE, (y+1)*QUAD_SIZE], color))
@vertices.append(Vertex.new([x*QUAD_SIZE, (y+1)*QUAD_SIZE], color))
end
end
update
end
def update
while @window.open?
@window.each_event do |event|
@window.close if event.type == Event::Closed
end
@window.clear
@window.draw(@vertices)
@window.display
end
end
end
MainWindow.new(640, 480)
Run smoothly with stable 60FPS
But the same code with a ruby array instead of a VertexArray :
require 'sfml'
include SFML
class MainWindow
QUAD_SIZE = 8
def initialize(width, height)
@window = RenderWindow.new([width, height], "VertexArray")
@window.framerate_limit = 60
@vertices = Array.new
for x in 0...@window.get_size.x/QUAD_SIZE
for y in 0...@window.get_size.y/QUAD_SIZE
color = [Color::Red, Color::Green, Color::Blue].sample
@vertices.push(Vertex.new([x*QUAD_SIZE, y*QUAD_SIZE], color))
@vertices.push(Vertex.new([(x+1)*QUAD_SIZE, y*QUAD_SIZE], color))
@vertices.push(Vertex.new([(x+1)*QUAD_SIZE, (y+1)*QUAD_SIZE], color))
@vertices.push(Vertex.new([x*QUAD_SIZE, (y+1)*QUAD_SIZE], color))
end
end
update
end
def update
while @window.open?
@window.each_event do |event|
@window.close if event.type == Event::Closed
end
@window.clear
@window.draw(@vertices, Quads, RenderStates::Default)
@window.display
end
end
end
MainWindow.new(640, 480)
Give me around 20FPS.
+ I really need a way to modify a particular Vertex :
I have animated tiles, and it's pretty slow to clear the VertexArray, loop through all the 4800tiles, re-create each Vertex just to change the texture coordinates of one tile :/