Spine finding a bit of a showstopper with LÖVE

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
gianmichele
Citizen
Posts: 63
Joined: Tue Jan 14, 2014 11:03 pm

Spine finding a bit of a showstopper with LÖVE

Post by gianmichele »

Seems like they might need a bit more support. Any plan for it?

Spine is an amazing piece of software and LÖVE too ;)

http://esotericsoftware.com/forum/viewt ... f=3&t=3690
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: Spine finding a bit of a showstopper with LÖVE

Post by bartbes »

It's not immediately obvious what the problem is? If he just wants textured quadrilaterals it should be possible.
User avatar
josefnpat
Inner party member
Posts: 955
Joined: Wed Oct 05, 2011 1:36 am
Location: your basement
Contact:

Re: Spine finding a bit of a showstopper with LÖVE

Post by josefnpat »

Perhaps he's talking about what I ran into, which was affine texture mapping:

Image
Missing Sentinel Software | Twitter

FORCIBLY IGNORED.
<leafo> when in doubt delete all of your code
<bartbes> git rm -r *
<bartbes> git commit -m "Fixed all bugs"
<bartbes> git push
User avatar
slime
Solid Snayke
Posts: 3144
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: Spine finding a bit of a showstopper with LÖVE

Post by slime »

You won't run into perspective-correctness issues with assets designed for use with orthographic 2D / affine transforms (e.g. what Spine creates, I assume.) It looks like the Corona framework (unlike LÖVE) does do some perspective-correctness shenanigans itself, which is causing problems for Spine when used with Corona.

Like bartbes said the post doesn't really explain what the problem with LÖVE might be. LÖVE supports [wiki]Mesh[/wiki]es with a fixed amount of vertex attributes per vertex (2 position coordinate components, 2 uv coordinate components, and 4 color components.) Maybe Spine needs more?
If so, that's planned for the future but won't be in LÖVE 0.9.x: https://bitbucket.org/rude/love/issue/7 ... for-meshes
NateS
Prole
Posts: 8
Joined: Thu Feb 14, 2013 1:47 pm

Re: Spine finding a bit of a showstopper with LÖVE

Post by NateS »

Hi guys! We definitely don't want perspective correction. It sounds like LÖVE can actually render meshes fine, sorry for my confusion. I've added a task for it:
https://trello.com/c/5bw8RITR/70-mesh-support-for-love

I don't have time at the moment to dig deeper, but it sounds like it won't be too hard to implement. Spine provides the vertices, triangles, and UVs so it's just a matter of sticking them in the appropriate LÖVE API. Eg, here it is done in C++:
https://github.com/EsotericSoftware/spi ... ml.cpp#L96
Here it is in AS3:
https://github.com/EsotericSoftware/spi ... te.as#L117

I'm currently using LÖVE scene graph nodes to render Spine attachments:
https://github.com/EsotericSoftware/spi ... e.lua#L118
This is why I didn't think LÖVE supported meshes, but I admit I must not have looked very hard. I would much prefer to render the whole thing as a mesh!
User avatar
Jasoco
Inner party member
Posts: 3725
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Spine finding a bit of a showstopper with LÖVE

Post by Jasoco »

When I started working with 3D a friendly Löver at the time, xXxMoNkEyMaNxXx, was kind enough to write a shader to do it correctly for me. At least mostly correct. I don't have the original code he gave me, and have made so many modifications since then, but if I need to I can provide it as-is. I don't think he's a member here anymore.

Edit: I did find an original version of the .lua file in a "benchmark" project I created to test the speed of texturing. Here it is as-is when he gave it to me as far as I know:

Code: Select all

--By xXxMoNkEyMaNxXx
--[[Complete API----  This was made to be a module, PLEASE USE IT AS A MODULE

	.cw=false
	-Counter clockwise vertex order starting at top left.

	.cw=true
	-Clockwise vertex order starting at top left.


	.preload(loadup):

	-loadup==true sets pixel effect to polygon texturer,
	-loadup==false clears any pixel effect.
	*NOTE: preload(false) must be done to draw blank polygons after textured ones.


	.setRepeat(origin,size):
	-Makes the image repeat every 'size' starting at 'origin'.
	-The default is origin={0,0},size={1,1}.


	.quad(image,v1,v2,v3,v4) - Draws a polygon.

	-if 'image' is nil, the function will prepare to make it blank.


	.quad(v1,v2,v3,v4) - draws a polygon with no image.


	.fast(image,v1,v2,v3,v4) - draws a polygon with 'image' on it.
	-slightly(!!!) faster than quad.
	-Must include an image.
	-Must call .preload(true) beforehand.


	Info:
	Vertices are in the form {x,y}.
	Vertices go clockwise from the top left.

	v1---v2
	| img |
	v4---v3
--]]

--Modified by RogueCarrot
local glsl=love.graphics.newShader[[
//Made by xXxMoNkEyMaNxXx

extern Image img;
extern vec2 v1;
extern vec2 v2;
extern vec2 v3;
extern vec2 v4;

extern vec2 p0;
extern vec2 rep;

extern number SIZEY;//So annoying
extern number SIZEX;//So annoying

vec2 one=vec2(1.0,1.0);

number c(vec2 v1,vec2 v2)
{
	return v1.x*v2.y-v2.x*v1.y;
}
number intersect(vec2 v1,vec2 d1,vec2 v2,vec2 d2)
{
	//v1+d1*
	return c(v2-v1,d2)/c(d1,d2);
}
vec4 mask(vec4 base,vec4 over)
{
	return vec4(over.rgb*over.a+base.rgb*(1-over.a),over.a+base.a*(1-over.a));
}
vec4 effect(vec4 colour,Image UNUSED1,vec2 UNUSED2,vec2 inverted)
{
	vec2 p=vec2(inverted.x*SIZEX,SIZEY-inverted.y);//SO ANNOYING

	vec2 A1=normalize(v2-v1);
	vec2 A2=normalize(v3-v4);

	vec2 B1=normalize(v2-v3);
	vec2 B2=normalize(v1-v4);

	number Adiv=c(A1,A2);
	number Bdiv=c(B1,B2);

	vec2 uv;

	bvec2 eq0=bvec2(abs(Adiv)<=0.0001,abs(Bdiv)<=0.0001);
	if(eq0.x && eq0.y){
		//Both edges are parallel, therefore the shape is a parallelogram (Isometric)
		number dis=dot(p-v1,A1);

		//cos theta
		number ct=dot(A1,B1);

		//Closest point on v1->A1 to p
		vec2 pA=v1+A1*dis;

		//uv
		number r=length(p-pA)/sqrt(1-ct*ct);
		uv=vec2(1-r/length(v2-v3),(dis+r*ct)/length(v2-v1));
	}else if(eq0.x){
		//One Vanishing point occurs in numerically set scenarios in 3D, and is a feature of 2.5D

		//Horizon is A1 (=A2) from B
		vec2 Vp=v3+B1*c(v4-v3,B2)/Bdiv;

		//Some point in the distance that diagonals go to
		vec2 D=Vp+A1*intersect(Vp,A1,v4,normalize(v2-v4));

		//uv
		number u=intersect(v1,A1,Vp,normalize(p-Vp));
		number v=intersect(v1,A1,D,normalize(p-D))-u;

		number len=length(v2-v1);
		uv=vec2(len-v,u)/len;//Reversed components to match up with other one
	}else if(eq0.y){
		//If the other edge is the parallel one
		vec2 Vp=v1+A1*c(v4-v1,A2)/Adiv;
		vec2 D=Vp+B1*intersect(Vp,B1,v4,normalize(v2-v4));
		number u=intersect(v3,B1,Vp,normalize(p-Vp));
		number len=length(v2-v3);
		uv=vec2(u,len-intersect(v3,B1,D,normalize(p-D))+u)/len;
	}else{
		//Else, two vanishing points

		//*intersect(v1,A1,v4,A2)
		//*intersect(v3,B1,v4,B2)

		//Vanishing points
		vec2 A=v1+A1*c(v4-v1,A2)/Adiv;
		vec2 B=v3+B1*c(v4-v3,B2)/Bdiv;

		//Horizon
		vec2 H=normalize(A-B);

		//Pixel
		uv=vec2(intersect(v4,-H,A,normalize(p-A))/intersect(v4,-H,v2,-A1),intersect(v4,H,B,normalize(p-B))/intersect(v4,H,v2,-B1));
	}
	return mask(colour,Texel(img,mod(uv*rep+vec2(p0.x-1,p0.y),one)));
}
]]
local gl_send=glsl.send
local q=love.graphics.polygon
local win = love.window
-- local lgr = love.graphics
local setEffect=love.graphics.setShader
gl_send(glsl,"SIZEX",1)--So annoying
gl_send(glsl,"SIZEY",love.graphics.getHeight())--So annoying
gl_send(glsl,"p0",{0,0})
gl_send(glsl,"rep",{1,1})

module(...)
cw=true--clockwise
function preload(loadup)
	if loadup then
		setEffect(glsl)
	else
		setEffect()
	end
end
function setRepeat(origin,size)
	gl_send(glsl,"p0",origin)
	gl_send(glsl,"rep",size)
end
function fast(img,v1,v2,v3,v4)
	gl_send(glsl,"img",img)
	gl_send(glsl,"v1",v2)
	gl_send(glsl,"v2",v3)
	gl_send(glsl,"v3",v4)
	gl_send(glsl,"v4",v1)
	q("fill",v1[1],v1[2],v2[1],v2[2],v3[1],v3[2],v4[1],v4[2])
end
function quad(img,v1,v2,v3,v4,w,h)
	if h then gl_send(glsl,"SIZEY",h) end
	if w then gl_send(glsl,"SIZEX",w/win.getWidth()) end
	if img and v4 then
		setEffect(glsl)
		gl_send(glsl,"img",img)
		if cw then
			gl_send(glsl,"v1",v2)
			gl_send(glsl,"v2",v3)
			gl_send(glsl,"v3",v4)
			gl_send(glsl,"v4",v1)
		else
			gl_send(glsl,"v1",v2)
			gl_send(glsl,"v2",v1)
			gl_send(glsl,"v3",v4)
			gl_send(glsl,"v4",v3)
		end
	else
		setEffect()
	end
	-- lgr.setBlendMode("premultiplied")
	if v4 then
		q("fill",v1[1],v1[2],v2[1],v2[2],v3[1],v3[2],v4[1],v4[2])
	else--img acts as a vertex
		q("fill",img[1],img[2],v1[1],v1[2],v2[1],v2[2],v3[1],v3[2])
	end
	-- lgr.setBlendMode("alpha")
	setEffect()
end
All credit goes to xXxMoNkEyMaNxXx.

It's better than nothing if you need to draw a four sided polygon with a texture on it and Meshes aren't doing it for you.
Post Reply

Who is online

Users browsing this forum: No registered users and 3 guests