GL rotating ground quad

GL rotating ground quad

Discuss Lua based Spring scripts (LuaUI widgets, mission scripts, gaia scripts, mod-rules scripts, scripted keybindings, etc...)

Moderator: Moderators

Post Reply
User avatar
Cheesecan
Posts: 1571
Joined: 07 Feb 2005, 21:30

GL rotating ground quad

Post 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:
Image
User avatar
knorke
Posts: 7971
Joined: 22 Feb 2006, 01:02

Re: GL rotating ground quad

Post 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:
Image
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
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7049
Joined: 16 Nov 2004, 13:08

Re: GL rotating ground quad

Post by zwzsg »

Shouldn't you rotate around Y, instead of X?
User avatar
Cheesecan
Posts: 1571
Joined: 07 Feb 2005, 21:30

Re: GL rotating ground quad

Post 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!

Image
User avatar
knorke
Posts: 7971
Joined: 22 Feb 2006, 01:02

Re: GL rotating ground quad

Post 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:
Image
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)   
User avatar
Cheesecan
Posts: 1571
Joined: 07 Feb 2005, 21:30

Re: GL rotating ground quad

Post 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
User avatar
BrainDamage
Lobby Developer
Posts: 1164
Joined: 25 Sep 2006, 13:56

Re: GL rotating ground quad

Post 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 )
User avatar
Cheesecan
Posts: 1571
Joined: 07 Feb 2005, 21:30

Re: GL rotating ground quad

Post 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.
User avatar
zwzsg
Kernel Panic Co-Developer
Posts: 7049
Joined: 16 Nov 2004, 13:08

Re: GL rotating ground quad

Post by zwzsg »

On a metal map, do you switch off nicely, or do you cover the whole map with thousand decals?
User avatar
Cheesecan
Posts: 1571
Joined: 07 Feb 2005, 21:30

Re: GL rotating ground quad

Post 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.
Post Reply

Return to “Lua Scripts”