ENIGMA Forums

Outsourcing saves money => Issues Help Desk => Topic started by: TheExDeus on November 30, 2010, 02:02:19 PM

Title: Can't draw anything inside _begin _end
Post by: TheExDeus on November 30, 2010, 02:02:19 PM
While testing my curve functions I innially could not get why my curves drawed normally some times, but not others. I found out that a draw_circle was to blame, which I used to mark the points. When I start drawing a spline with draw_spline_begin() it just does:
Code: [Select]
    glPushAttrib(GL_CURRENT_BIT);
    glBegin(mode);
And when I draw a circle or any other shape in between it will get points on that circle, and thus mess up my curve. This is exactly the same problem with the already implemented draw_primitive functions. Try something like this and see for yourself:
Code: [Select]
draw_primitive_begin(pr_linestrip);
draw_vertex(10,10);
draw_vertex(100,50);
draw_circle(500,300,5,1);
draw_vertex(50,300);
draw_primitive_end();
In GM it does allow things like this. The way it does this is that the _end function is the one that draws it. So I guess this is how I need to do it too? I already save points in an array, so I guess its not a problem, but still. There is some DEPTHBUFFER code already done in primitive functions and in thous it does save points as well. So drawing it in _end would be the best bet I guess.

Also, if I have to save points + colors + alphas in an array, then should I use something like this:
http://www.fredosaurus.com/notes-cpp/newdelete/50dynamalloc.html
or just:
float pr_point_ar[MAXPOINTS][4];
MAXPOINTS could be changed, or just be a large number by default.
I don't want to do that dynamic deleting and allocation because I would need to do this for every point... Or I could alloc, for example, 64 points at a time, and when I run out I alloc another 64. This wouldn't waste much memory and should be faster, but then again its another if cycle.

Also, I guess I should post these as tickets in the tracker, but I might as well put it here:
draw_merge doesn't work. I wasted about 40min trying to figure out why I can't blend my curve smoothly, and it ends up that the function doesn't return the right values. For example, merge_color(c_red,c_white,1), will return c_red even thou it needs to return c_white. Either way, this is how I fixed it:
Code: [Select]
int merge_color(int c1,int c2,double amount)
{
amount = amount > 1 ? 1 : (amount < 0 ? 0 : amount);

    return
    (unsigned char)(fabs(__GETR(c1)+(__GETR(c2)-__GETR(c1))*amount))
    | (unsigned char)(fabs(__GETG(c1)+(__GETG(c2)-__GETG(c1))*amount))<<8
    | (unsigned char)(fabs(__GETB(c1)+(__GETB(c2)-__GETB(c1))*amount))<<16;
}
I think fabs can be removed somehow.

Also, draw_get_color() (or anything draw_get for that matter) returns nan all the time.. I have this code:
Code: [Select]
pr_point_ar[i][2] = (pr_curve_color1 == -1 ? draw_get_color() : merge_color(pr_curve_color1,pr_curve_color2,1/(pr_spline_points+1)))And it will return nan if pr_curve_color1 is -1 (so its calling merge_color). I just tested std::cout << merge_color(col1,col2,1) and got the same result. Couldn't find the reason thou... I looked in GScolors.cpp and everything seems fine.

edit: Anyway, as you can see this post started as a question, but by the second paragraph I realized how to fix this myself (by drawing in _end), so the first part can be ignored I guess.
Title: Re: Can't draw anything inside _begin _end
Post by: Josh @ Dreamland on November 30, 2010, 05:37:12 PM
Indeed, I chose not to use a custom vertex buffer to render primitives, and nested glBegin()s are invalid. I am unsure why you would be drawing a circle inside your primitive calls in the first place, but if you can make a case for it I'd be happy to use a dynamic array for a custom VBO (another 1980 GL spec that Intel refuses to support).

merge_color worked at one point, but serp found a more efficient way. He just never tests his efficient ways thoroughly. Notice the tabs everywhere. Not my trademark...
Title: Re: Can't draw anything inside _begin _end
Post by: TheExDeus on November 30, 2010, 05:45:44 PM
Quote
Indeed, I chose not to use a custom vertex buffer to render primitives, and nested glBegin()s are invalid. I am unsure why you would be drawing a circle inside your primitive calls in the first place, but if you can make a case for it I'd be happy to use a dynamic array for a custom VBO (another 1980 GL spec that Intel refuses to support).
Well I had code like this:
Code: [Select]
draw_spline_begin(pr_linestrip);
for (int i=0; i<points; i++){
    draw_spline_add_point_color(ar[i,0],ar[i,1],ar[i,2],ar[i,3]);
    draw_circle(ar[i,0],ar[i,1],5,1);
}
draw_spline_add_point(ar[points-1,0],ar[points-1,1]);
draw_spline_end();
So I draw a point and also draw a circle at that same point. I can, of course, make two "for cycles" for this, but that would be slower. Maybe not in this case (where point number is like 512 max), but in other cases where you draw more stuff together. Either way, how would dynamic arrays work? Is it the same as in the link I posted? Where you just create new array every time you need more space?
Title: Re: Can't draw anything inside _begin _end
Post by: Josh @ Dreamland on December 01, 2010, 01:57:19 PM
Essentially. It would require a less-than check every primitive, which is what I consider to be a waste of time. I may offer a second set of primitive functions that have no such time consumers (and smaller names. I'm thinking just draw_begin(), draw_end()).
Title: Re: Can't draw anything inside _begin _end
Post by: TheExDeus on December 01, 2010, 03:05:36 PM
Also, when you make _end functions actually draw the primitive you can have things like "draw_add_vertex" inside, for example, a mouse click event and then just draw with _end in the draw event. So this allows adding points without using any arrays. I also thought that would increase speed, as every add_vertex function assigns arrays its values and increments, but my test showed that fps gain is minimal, or none at all.
Also, its allows drawing with _end, then have some d3d transform function in the middle, and draw again with _end thus making some interesting effects. GM allows this, as GM also draws only in _end.

Also, room_goto() doesn't work. I will test it some more and if its really not my fault, then I will post a ticket.
Title: Re: Can't draw anything inside _begin _end
Post by: RetroX on December 03, 2010, 09:44:16 PM
Code: [Select]
draw_spline_begin(pr_linestrip);
for (int i=0; i<points; i++){
    draw_spline_add_point_color(ar[i,0],ar[i,1],ar[i,2],ar[i,3]);
    draw_circle(ar[i,0],ar[i,1],5,1);
}
The one thing that I could see for this would be implementing a draw_add_circle function, which is essentially draw_circle without the glBegin and glEnd; that way, it draws the points in the current primitive  It would probably specify a starting angle for which point to draw first, but I can see it as being useful for speed in minor cases such as this.

You could draw the point, draw the circle starting with the angle on the line, go back to the point, then go to the next point, and repeat.
Title: Re: Can't draw anything inside _begin _end
Post by: Josh @ Dreamland on December 04, 2010, 04:56:21 AM
Well, since the draw event only clears it every time, you'd still have to keep your own array.
The speed will actually decrease from keeping your own array. It is much more efficient to outsource point management to the GPU. Not to mention the number of function calls doubles by this method. At it's simplest, now we're keeping a nonstatic array, and the GPU is keeping a static one. The difference in the long run, though, is negligible; most of the work here is probably in drawing the primitive.
But yes, I see how drawing a circle around each vertex could be useful, so if you have not, I will probably preprocess the current primitive functions manually and rename them to draw_begin, draw_vertex2d() and draw_end(). Then our Game Maker equivalents can do their craziness.

Issue is, now I have to store texture and color data in the array, too.
Title: Re: Can't draw anything inside _begin _end
Post by: TheExDeus on December 04, 2010, 06:25:25 AM
RetroX: Wouldn't it connect the last point to the circle? And then connect the circles last point to the next one? Also, the circle will the draw with the currently selected mode, which cause problems (in my case it connected all of the points in the circle). I would be almost better to do something like glend and glbegin before and after the circle. Of course that could be slow thou. So drawing in _end is still the best thing I can come up with. Its also the best thing Mark could come up with. And this actually allows some neat effects like transforming before drawing. So you can add all points, then rotate it 45 degrees, scale 2 times and then draw.