Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Can't modify Vertex of a VertexArray  (Read 7954 times)

0 Members and 1 Guest are viewing this topic.

Rowad

  • Newbie
  • *
  • Posts: 4
    • View Profile
Can't modify Vertex of a VertexArray
« on: June 29, 2013, 12:35:33 am »
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 ;)

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Re: Can't modify Vertex of a VertexArray
« Reply #1 on: June 29, 2013, 03:24:10 pm »
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.
« Last Edit: June 29, 2013, 04:31:51 pm by Groogy »
Developer and Maker of rbSFML and Programmer at Paradox Development Studio

Rowad

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: Can't modify Vertex of a VertexArray
« Reply #2 on: June 29, 2013, 07:30:44 pm »
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 :/

Groogy

  • Hero Member
  • *****
  • Posts: 1469
    • MSN Messenger - groogy@groogy.se
    • View Profile
    • http://www.groogy.se
    • Email
Re: Can't modify Vertex of a VertexArray
« Reply #3 on: June 29, 2013, 08:55:29 pm »
Aight, I will put a []= operator in the class tomorrow.

I want references to the individual vertices, but that would mean that I have to wrap the sf::Vertex class, they have to be dynamically allocated, and I have to manage the references between them and other classes(like sf::VertexArray). As it is now Ruby does it for me since the object is a light weight ruby object that is just there temporarily. The Ruby GC is quite good at reusing small objects with small life times.
Developer and Maker of rbSFML and Programmer at Paradox Development Studio