Rotate image on a quad

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
Bobble68
Party member
Posts: 155
Joined: Wed Nov 30, 2022 9:16 pm
Contact:

Rotate image on a quad

Post by Bobble68 »

Hello there LÖVE forums, I am once again asking for your knowledge and assistance.

I've been working on a game with a level editor where you can draw out polygons for the level platforms, and now I have made it so you can convert them into physics objects.

Each platform has a repeating texture, which I have managed using setWrap(), then drawing it on a quad the size of the screen, and then finally stenciling it - however my issue is that now they are physics objects, they can also rotate. Just setting r on the draw function rotates the whole quad and not just the texture, which means it no longer covers the whole screen.

Is there a good way to achieve what I want?
Dragon
User avatar
Bigfoot71
Party member
Posts: 287
Joined: Fri Mar 11, 2022 11:07 am

Re: Rotate image on a quad

Post by Bigfoot71 »

If I understood correctly what you are describing why not just use `love.graphics.rotate` inside `love.graphics.push` ?

Here is what I mean:

Code: Select all

love.graphics.push()
love.graphics.translate(cx, cy)
love.graphics.rotate(polygon:getRotation())
love.graphics.translate(-cx, -cy)
  
love.graphics.stencil(function()
    love.graphics.polygon("fill", polygon)
end, "replace", 1)
love.graphics.setStencilTest("greater", 0)

love.graphics.draw(
    sprite, cx, cy, sprite_angle, 1, 1,
    sprite:getWidth()/2,
    sprite:getHeight()/2
)

love.graphics.setStencilTest()
love.graphics.pop()
Is that what you were describing?

Image

Here you can manage the rotation of the polygon and the texture separately.
Attachments
Rotation-test.love
(133.14 KiB) Downloaded 68 times
My avatar code for the curious :D V1, V2, V3.
User avatar
Bobble68
Party member
Posts: 155
Joined: Wed Nov 30, 2022 9:16 pm
Contact:

Re: Rotate image on a quad

Post by Bobble68 »

Bigfoot71 wrote: Sun Jan 29, 2023 7:59 pm Is that what you were describing?
Not quite - the main issue is that it needs to be a repeating texture, like so:
Untitled.png
Untitled.png (111.79 KiB) Viewed 3212 times
Here is what I'm currently working with, which works untill you need to rotate the texture around a point

Code: Select all

image = love.graphics.newImage("anImage.png")

function love.draw()
  wrappedDraw(image, love.graphics.getWidth()/2, love.graphics.getHeight()/2, 0)
end



function wrappedDraw(drawable, x, y, r, scale)
  if not scale then
    scale = 1
  end
  if not r then
    r = 1
  end
  drawable:setWrap( "repeat", "repeat" )
  local quad = love.graphics.newQuad( -x, -y, love.graphics.getWidth(), love.graphics.getHeight(), drawable:getWidth()*scale, drawable:getHeight()*scale )
  love.graphics.draw( drawable, quad, 0+love.graphics.getWidth()/2, 0+love.graphics.getHeight()/2, 0, 1, 1, love.graphics.getWidth()/2, love.graphics.getHeight()/2)
end
Appologies for my code, I'm aware I probably do things inefficiently.
Dragon
User avatar
darkfrei
Party member
Posts: 1168
Joined: Sat Feb 08, 2020 11:09 pm

Re: Rotate image on a quad

Post by darkfrei »

See also: viewtopic.php?f=4&t=93939

You can use meshes for it:

Code: Select all

love.window.setMode(800, 800)
W, H = love.graphics.getDimensions( )

function love.load()
	local image = love.graphics.newImage('img-16.png')
	image:setWrap( "repeat" )
	image:setFilter("linear", "nearest")

	local n = 6 -- amount of tiles
	local k = 128 -- size of tile
	local s = n*k -- size of screen
	
	local vertices = {
		{0, 0, 0, 0, 1,1,1},
		{0, s, 0, n, 1,1,1},
		{s, s, n, n, 1,1,1},
		{s, 0, n, 0, 1,1,1},
	}
	mesh = love.graphics.newMesh( vertices, "fan")
	mesh:setTexture(image)
end

Code: Select all

function love.draw()
	love.graphics.draw(mesh)
end
2023-01-29T23_15_19-Untitled.png
2023-01-29T23_15_19-Untitled.png (108.96 KiB) Viewed 3164 times
So, make the round mesh and rotate it around the middle of it.
Attachments
mesh-with-texture-01.love
(1.13 KiB) Downloaded 57 times
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
Bigfoot71
Party member
Posts: 287
Joined: Fri Mar 11, 2022 11:07 am

Re: Rotate image on a quad

Post by Bigfoot71 »

I'm still not sure I understand the problem, is it the `r` variable you forgot to `draw`?

It doesn't matter, if you can't follow darkfrei's instructions, otherwise here's what I wrote to rotate the texture:

Code: Select all

function wrappedDraw(drawable, x, y, r, scale)

    r = r or 0
    scale = scale or 1

    drawable:setWrap( "repeat", "repeat" )
    local quad = love.graphics.newQuad( -x, -y, love.graphics.getWidth(), love.graphics.getHeight(), drawable:getWidth()*scale, drawable:getHeight()*scale )
    love.graphics.draw( drawable, quad, 0+love.graphics.getWidth()/2, 0+love.graphics.getHeight()/2, r, 1, 1, love.graphics.getWidth()/2, love.graphics.getHeight()/2)

end
You will notice that instead of writing:

Code: Select all

if not value then
  value = 1
end
You can simply write:

Code: Select all

value = value or 1
My avatar code for the curious :D V1, V2, V3.
User avatar
Bobble68
Party member
Posts: 155
Joined: Wed Nov 30, 2022 9:16 pm
Contact:

Re: Rotate image on a quad

Post by Bobble68 »

darkfrei wrote: Sun Jan 29, 2023 10:15 pm You can use meshes for it:
Ah I see! I'm unfamilar with meshes (this is the first I knew love could handle them), so I'll look into them. Is this any better than just drawing a quad big enough to fill the entire screen?
Dragon
User avatar
Bobble68
Party member
Posts: 155
Joined: Wed Nov 30, 2022 9:16 pm
Contact:

Re: Rotate image on a quad

Post by Bobble68 »

Bigfoot71 wrote: Mon Jan 30, 2023 10:57 am You will notice that instead of writing:

Code: Select all

if not value then
  value = 1
end
You can simply write:

Code: Select all

value = value or 1
Oh that's very neat! Time to update all my functions...

What I was looking for before was to just fill the whole screen, what I'm trying to avoid is drawing outside the screen area, and not leaving any undrawn area, otherwise you get these corners.
Untitled.png
Untitled.png (716.25 KiB) Viewed 3115 times
Appologies if I'm not being clear, hopefully looking more into meshes will give a solution.


Edit: Upon looking more into meshes, I'm less certain how I can use this to fix my issue if I make a mesh that matches the level polygon, wouldn't that make it difficult to set the UVs correctly?
Dragon
User avatar
Bigfoot71
Party member
Posts: 287
Joined: Fri Mar 11, 2022 11:07 am

Re: Rotate image on a quad

Post by Bigfoot71 »

Bobble68 wrote: Mon Jan 30, 2023 11:13 am
Bigfoot71 wrote: Mon Jan 30, 2023 10:57 am You will notice that instead of writing:

Code: Select all

if not value then
  value = 1
end
You can simply write:

Code: Select all

value = value or 1
Oh that's very neat! Time to update all my functions...

What I was looking for before was to just fill the whole screen, what I'm trying to avoid is drawing outside the screen area, and not leaving any undrawn area, otherwise you get these corners.

Untitled.png

Appologies if I'm not being clear, hopefully looking more into meshes will give a solution.


Edit: Upon looking more into meshes, I'm less certain how I can use this to fix my issue if I make a mesh that matches the level polygon, wouldn't that make it difficult to set the UVs correctly?
Ah okay, unfortunately, mesh or not apart from extending the edges beyond the screen, I don't really see how you could do it to be honest (unless a solution escapes me at this moment)...

Otherwise for the UVs it's very simple when you understand, they go from 0 to 1, where 0.0 is the origin of the image (top left for Löve or bottom left for other engines) and 1.1 is bottom right (or top right...).

Here is an example I made using a mesh:

Code: Select all

local GW, GH = love.graphics.getDimensions()
local GOX, GOY = GW/2, GH/2

local backgroundImage = love.graphics.newImage("background.jpg")
backgroundImage:setWrap("repeat", "repeat") -- Always important to call this method

local backgroundAngle = 0

-- Set a distance larger than the screen size for the vertices of the mesh
local distance = 2 * math.max(GW, GH)

-- Create an array for the texture coordinates of the mesh
-- To repeat the texture it is necessary to normalize from 0 to 1 by dividing the size of the mesh by the size of the texture
-- If we defined the corners only with 0 and 1 the texture would simply be stretched.
local meshVertices = {
    {-distance, -distance, 0, 0},
    {distance, -distance, GW / backgroundImage:getWidth(), 0},
    {distance, distance, GW / backgroundImage:getWidth(), GH / backgroundImage:getHeight()},
    {-distance, distance, 0, GH / backgroundImage:getHeight()}
}

-- Create a mesh from the array
local mesh = love.graphics.newMesh(meshVertices, "fan")
mesh:setTexture(backgroundImage)


-- We do it all --

function love.update(dt)
    backgroundAngle = backgroundAngle + dt
end

function love.draw()
  love.graphics.setColor(1, 1, 1)
  love.graphics.draw(mesh, GOX, GOY, backgroundAngle, 1, 1, GOX, GOY)
end
Image
Attachments
Rotation-test.love
(7.34 KiB) Downloaded 58 times
My avatar code for the curious :D V1, V2, V3.
User avatar
darkfrei
Party member
Posts: 1168
Joined: Sat Feb 08, 2020 11:09 pm

Re: Rotate image on a quad

Post by darkfrei »

Bobble68 wrote: Mon Jan 30, 2023 11:13 am Edit: Upon looking more into meshes, I'm less certain how I can use this to fix my issue if I make a mesh that matches the level polygon, wouldn't that make it difficult to set the UVs correctly?
So,

Code: Select all

function love.load()
	local image = love.graphics.newImage('img-16.png')
	image:setWrap( "repeat" )
	image:setFilter("linear", "nearest")

	local n = 6 -- amount of tiles
	local k = 128 -- size of tile
	local s = n*k -- size of screen
	
	local vertices = {
		{0, 0, 0, 0, 1,1,1},
		{s, 0, n, 0, 1,1,1},
		{0, s, 0, n, 1,1,1},
		{s, s, n, n, 1,1,1},
	}
	mesh = love.graphics.newMesh( vertices, "strip") -- strip, not fan!
	mesh:setTexture(image)
	Angle = 0
end

Code: Select all

local function rotateMesh (mesh, s, n, angle)
	local u1 =  n*math.cos(angle)
	local u2 =  n*math.sin(angle)
	local v1 =  n*math.sin(angle)
	local v2 = -n*math.cos(angle)
	mesh:setVertex(2, s, 0, u1, v1)
	mesh:setVertex(3, 0, s, u2, v2)
	mesh:setVertex(4, s, s, u1+u2, v1+v2)
end
 
function love.update(dt)
	local n, s = 6, 128*6
	Angle = Angle + 0.1*dt
	rotateMesh (mesh, s, n, Angle)
end

Code: Select all

function love.draw()
	love.graphics.draw(mesh)
end
2023-01-30T14_22_35-Untitled.png
2023-01-30T14_22_35-Untitled.png (170.15 KiB) Viewed 3063 times
Attachments
mesh-with-texture-02.love
(1.34 KiB) Downloaded 60 times
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
Bobble68
Party member
Posts: 155
Joined: Wed Nov 30, 2022 9:16 pm
Contact:

Re: Rotate image on a quad

Post by Bobble68 »

darkfrei wrote: Mon Jan 30, 2023 1:23 pm
Bobble68 wrote: Mon Jan 30, 2023 11:13 am Edit: Upon looking more into meshes, I'm less certain how I can use this to fix my issue if I make a mesh that matches the level polygon, wouldn't that make it difficult to set the UVs correctly?
So,

Code: Select all

function love.load()
	local image = love.graphics.newImage('img-16.png')
	image:setWrap( "repeat" )
	image:setFilter("linear", "nearest")

	local n = 6 -- amount of tiles
	local k = 128 -- size of tile
	local s = n*k -- size of screen
	
	local vertices = {
		{0, 0, 0, 0, 1,1,1},
		{s, 0, n, 0, 1,1,1},
		{0, s, 0, n, 1,1,1},
		{s, s, n, n, 1,1,1},
	}
	mesh = love.graphics.newMesh( vertices, "strip") -- strip, not fan!
	mesh:setTexture(image)
	Angle = 0
end

Code: Select all

local function rotateMesh (mesh, s, n, angle)
	local u1 =  n*math.cos(angle)
	local u2 =  n*math.sin(angle)
	local v1 =  n*math.sin(angle)
	local v2 = -n*math.cos(angle)
	mesh:setVertex(2, s, 0, u1, v1)
	mesh:setVertex(3, 0, s, u2, v2)
	mesh:setVertex(4, s, s, u1+u2, v1+v2)
end
 
function love.update(dt)
	local n, s = 6, 128*6
	Angle = Angle + 0.1*dt
	rotateMesh (mesh, s, n, Angle)
end

Code: Select all

function love.draw()
	love.graphics.draw(mesh)
end
2023-01-30T14_22_35-Untitled.png
Thats nearly perfect! Only issue is it needs to be able to be rotated around a specific point, rather than just 0,0 so it doesn't shift when a physics object rotate. I tried to figure out how to do it, though I got wrong (though interesting to look at) results.
Untitled.png
Untitled.png (1.08 MiB) Viewed 3048 times
Dragon
Post Reply

Who is online

Users browsing this forum: No registered users and 20 guests