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

Author Topic: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.  (Read 23485 times)

0 Members and 1 Guest are viewing this topic.

Anteara

  • Newbie
  • *
  • Posts: 40
    • View Profile
    • Email
Hi all, I'm in the process of converting my game engine from c++ to c#, mainly because I want to use WinForms, I tried using QT in c++ but it was much harder, also because I'm currently debating whether or not I should learn c++ or C# for Object Oriented Programming next semester (thoughts? :P).

Anyway, this line here:

sf::Vertex* quad = &m_vertices[(i + j * width) * 4];
is giving me trouble.

If i make it simply a vertex, I can't do quad[0], quad[1], etc, as per:

                quad[0].Position = new Vector2f(i * tileSize.X, j * tileSize.Y);
                quad[1].Position = new Vector2f((i + 1) * tileSize.X, j * tileSize.Y);
                quad[2].Position = new Vector2f((i + 1) * tileSize.X, (j + 1) * tileSize.Y);
                quad[3].Position = new Vector2f(i * tileSize.X, (j + 1) * tileSize.Y);

Note that I've put it in C# syntax, the c++ syntax is basically the same.

If I make it a vertex[], then that doesn't work either because it tries to convert from Vertex to Vertex[];

 
Vertex[] quad = m_vertices[(i + j * width) * 4];

I have no idea how I can do this. Since safe c# can't use pointers or reference, I don't know how I can get this to work.

Can someone please show how I can get this specific part of code to work?

Thanks.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #1 on: July 14, 2013, 08:15:54 pm »
Use indices instead of pointers.

uint index = (i + j * width) * 4;
m_vertices[index + 0].Position = ...;
m_vertices[index + 1].Position = ...;
m_vertices[index + 2].Position = ...;
m_vertices[index + 3].Position = ...;
Laurent Gomila - SFML developer

Anteara

  • Newbie
  • *
  • Posts: 40
    • View Profile
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #2 on: July 15, 2013, 02:27:23 am »
Thanks, I tried that, however now I'm getting this error:
Error   1       Cannot modify the return value of 'SFML.Graphics.VertexArray.this[uint]' because it is not a variable   C:\Users\Kevin Mallinson\Documents\Visual Studio 2012\Projects\MapMakerDotNet\MapMakerDotNet\TileMap.cs 92
 

This is how I implemented it:

m_vertices[index + 0].Position = new Vector2f(i * tileSize.X, j * tileSize.Y);
m_vertices[index + 1].Position = new Vector2f((i + 1) * tileSize.X, j * tileSize.Y);
m_vertices[index + 2].Position = new Vector2f((i + 1) * tileSize.X, (j + 1) * tileSize.Y);
m_vertices[index + 3].Position = new Vector2f(i * tileSize.X, (j + 1) * tileSize.Y);

Do you know why that's happening? It's strange...
« Last Edit: July 15, 2013, 02:30:59 am by Anteara »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #3 on: July 15, 2013, 08:02:19 am »
Ah, yes. Vertex is a structure, operator [] returns a copy. You have to overwrite the whole vertex (m_vertices[a] = new Vertex(...)).
Laurent Gomila - SFML developer

Anteara

  • Newbie
  • *
  • Posts: 40
    • View Profile
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #4 on: July 15, 2013, 12:51:03 pm »
Thanks, it compiles fine now:

m_vertices[index + 0] = new Vertex(new Vector2f(i * tileSize.X, j * tileSize.Y), new Vector2f(tu * tileSize.X, tv * tileSize.Y));
m_vertices[index + 1] = new Vertex(new Vector2f((i + 1) * tileSize.X, j * tileSize.Y), new Vector2f((tu + 1) * tileSize.X, tv * tileSize.Y));
m_vertices[index + 2] = new Vertex(new Vector2f((i + 1) * tileSize.X, (j + 1) * tileSize.Y), new Vector2f((tu + 1) * tileSize.X, (tv + 1) * tileSize.Y));
m_vertices[index + 3] = new Vertex(new Vector2f(i * tileSize.X, (j + 1) * tileSize.Y), new Vector2f(tu * tileSize.X, (tv + 1) * tileSize.Y));
 

That is how I've implemented it.
Also, one more thing: Since I'm basing my class off the vertex array tutorial, which inherets Drawable and Transformable, and i'm using c#, I can't inheret more than one class.

So I simply instantiated Transformable inside the class, so I can access the method to get the transform:

states.Transform *= TransformInstance.Transform;

Do you think that would work? Note that I can't test it right now since I'm making sure all the code compiles before linking it all up and whatnot :/.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #5 on: July 15, 2013, 01:17:35 pm »
Quote
Since I'm basing my class off the vertex array tutorial, which inherets Drawable and Transformable, and i'm using c#, I can't inheret more than one class.
Drawable is an interface, and in C# you can inherit as many interface as you want in addition to another base class. Look at SFML drawable classes, they all inherit both Drawable and Transformable. So there's no problem.
Laurent Gomila - SFML developer

Anteara

  • Newbie
  • *
  • Posts: 40
    • View Profile
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #6 on: July 15, 2013, 02:04:59 pm »
Ah, okay thanks :)

So i've successfully converted my program from c++ to c#. I've noticed that in c++ it uses 10% cpu, in c# it uses about 30%. That's something I'll have to look in to, perhaps I'm doing something wrong.

There's one thing I was slightly confused about:

The way that I can implement the Draw function from the Drawable interface is like this:
void Drawable.Draw(RenderTarget target, RenderStates states)

whereas in c++ i can do it like this:

virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const

Notice that in c++ i can pass the target by reference, but I can't do that in c#. I tried, but it says I'm not implementing the interface when I do it like this:

void Drawable.Draw(ref RenderTarget target, RenderStates states)

Couldn't this perhaps cause a slight inefficiency, if it has to pass by value and copy the target each time It's called? Or am I misinterpreting this?

Thanks! :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #7 on: July 15, 2013, 03:03:15 pm »
In C# all class instances are hidden pointers. You don't need to pass them by reference.
Laurent Gomila - SFML developer

Anteara

  • Newbie
  • *
  • Posts: 40
    • View Profile
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #8 on: July 15, 2013, 03:15:34 pm »
In C# all class instances are hidden pointers. You don't need to pass them by reference.

Ah, okay thanks.

Anteara

  • Newbie
  • *
  • Posts: 40
    • View Profile
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #9 on: July 16, 2013, 11:37:08 am »
Hi, sorry for bothering you again! >_< anyway, I did some profiling on my C# program (it uses 20% CPU, I have an i7) whereas my c++ version of the same program uses about 5-8% CPU.

I ran the visual studio profiler and according to that this is what is causing most of the cpu usage:

 m_vertices[index + 0] = new Vertex(new Vector2f(i * tileSize.X, j * tileSize.Y), new Vector2f(tu * tileSize.X, tv * tileSize.Y));
                    m_vertices[index + 1] = new Vertex(new Vector2f((i + 1) * tileSize.X, j * tileSize.Y), new Vector2f((tu + 1) * tileSize.X, tv * tileSize.Y));
                    m_vertices[index + 2] = new Vertex(new Vector2f((i + 1) * tileSize.X, (j + 1) * tileSize.Y), new Vector2f((tu + 1) * tileSize.X, (tv + 1) * tileSize.Y));
                    m_vertices[index + 3] = new Vertex(new Vector2f(i * tileSize.X, (j + 1) * tileSize.Y), new Vector2f(tu * tileSize.X, (tv + 1) * tileSize.Y));
 

I think I may know why, it's because I'm creating everything with new, as that's the only way I think it will work, instead of just editing the existing value.

Perhaps I'm being inefficient by calling this every main loop. I THINK I could use a conditional to call it only when the map is changed. In fact, I'll do that after I post this.

However, I was wondering if theres a more efficient way of doing what I've enclosed in the code tags, without using new to save cpu resources?

Thanks! :)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #10 on: July 16, 2013, 11:42:17 am »
Quote
However, I was wondering if theres a more efficient way of doing what I've enclosed in the code tags, without using new to save cpu resources?
With a VertexArray, no. But with your own storage (like a Vertex[]), yes, I think you would be able to modify vertices directly.
Laurent Gomila - SFML developer

Anteara

  • Newbie
  • *
  • Posts: 40
    • View Profile
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #11 on: July 16, 2013, 11:54:37 am »
Okay, thanks! :)
I'll try to implement that.
and p.s. i save about 5% CPU by only calling it when the map is updated, which is good.

Thanks :)

Anteara

  • Newbie
  • *
  • Posts: 40
    • View Profile
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #12 on: July 16, 2013, 12:23:26 pm »
Oh, one more question, if you don't mind. I'm sorry for asking so much questions, I just love using SFML and am a beginner still with it :)
p.s. Sorry for double posting, I'm not sure if editing would notify readers that there is a message unread(?).

I'm trying to get my memory usage down now, as It's using 60MB, which is quite high since my program is still small-ish.

I profiled the memory usage and it came up with this:

http://i.imgur.com/n12iB8s.png

I'm not sure why views are using a lot of memory, as I remember reading in the tutorial that they're lightweight. Since it says GetView is using the most memory, I'll show you the function that uses GetView:

        public int change_current_tile_temp(ref RenderWindow window, ref int tile)
        {
            Vector2f mouse = window.MapPixelToCoords(Mouse.GetPosition(window));

            float[] ViewSize = {window.GetView().Size.X, window.GetView().Size.Y};
            //std::cout << "Mouse X Versus View Size: " << mouse.x << " VS " << XYSIZE * TILE_SIZE << std::endl;

            if (mouse.X > ViewSize[0] - ViewSize[0] &&
                mouse.X < Constants.XYSIZE * Constants.TILE_SIZE &&
                mouse.Y < Constants.XYSIZE * Constants.TILE_SIZE &&
                mouse.Y > ViewSize[1] - ViewSize[1]
                && Mouse.IsButtonPressed(Mouse.Button.Left)
                )
            {
                int mouseX = (int)mouse.X / Constants.TILE_SIZE;
                int mouseY = (int)mouse.Y / Constants.TILE_SIZE;
                tile = mouseX + mouseY * Constants.XYSIZE;
                //std::cout << "pressed tile: " << tile << std::endl;
            }
            return tile;
        }

This is called once every tick of the main loop. It checks if the mouse is in the view window, and then if it is, and you pess the mouse down, it gets what tile you clicked, and returns it.

Do you know why this might be apparently using a lot of memory?

Thanks! :)

Edit: Oh, by the way, the reason I'm using an array to store the X and Y which may seem redundant is because I was checking if calling GetView two times per tick instead of four would make a difference.. It didn't make a difference unfortunately.
« Last Edit: July 16, 2013, 12:28:06 pm by Anteara »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #13 on: July 16, 2013, 12:50:55 pm »
Quote
Sorry for double posting, I'm not sure if editing would notify readers that there is a message unread(?)
Yes there's a notification. But anyway, editing or posting a new message leads to the same result (new message to read), so don't worry so much about that ;)

I don't think that views are directly causing half of your memory usage. I would say it's something different, which somehow shows up as "views" in your report.

Memory usage can be very high even if you're not doing anything in your program, this is generally caused by the graphics driver itself, which allocates and runs a lot of hidden stuff. You should first compare your own program with a minimal one (i.e. a window with a main loop). Maybe the memory usage of the minimal program will already be quite high.
Laurent Gomila - SFML developer

Anteara

  • Newbie
  • *
  • Posts: 40
    • View Profile
    • Email
Re: sf::Vertex* quad = &m_vertices[(i + j * width) * 4]; from C++ to C#.
« Reply #14 on: July 16, 2013, 01:52:37 pm »
Thanks for that tip, in a minimal example, rendering nothing, it just having a blank window open and refreshing it, it uses 40MB. So the memory of my program is about 20mb, i guess.

It thinks this is the function with the most allocated memory in the minimal example:

Functions Allocating Most Memory
Name    Bytes %
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(native int,int32,int32)        43.04
 

I'm not really sure what that is, lol.

Anyway, in relation to the earlier posts of this thread, I tried using a Vertex[] instead of VertexArray. I can get it to render just fine when I use the new function to create the new vertex to display, however, if I don't use the new function, it just doesn't work for some reason.

In the code below,  the first set of code succeeding the commented section works, the next part doesn't work. In the second part I used the new function to create the Vector2f, so in the third example I got rid of the new function all together just to rule out that as a cause.

//WORKS

testVertexArray[index + 0] = new Vertex(new Vector2f(i * tileSize.X, j * tileSize.Y), new Vector2f(tu * tileSize.X, tv * tileSize.Y));
testVertexArray[index + 1] = new Vertex(new Vector2f((i + 1) * tileSize.X, j * tileSize.Y), new Vector2f((tu + 1) * tileSize.X, tv * tileSize.Y));
testVertexArray[index + 2] = new Vertex(new Vector2f((i + 1) * tileSize.X, (j + 1) * tileSize.Y), new Vector2f((tu + 1) * tileSize.X, (tv + 1) * tileSize.Y));
testVertexArray[index + 3] = new Vertex(new Vector2f(i * tileSize.X, (j + 1) * tileSize.Y), new Vector2f(tu * tileSize.X, (tv + 1) * tileSize.Y));

//DOESNT WORK

testVertexArray[index + 0].Position.X = i * tileSize.X;
testVertexArray[index + 0].Position.Y = j * tileSize.Y;

testVertexArray[index + 1].Position.X = (i + 1) * tileSize.X;
testVertexArray[index + 1].Position.Y = j * tileSize.Y;

testVertexArray[index + 2].Position.X = (i + 1) * tileSize.X;
testVertexArray[index + 2].Position.Y = (j + 1) * tileSize.Y;

testVertexArray[index + 3].Position.X = i * tileSize.X;
testVertexArray[index + 3].Position.Y = (j + 1) * tileSize.Y;

testVertexArray[index + 0].TexCoords.X = tu * tileSize.X;
testVertexArray[index + 0].TexCoords.Y = tv * tileSize.Y;

testVertexArray[index + 1].TexCoords.X = (tu + 1) * tileSize.X;
testVertexArray[index + 1].TexCoords.Y = tv * tileSize.Y;

testVertexArray[index + 2].TexCoords.X = (tu + 1) * tileSize.X;
testVertexArray[index + 2].TexCoords.Y = (tv + 1) * tileSize.Y;

testVertexArray[index + 3].TexCoords.X =tu * tileSize.X;
testVertexArray[index + 3].TexCoords.Y = (tv + 1) * tileSize.Y;

//DOESNT WORK

testVertexArray[index + 0].Position = new Vector2f(i * tileSize.X, j * tileSize.Y);
testVertexArray[index + 1].Position = new Vector2f((i + 1) * tileSize.X, j * tileSize.Y);
testVertexArray[index + 2].Position = new Vector2f((i + 1) * tileSize.X, (j + 1) * tileSize.Y);
testVertexArray[index + 3].Position = new Vector2f(i * tileSize.X, (j + 1) * tileSize.Y);

testVertexArray[index + 0].TexCoords = new Vector2f(tu * tileSize.X, tv * tileSize.Y);
testVertexArray[index + 1].TexCoords = new Vector2f((tu + 1) * tileSize.X, tv * tileSize.Y);
testVertexArray[index + 2].TexCoords = new Vector2f((tu + 1) * tileSize.X, (tv + 1) * tileSize.Y);
testVertexArray[index + 3].TexCoords = new Vector2f(tu * tileSize.X, (tv + 1) * tileSize.Y);

Sorry that it's quite lengthy, but it's essentially all the same thing, just rewritten. I'm not sure why this isn't working. Do you have any idea?

Thanks!