Interface: primitives

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
rude
Administrator
Posts: 1051
Joined: Mon Feb 04, 2008 3:58 pm
Location: Oslo, Norway

Interface: primitives

Post by rude » Thu Mar 06, 2008 6:00 pm

The primitives interface is horrible, as alxs pointed out. I believe that may be my fault, but here's a suggested improvement:

Code: Select all

love.graphics:line(x1, y1, x2, y2) -- Draw line. 
love.graphics:line(x1, y1, x2, y2, w) -- Draw line with line width.
love.graphics:line(x1, y1, x2, y2, x3, y3) -- Draw triangle.
love.graphics:line(x1, y1, x2, y2, x3, y3, w) -- Draw triangle with line width.
love.graphics:line(x1, y1, x2, y2, x3, y3, x4, y4) -- Draw quad.
love.graphics:line(x1, y1, x2, y2, x3, y3, x4, y4, w) -- Draw quad with line width.
love.graphics:circle(x, y, r) -- Draw circle.
love.graphics:circle(x, y, r, w) -- Draw circle with line width.
love.graphics:fill(x1, y1, x2, y2, x3, y3) -- Fill triangle.
love.graphics:fill(x1, y1, x2, y2, x3, y3, x4, y4) -- Fill quad.
love.graphics:fill(x, y, r) -- Fill circle.

User avatar
mikulka
Prole
Posts: 19
Joined: Thu Feb 21, 2008 10:43 pm
Location: Estonia

Re: Interface: primitives

Post by mikulka » Thu Mar 06, 2008 7:03 pm

It would be confusing if "love.graphics:line" draws triangles, quads, pentagons, ...
Maybe love.graphics:polygon, love.graphics:shape or something else would be better?

User avatar
rude
Administrator
Posts: 1051
Joined: Mon Feb 04, 2008 3:58 pm
Location: Oslo, Norway

Re: Interface: primitives

Post by rude » Thu Mar 06, 2008 7:08 pm

Maybe! We shoud at least try to keep it as simple as possible. We may also consider:

Code: Select all

love.graphics:triangle(love.fill, x1, y1, x2, y2, x3, y3)
love.graphics:circle(love.fill, x, y, r)
love.graphics:circle(love.outline, x, y, r)
etc
Or just keep what we have, but remove position:

Code: Select all

love.graphics:drawTriangle(x1, y1, x2, y2, x3, y3)
love.graphics:fillTriangle(x1, y1, x2, y2, x3, y3)
etc

User avatar
Merkoth
Party member
Posts: 186
Joined: Mon Feb 04, 2008 11:43 pm
Location: Buenos Aires, Argentina

Re: Interface: primitives

Post by Merkoth » Thu Mar 06, 2008 10:55 pm

love.graphics:shape() sounds good and I like the love.fill / love.outline idea too. I don't like and all-around line method :P

User avatar
ivan
Party member
Posts: 1530
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Interface: primitives

Post by ivan » Fri Mar 07, 2008 1:57 pm

Hey what's up rude? :) I'm the dude from http://2dengine.com/

Anyways, we did quite a bit of research on drawing interfaces and there seem to be 2 main styles of drawing primitives.
One is the OO style where you create "brush" and "pen" objects and you can assign them to the canvas that you're using. This is how they do it in the Windows GDI. The problem with Win GDI is that most of their drawing functions only accept arrays of points which complicates things quite a bit. To get around this issue, you could have helper "shape" objects such as rectangle, circle, ellipse, polygon, curve, etc... So it would work as follows:

Code: Select all

rect = love.graphics:new_rectangle ( -50, -50, 50, 50 )\
love.graphics:outline_shape ( rect )
love.graphics.brush:set_color ( 0, 255, 0 )
love.graphics.pen:set_width ( 5 )
love.graphics.pen:set_color ( 255, 255, 0 )
x = 100, y = 100, rotation = 45, scale = 1.0
love.graphics:draw_shape ( rect, x, y, rotation, scale )
You get the idea, you basically have a bunch of helper objects

Another approach to drawing is the C approach (that's what we did). We basically ripped off Cairo/Flash where you do a series of "move_to" and "line_to" commands and at the end you either "fill" or "stroke"

Code: Select all

love.graphics:move_to ( -50, -50 )
love.graphics:line_to ( -50, 50 )
love.graphics:line_to ( 50, 50 )
love.graphics:line_to ( 50, -50 )
love.graphics:line_to ( -50, -50 )
love.graphics:fill ( 255, 255, 0 )

User avatar
Sardtok
Party member
Posts: 108
Joined: Thu Feb 21, 2008 2:37 pm
Location: Norway/Norge/諾威/挪威 (Yes, I'm teh back!)
Contact:

Re: Interface: primitives

Post by Sardtok » Fri Mar 07, 2008 2:25 pm

The Flash approach reminds me of OpenGL, where you just continue to add vectors, and depending on your drawing mode things get drawn differently.
Lines, linesets, triangles, trianglestrips, quads, quadstrips, and there's another one for lines, to automatically close the shape when you run glEnd.
You are using GL for rendering right?
So an approach that is similar to GL should work well.
Possibly, define draw functions depending on what is going to be drawn, then use a glBegin for each function.
So, love.graphics.drawLine(x,y, x2, y2), or possibly taking arguments for the shading of the line as well, like drawLine(x,y,color,x2,y2,color2).
Also, if you want to draw multiple, non-connected lines, or lineSets(polygons), I guess you'd have to take some kind of array.
Take off every Zigg for great rapist.
Now, outgay that!

User avatar
ivan
Party member
Posts: 1530
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Interface: primitives

Post by ivan » Fri Mar 07, 2008 3:49 pm

Sardtok wrote:The Flash approach reminds me of OpenGL, where you just continue to add vectors, and depending on your drawing mode things get drawn differently.
Yeah, I think this is called a "state" machine or whatever, pretty similar to OpenGL.
Sardtok wrote:You are using GL for rendering right?
We have plugins for both DirectX and OpenGL. It's overkill in our case, although having different plugins helped the design a little bit. It helped in defining wehere the abstract layer of the framework ends and where the platform-dependent code begins.
Sardtok wrote:So an approach that is similar to GL should work well.
I have to mention that there are certain limitations if you plan to do everything in C style with a single global "graphics" object. For example, this would force you to do the z-ordering manually, in Lua. This is a pain in the ass, but necessary especially for transparent objects.

User avatar
rude
Administrator
Posts: 1051
Joined: Mon Feb 04, 2008 3:58 pm
Location: Oslo, Norway

Re: Interface: primitives

Post by rude » Fri Mar 07, 2008 6:18 pm

ivan wrote:Hey what's up rude? :) I'm the dude from http://2dengine.com/
Hey Ivan, nice seeing you here ^.^!

Ooh, I definitely like the Cairo/Flash way ... but Mike has the final word (tm) in this case. He's slightly out of commission these days, but he'll be back soon enough. (To spread his LÖVE onto us all, etc etc).
ivan wrote:z-ordering manually
We decided to just do it manually (in Lua) for now. Most of the graphics need transparency anyway.

May I ask you how you implemented "batch rendering"? I've noticed that XNA also uses something like this. Is it a fancy name for queuing up sprites in a native container and then sending everything to the GPU?

User avatar
mike
Administrator
Posts: 364
Joined: Mon Feb 04, 2008 5:24 pm

Re: Interface: primitives

Post by mike » Fri Mar 07, 2008 11:20 pm

rude wrote:...but Mike has the final word (tm) in this case...
Alright, I'll take the blame for this.. I wanted simpler functions to begin with rude, remember that? Simpler but not as useful, etc so I went with the idea that was eventually hated. Anyway onto what I think:

First of: Hello ivan. I don't know who you are but everyone is welcome here. I do believe that the first suggestion, using helper objects just seems too confusing:

Code: Select all

rect = love.graphics:new_rectangle ( -50, -50, 50, 50 )\
love.graphics:outline_shape ( rect )
love.graphics.brush:set_color ( 0, 255, 0 )
love.graphics.pen:set_width ( 5 )
love.graphics.pen:set_color ( 255, 255, 0 )
x = 100, y = 100, rotation = 45, scale = 1.0
love.graphics:draw_shape ( rect, x, y, rotation, scale )
In my head this is an unnecessary amount of clutter just for a rectangle. What I wanted was a simpler way to do it where you create a shape (which has a position, rotation, size, etc):

Code: Select all

rect = love.objects:newRectangle(100,100,20,20) -- x, y, width, height
rect:rotate(45) -- degrees
Which would/could be used in collision detection as well as being drawn by the draw function:

Code: Select all

love.graphics:draw(rect, love.fill)
This may oversaturate our SWIG with draw functions (rude explained what he had seen in one legendary night of clarity... the fields of if statements extending endlessly into the horizon) and we're not really sure how we are going to handle collision detection yet so we're going to have to wait for fancy things.

Code: Select all

love.graphics:move_to ( -50, -50 )
love.graphics:line_to ( -50, 50 )
love.graphics:line_to ( 50, 50 )
love.graphics:line_to ( 50, -50 )
love.graphics:line_to ( -50, -50 )
love.graphics:fill ( 255, 255, 0 )
This confuses and infuriates me!
Alright, it takes about 10 seconds of thinking to deduct yourself to what is going on, but as much as a logical system I want LÖVE to be an aesthetically logical system, where you don't need to think. I am not going to say more about our target demographic... *cough* :roll:

HOWEVER, the truth came forth in the words of my love mate:

Code: Select all

love.graphics:triangle(love.fill, x1, y1, x2, y2, x3, y3)
love.graphics:circle(love.fill, x, y, r)
love.graphics:circle(love.outline, x, y, r)
etc
This seems very pretty and understandable (as well as useful), despite you having to do the rotational mathematics yourself. I do believe that they could use a "draw" in front of each shape to be completely logical about what's going on, but I think that this could be our choice. Remove the x,y positions and have love.fill/love.outline as parameters.


Mike has spoken


(If you disagree, feel free to say so.. I don't actually have the final word despite what mr."let's avoid people talking to me about this" says)
Now posting IN STEREO (where available)

User avatar
ivan
Party member
Posts: 1530
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Interface: primitives

Post by ivan » Sat Mar 08, 2008 12:37 am

May I ask you how you implemented "batch rendering"?
Nah, we haven't done batching yet, but so far, rendering is one of the fastest components in our system so optimizing it is not really a concern for now. I doubt that batching will have significant results in 2D (since you're not dealing with huge 3D meshes)
I've noticed that XNA also uses something like this. Is it a fancy name for queuing up sprites in a native container and then sending everything to the GPU?
Yeah, that's how it's supposed to work in theory. The goal is to keep the transfers between system memory and video ram as few as possible. Since the video card usually can't store all of the textures/vertices in its own ram it moves the less used resouces to system memory. I've read that the ZFX Engine renderer iteratates its queue forward on even frames and backwards on odd frames in order to make use of the resources that were transfered to the video card from the previous frame. There are many similar optimizations that you can do, but I don't think that's as important in 2D.
love.graphics:triangle(love.fill, x1, y1, x2, y2, x3, y3)
love.graphics:circle(love.fill, x, y, r)
love.graphics:circle(love.outline, x, y, r)
etc
This seems very pretty and understandable (as well as useful), despite you having to do the rotational mathematics yourself. I do believe that they could use a "draw" in front of each shape to be completely logical about what's going on, but I think that this could be our choice. Remove the x,y positions and have love.fill/love.outline as parameters
Hey Mike. :)
And what about rendering filled polygons/polylines - how would that work? Based on the above syntax, and without helper objects you have to pass a Lua table as the parameter of a function.

Post Reply

Who is online

Users browsing this forum: No registered users and 10 guests