Page 1 of 1

Right way to draw to screen?

Posted: Sun Feb 17, 2013 1:17 am
by nate
[EDIT: A week after posting this, I realized the answer, and feel compelled to share in case anybody ever wonders the same thing I wondered. The correct way to draw a pixel is to use drawQuad-- you can keep track of your glScale() and scale your quadrant appropriately, if you really, really need 1 pixel. For my particular problem, the right answer is not to draw lines with end points determined by trig functions, but to glTranslate to my center point, then glRotate to an appropriate angle, drawing a very thin quad from -0.5*length, radius to 0.5*length, radius+width. Do this through your full 2pi and you get your circle. Note that my original method gives a polygon contained in a circle, and the method in this edit gives a polygon that contains a circle, but you can tweak your radius to make these the same thing.]


I've been experimenting with drawing to the screen lately-- have found a way to do it, but I doubt it's The Right Way. Looking for feedback-- "yeah, that's good enough," "no, you should do it this way," etc.

Here's what I got:

in mod/class/uiset/minimalist.lua/_M:displayResources:

Code: Select all

		local drawLine = function (xStart, yStart, xEnd, yEnd, dotDensity, color, shader)
		--draws a line of a certain dot density
			local x, y = xStart, yStart
			local length = math.sqrt((x-xEnd)^2+(y-yEnd)^2)
			local step = 0
			local xSlope, ySlope = (xEnd - xStart)/length, (yEnd -yStart)/length
			while step < length do
				shat[1]:toScreenPrecise(x, y, 1/dotDensity, 1/dotDensity, 0, 1, 0, 1, color[1], color[2], color[3], 1)
				step = step + 1/dotDensity
				x = x+xSlope
				y = y+ySlope
			end
		end

		local fixAngles = function (angle)
			while angle >= 2*math.pi do
				angle = angle - 2*math.pi
			end
			while angle < 0 do
				angle = angle + 2*math.pi
			end
			return angle
		end		
		
		local polarToCartesian = function (angle, radius)
			return radius*math.cos(fixAngles(angle)), radius*math.sin(fixAngles(angle))
		end
		
		local drawArc = function (xCenter, yCenter, radius, angleStart, angleEnd, numCorners, dotDensity, color, shader)
		--draws an arc centered on, of radius, starting at angle, ending at angle, represented by a segment of a polygon of a certain number of corners,of certain density and color;
                --angle 0 is East, angle pi/2 is South
			if numCorners < 3 then return nil end
			local start, stop = fixAngles(angleStart), angleEnd
			if stop <= start then stop = stop + 2*math.pi end
			local corners = math.ceil(numCorners*(stop-start)/(2*math.pi))
			--this is the number of actual lines our arc will be composed of, whereas numCorners is the number of corners if the arc were to describe an entire circle
			for count = 1, corners do
				local angleNext = start+(2*math.pi/numCorners)
				if angleNext > stop then angleNext = stop end
				local xStart, yStart = polarToCartesian(start, radius)
				local xStop, yStop = polarToCartesian(angleNext, radius)
				drawLine(xStart+xCenter, yStart+yCenter, xStop+xCenter, yStop+yCenter, dotDensity, color, shader)
				start = angleNext
			end
			return true
		end		

--test my function
		drawArc(160, 160, 40, 0, math.pi, 12, 1, hate_c)
Basically what I'm doing is using drawing a texture to a single pixel in lieu of drawing directly to that pixel. DrawArc should demonstrate why I can't just rescale the texture to do this-- I want to make curved lines, of various radii and angles, to represent some in-game stats. (With rotation and small enough pie slices, I could approximate this with textures, but that seems clunky.)

Not sure if it's a big deal from a performance standpoint, not sure if there are some better functions I can access that I just haven't noticed.