Page 1 of 1
GL rotating ground quad
Posted: 21 Apr 2013, 15:19
by Cheesecan
I am pretty much awful at opengl so I'm asking for help. I tried googling it, but everyone has their own solution (none of which seem to work perfectly in spring - though quite close).
I have a textured ground quad consisting of a small 64 x 64 pixel texture drawn on the ground as a metal spot. I'd like to rotate this randomly 0 - 360 degrees to get some variety.
Code: Select all
function drawPatches()
local mSpots = WG.metalSpots
-- Set Matrix
gl.MatrixMode(GL.TEXTURE)
gl.PushMatrix()
gl.PolygonOffset(-25, -2)
gl.Culling(GL.BACK)
gl.DepthTest(true)
gl.Texture("maps/metal_high.png" )
gl.Color(1, 1, 1) -- fix color from other widgets
for i = 1, #mSpots do
gl.LoadIdentity()
gl.Translate(metalSpotWidth/2, metalSpotHeight/2, 0)
gl.Rotate( math.random(0, 360), 0, 1, 0)
gl.DrawGroundQuad( mSpots[i].x - metalSpotWidth/2, mSpots[i].z - metalSpotHeight/2, mSpots[i].x + metalSpotWidth/2, mSpots[i].z + metalSpotHeight/2, false, 0, 0, 1, 1)
gl.Translate(-metalSpotWidth/2, -metalSpotHeight/2, 0)
end
gl.Texture(false)
gl.DepthTest(false)
gl.Culling(false)
gl.PolygonOffset(false)
-- Restore Matrix
gl.PopMatrix()
gl.MatrixMode(GL.MODELVIEW)
end
But the result is that some quads are stretched out instead of rotated:

Re: GL rotating ground quad
Posted: 22 Apr 2013, 11:58
by knorke
I think it needs to be like
Translate
Rotate
Translate
Draw
you have
Translate
Rotate
Draw
Translate
I could not get that to work though, the texture was either stretching or rotating around wrong point. At one point got it to rotate around center but the texture was tiled and shifted by half its width. wtf.
This works:
Code: Select all
for i = 1, #mSpots do
gl.Translate(0.5, 0.5, 0)
gl.Rotate( r*i,0, 0,1)
gl.DrawGroundQuad( mSpots[i].x - metalSpotWidth/2, mSpots[i].z - metalSpotHeight/2, mSpots[i].x + metalSpotWidth/2, mSpots[i].z + metalSpotHeight/2, false, -0.5,-0.5, 0.5,0.5)
gl.Rotate( -r,0, 0,1)
gl.Translate(-0.5, -0.5, 0)
end
Instead of the "do reset rotate + translate backwards again to reset" one can use pop push thing:
Code: Select all
for i = 1, #mSpots do
gl.PushMatrix()
gl.Translate(0.5, 0.5, 0)
gl.Rotate( r*i,0, 0,1)
gl.DrawGroundQuad( mSpots[i].x - metalSpotWidth/2, mSpots[i].z - metalSpotHeight/2, mSpots[i].x + metalSpotWidth/2, mSpots[i].z + metalSpotHeight/2, false, -0.5,-0.5, 0.5,0.5)
gl.PopMatrix()
end
anyway it kinda seems to work:

Notice the orange piece in middle of circles, it is because the texture is repeated when rotating and I did not leave enough empty transparent space on the image. I am certain there is a way to make it non-repeating but Idk.
disclaimer: i am not openglpeopleperson
Re: GL rotating ground quad
Posted: 22 Apr 2013, 14:26
by zwzsg
Shouldn't you rotate around Y, instead of X?
Re: GL rotating ground quad
Posted: 22 Apr 2013, 20:22
by Cheesecan
Thanks knorke, you're a gem!
The whole function for future reference:
Code: Select all
function drawPatches()
local mSpots = WG.metalSpots
-- Switch to texture matrix mode
gl.MatrixMode(GL.TEXTURE)
gl.PolygonOffset(-25, -2)
gl.Culling(GL.BACK)
gl.DepthTest(true)
gl.Texture("maps/metal_high.png" )
gl.Color(1, 1, 1) -- fix color from other widgets
for i = 1, #mSpots do
local rot = math.random(0, 360)
gl.PushMatrix()
gl.Translate(0.5, 0.5, 0)
gl.Rotate( rot, 0, 0, 1)
gl.DrawGroundQuad( mSpots[i].x - metalSpotWidth/2, mSpots[i].z - metalSpotHeight/2, mSpots[i].x + metalSpotWidth/2, mSpots[i].z + metalSpotHeight/2, false, -0.5,-0.5, 0.5,0.5)
gl.PopMatrix()
end
gl.Texture(false)
gl.DepthTest(false)
gl.Culling(false)
gl.PolygonOffset(false)
-- Restore Modelview matrix
gl.MatrixMode(GL.MODELVIEW)
end
I also added canvas to the metal texture so it's 92x92 now, while metalSpotWidth & metalSpotHeight is still 64. This eliminated the mirrored repeat. Looks soo much better now!

Re: GL rotating ground quad
Posted: 22 Apr 2013, 21:51
by knorke
zwzsg wrote:Shouldn't you rotate around Y, instead of X?
i think yes, but some reason that just results in stretching like this:
local rot = math.random(0, 360)
doesnt that just result in very fast flickering metalspots? (different rotation everytime they are drawn)
You would want something like:
Code: Select all
--somewhere in init:
for i = 1, #mSpots do
mSpots[i].rot = math.random (0,360)
end
--in draw code:
gl.Rotate(mSpots[i].rot, 0, 0, 1)
Re: GL rotating ground quad
Posted: 22 Apr 2013, 23:19
by Cheesecan
They are stored in a displaylist for performance reasons - because of this the drawing will be the exact same in every frame.
Code: Select all
function widget:DrawWorldPreUnit()
local mode = Spring.GetMapDrawMode()
if(mode ~= "height") then
gl.CallList(displayList)
end
end
Re: GL rotating ground quad
Posted: 23 Apr 2013, 14:10
by BrainDamage
if you make a displaylist for all metal spots, then you should regenerate it when the ground surrounding a metal platter is deformed ( explosions, unit terraform, unit ground restore )
Re: GL rotating ground quad
Posted: 23 Apr 2013, 20:14
by Cheesecan
That's a good point. I looked up lua callins and found these:
Code: Select all
TerraformComplete() --> "unitID, unitDefID, unitTeam, buildUnitID, buildUnitDefID, buildUnitTeam"
Explosion() --> "weaponID, px, py, pz, ownerID"
They don't seem to lend themselves to polling for terrain deformation.
The reason for display lists is because I'm concerned that some players might experience performance loss without them. On my machine there is little or no performance impact when redrawing everything each time DrawWorldPreUnit() is called, but it was a high-end PC in 2012.
Another (simpler) solution is to set notDeformable=true in mapinfo.lua.
Re: GL rotating ground quad
Posted: 23 Apr 2013, 21:55
by zwzsg
On a metal map, do you switch off nicely, or do you cover the whole map with thousand decals?
Re: GL rotating ground quad
Posted: 24 Apr 2013, 07:55
by Cheesecan
zwzsg wrote:On a metal map, do you switch off nicely, or do you cover the whole map with thousand decals?
This is for a map widget. Don't see why anyone would add it to a metal map.