Hello guys,
I’m currently working on porting the Box2D buoyancy controller from AS3 to LUA … I’m almost there …I think :).
I just need to debug the function that calculates the submerged area of a body. I think it’s a index problem (in AS3 arrays start at 0)…I’ve modified the indexes but I can figure it out.
Anyway here’s the code in LUA:
[lua]function ComputeSubmergedArea(params)
local normal = params.normal;
local offset = params.offset;
local the_body=params.body;
–vertices arrray
– get it from the body or pass it in
local m_vertices=params.vertices;
– basically we’re using just rectangles so we’ve got 4 vertexes
– use count from above
local m_vertexCount= 4 --params.vcount;
local xf={};
xf.position={the_body.x, the_body.y};
local RR={};
RR.col1={1,0};
RR.col2={0,1};
xf.R=RR;
function SetAngle(par)
local c = math.cos(par.angle);
local s= math.sin(par.angle);
local R=par.R;
R.col1[1] = c; R.col2[1] = -s;
R.col1[2] = s; R.col2[2] = c;
return R;
end
function Dot(para)
local a=para.first;
local b=para.second;
local d=a[1] * b[1] + a[2] * b[2];
return d;
end
function MulTMV(para)
local u={Dot({first=para.v, second=para.A.col1}), Dot({first=para.v, second=para.A.col2})}
return u;
end
xf.R=SetAngle({R=xf.R,angle=the_body.rotation});
– Transform plane into shape co-ordinates
local normalL= MulTMV({A=xf.R, v=normal});
local offsetL= offset - Dot({first=normal, second=xf.position});
local depths={};
local diveCount = 0;
local intoIndex = -1;
local outoIndex = -1;
local lastSubmerged = false;
local isSubmerged;
local i;
for i = 1, m_vertexCount, 1 do
— DOT && MIN_VALUE
depths[i] = Dot({first=normalL, second=m_vertices[i]}) - offsetL;
isSubmerged = depths[i] < -0.0000000000001;
if (i > 1) then
if (isSubmerged) then
if not(lastSubmerged) then
intoIndex = i - 1;
diveCount=diveCount+1;
end
else
if (lastSubmerged) then
outoIndex = i - 1;
diveCount=diveCount+1;
end
end
end
lastSubmerged = isSubmerged;
end
if (diveCount==0) then
if (lastSubmerged ) then
print(‘Completly submerged’)
-------------------------------------------------------totaly submerged
return 100;
else
–Completely dry
print(‘Completly dry’)
return 0;
end
elseif (diveCount==1) then
if (intoIndex == -1) then
intoIndex = m_vertexCount - 1;
else
outoIndex = m_vertexCount - 1;
end
end
local intoIndex2 = (intoIndex ) % m_vertexCount;
local outoIndex2 = (outoIndex ) % m_vertexCount;
print(intoIndex, intoIndex2, outoIndex, outoIndex2);
local intoLamdda = (0 - depths[intoIndex]) / (depths[intoIndex2] - depths[intoIndex]);
local outoLamdda = (0 - depths[outoIndex]) / (depths[outoIndex2] - depths[outoIndex]);
local intoVec = {m_vertices[intoIndex][1] * (1 - intoLamdda) + m_vertices[intoIndex2][1] * intoLamdda,
m_vertices[intoIndex][2] * (1 - intoLamdda) + m_vertices[intoIndex2][2] * intoLamdda};
local outoVec = {m_vertices[outoIndex][1] * (1 - outoLamdda) + m_vertices[outoIndex2][1] * outoLamdda,
m_vertices[outoIndex][2] * (1 - outoLamdda) + m_vertices[outoIndex2][2] * outoLamdda};
– Initialize accumulator
area = 0;
center = {0,0};
p2= m_vertices[intoIndex2];
p3={}
– An awkward loop from intoIndex2+1 to outIndex2
i = intoIndex2;
while (i ~= outoIndex2) do
i = (i ) % m_vertexCount;
if(i == outoIndex2) then
p3 = outoVec;
else
print("nr i ",i)
p3 = m_vertices[i];
end
local triangleArea = 0.5 * ( (p2[1] - intoVec[1]) * (p3[2] - intoVec[2]) - (p2[2] - intoVec[2]) * (p3[1] - intoVec[1]) );
area = area + triangleArea;
– Area weighted centroid
center[1] = center[1] + triangleArea * (intoVec[1] + p2[1] + p3[1]) / 3;
center[2] = center[2] + triangleArea * (intoVec[2] + p2[2] + p3[2]) / 3;
p2 = p3;
end
–Normalize and transform centroid
function Multiply§
local v= {}
v[1]=p.vector[1] * p.factor;
v[2]=p.vector[2] * p.factor;
return v;
end
–center=Multiply({factor=1 / area, vector=center});
–c.SetV(b2Math.MulX(xf, center));
–print ("Submerged Area: ", area );
return area;
end[/lua]
and here is the AS3 function:
[as3]
public override function ComputeSubmergedArea(
normal:b2Vec2,
offset:Number,
xf:b2Transform,
c:b2Vec2):Number
{
// Transform plane into shape co-ordinates
var normalL:b2Vec2 = b2Math.MulTMV(xf.R, normal);
var offsetL:Number = offset - b2Math.Dot(normal, xf.position);
var depths:Vector. = new Vector.();
var diveCount:int = 0;
var intoIndex:int = -1;
var outoIndex:int = -1;
var lastSubmerged:Boolean = false;
var i:int;
for (i = 0; i < m_vertexCount;++i)
{
depths[i] = b2Math.Dot(normalL, m_vertices[i]) - offsetL;
var isSubmerged:Boolean = depths[i] < -Number.MIN_VALUE;
if (i > 0)
{
if (isSubmerged)
{
if (!lastSubmerged)
{
intoIndex = i - 1;
diveCount++;
}
}
else
{
if (lastSubmerged)
{
outoIndex = i - 1;
diveCount++;
}
}
}
lastSubmerged = isSubmerged;
}
switch(diveCount)
{
case 0:
if (lastSubmerged )
{
// Completely submerged
var md:b2MassData = new b2MassData();
ComputeMass(md, 1);
c.SetV(b2Math.MulX(xf, md.center));
return md.mass;
}
else
{
//Completely dry
return 0;
}
break;
case 1:
if (intoIndex == -1)
{
intoIndex = m_vertexCount - 1;
}
else
{
outoIndex = m_vertexCount - 1;
}
break;
}
var intoIndex2:int = (intoIndex + 1) % m_vertexCount;
var outoIndex2:int = (outoIndex + 1) % m_vertexCount;
var intoLamdda:Number = (0 - depths[intoIndex]) / (depths[intoIndex2] - depths[intoIndex]);
var outoLamdda:Number = (0 - depths[outoIndex]) / (depths[outoIndex2] - depths[outoIndex]);
var intoVec:b2Vec2 = new b2Vec2(m_vertices[intoIndex].x * (1 - intoLamdda) + m_vertices[intoIndex2].x * intoLamdda,
m_vertices[intoIndex].y * (1 - intoLamdda) + m_vertices[intoIndex2].y * intoLamdda);
var outoVec:b2Vec2 = new b2Vec2(m_vertices[outoIndex].x * (1 - outoLamdda) + m_vertices[outoIndex2].x * outoLamdda,
m_vertices[outoIndex].y * (1 - outoLamdda) + m_vertices[outoIndex2].y * outoLamdda);
// Initialize accumulator
var area:Number = 0;
var center:b2Vec2 = new b2Vec2();
var p2:b2Vec2 = m_vertices[intoIndex2];
var p3:b2Vec2;
// An awkward loop from intoIndex2+1 to outIndex2
i = intoIndex2;
while (i != outoIndex2)
{
i = (i + 1) % m_vertexCount;
if(i == outoIndex2)
p3 = outoVec
else
p3 = m_vertices[i];
var triangleArea:Number = 0.5 * ( (p2.x - intoVec.x) * (p3.y - intoVec.y) - (p2.y - intoVec.y) * (p3.x - intoVec.x) );
area += triangleArea;
// Area weighted centroid
center.x += triangleArea * (intoVec.x + p2.x + p3.x) / 3;
center.y += triangleArea * (intoVec.y + p2.y + p3.y) / 3;
p2 = p3;
}
//Normalize and transform centroid
center.Multiply(1 / area);
c.SetV(b2Math.MulX(xf, center));
return area;
}
[/as3]
If anyone can help with getting this working I would really appreciate it. I’m planing on sharing the hole thing with the community as soon as I finish porting it (I still need to port some code for circular shapes and bodies with multiple shapes).
Thanks.
[import]uid: 88546 topic_id: 16060 reply_id: 78167[/import]