Slicing a body

Started by
5 comments, last by ClaF 12 years, 11 months ago
Hey, I'm using Farseer physics engine and would like to be able to slice a body into two pieces. What would be the best way of doing this in Silverlight? It's similar to the 'Cut the rope' game where you slice the rope and it cuts at that place. Any suggestions on what technique I should use? Thanks for any help
Advertisement
i think you want to make two dffrent models from one model splitted by a plane







so there: from nvidia portal engine






procedure AddVertex(const x: t3dpoint; var res: TPolygon);
begin

// Append a vertex to a polygon.
if (res.Count = 0) or
(magnitude(vectors_substract_v1minusv2(x, res.V[res.Count-1])) > 0.01) then
begin
INC(res.Count);
res.V[res.Count-1] := x;
end;

end;

function ClipEdge(const v1, v2: t3dpoint; const plane: t3dpoint): t3dpoint;
var
v: t3dpoint;
t: Single;
begin

// Clip a line segment to a plane, return the new end point.
v := vectors_substract_v1minusv2(v2, v1);
// t := -sdotPlaneVecDist(plane, v1) / iloczynskalarny3d(plane, v);
Result := vectors_add(v1, vector_multiple(v, t));

end;

function dotVecScalarMult3(v: TDotVector3; s: Single): TDotVector3;
begin

Result.x := v.x * s;
Result.y := v.y * s;
Result.z := v.z * s;

end;


function ClipPoly(const poly: TPolygon; const plane: t3dpoint): TPolygon;
var
a, b: t3dpoint;
count, i: Integer;
da, db: Integer;
clipped: TPolygon;
begin

// Clip a polygon to a plane.
count := poly.Count;
clipped.Count := 0;

for i := 0 to count - 1 do
begin
a := poly.V;
b := poly.V[(i+1) mod count];

da := classifyapointagainstaplane(a,plane,getplaned(plane,a));
db := classifyapointagainstaplane(b,plane,getplaned(plane,b));

if da < 1 then
begin
AddVertex(a, clipped);
if db = 1 then AddVertex(ClipEdge(a, b, plane), clipped);
end
else if db = -1 then
begin
AddVertex(ClipEdge(a, b, plane), clipped);
AddVertex(b, clipped);
end;
end;

Result := clipped;
result.normal := poly.normal;
end;

[/quote]







but in other words












const float SPECIAL_FEAUTRE = 0.00000001; //wtf ;u called epsilon

const int isOnPlane = 0;
const int isFront = 1;
const int isBack = -1;


int __fastcall classifyapointagainstaplane(t3dpoint point,t3dpoint normal,float distance)
{
float costam;
int result;
costam = dotproduct(point,normal)+distance;
if (costam > 0) result = isFront;
if (costam < 0) result = isBack;
if (betweenorequal(-SPECIAL_FEAUTRE,SPECIAL_FEAUTRE,costam) == true) result = isOnPlane;

return result;
}









[/quote]







so we have model- models have vertices the vertices represent polygons the polygons have sides




heres a function that i made years ago :P actually i didnt finish this function at all






void __fastcall TachoGLModel::SplitByPlane(int delete_side, t3dpoint split_normal, float split_distance,t3dpoint point_on_split_plane)
{
int i;
bool found=false;
int BASE_SIDE;
int j;
t3dpoint vline[2];

t3dpoint C[2];
int SPLIT_COUNT=0;
int cnt=0;
LIGHT_TRAIL NEW_FACE;


for (i = 0; i < VBO_BE.Length; i++) {
found = false;

for (j = VBO_BE.INDEX_START+1; j < VBO_BE.INDEX_START+VBO_BE.length; j++) {
BASE_SIDE = classifyapointagainstaplane(VBO_V[j-1],split_normal,split_distance);
if (classifyapointagainstaplane(VBO_V[j],split_normal,split_distance) != delete_side ) cnt = cnt + 1;

if (classifyapointagainstaplane(VBO_V[j],split_normal,split_distance) != BASE_SIDE) {
vline[0] = VBO_V[j-1];
vline[1] = VBO_V[j];
C[SPLIT_COUNT] = PUNKT_PRZECIECIA_ODCINEK_PLASZCZYZNA(split_normal,point_on_split_plane,vline);
SPLIT_COUNT = SPLIT_COUNT + 1;

}
}//eof for j


SPLIT_COUNT = 0;
NEW_FACE.set_length(cnt+2);
cnt = -1;

for (j = VBO_BE.INDEX_START+1; j < VBO_BE.INDEX_START+VBO_BE.length; j++) {
BASE_SIDE = classifyapointagainstaplane(VBO_V[j-1],split_normal,split_distance);
if (classifyapointagainstaplane(VBO_V[j],split_normal,split_distance) != delete_side ) { cnt = cnt + 1; NEW_FACE[cnt] = VBO_V[j]; }

if (classifyapointagainstaplane(VBO_V[j],split_normal,split_distance) != BASE_SIDE) {

cnt = cnt + 1; NEW_FACE[cnt] = C[SPLIT_COUNT];

SPLIT_COUNT = SPLIT_COUNT + 1;

}
}//eof for j

Replace_Face(NEW_FACE,i);
//REPLACE FACE

//nie dokonczone

}



}



[/quote]







and again in other words:




go through all faces (polygons ) in a mesh:

test where they are ( front or back of split plane)




if tehe is at least one vertex that is different from BASE_SIDE (note that base side is a side for first vertex in face)

we must split this face

now compare

two sides from wrong vertex:




ONE_SIDE = vectorAB( VERTS[ WRONG_INDEX], VERTS[WRONG_INDEX + 1]);

SECOND_SIDE = vectorAB( VERTS[ WRONG_INDEX], VERTS[WRONG_INDEX - 1]);




if WRONG_INDEX is 0 then wrong_index - 1 equals to tle last face vert

if wrong_index is the last face vert then wrong__index +1 is the first face index = 0




then you calculate point of intersection between line and plane:




there are many wasy to do iit and i dont have the simpliest code for doing that but i dont care














t3dpoint __fastcall PUNKT_PRZECIECIA_ODCINEK_PLASZCZYZNA(t3dpoint vNormal,t3dpoint pointonplane,
t3dpoint vLine[2])
{
const Extended MATCH_FACTOR = 0.9999999999;


t3dpoint vIntersection;// : t3dpoint;
Extended originDistance;
Extended distance1;
Extended distance2;
double m_magnitude;// : Double;
t3dpoint vPoint;// : t3dpoint;
t3dpoint vLineDir;// : t3dpoint;
Extended Numerator;// : Extended;
Extended Denominator;// : Extended;
Extended dist;// : Extended;
Extended Angle,tempangle;// : Extended;
t3dpoint vA, vB;// : t3dpoint;
int I;
Extended dotProduct;// : Extended;
Extended vectorsMagnitude;// : Extended;

t3dpoint result;

originDistance = 0;
distance1 = 0;
distance2 = 0;
vPoint.x = 0;
vPoint.y = 0;
vPoint.z = 0;

vLineDir.x = 0;
vLineDir.y = 0;
vLineDir.z = 0;

Numerator = 0.0;
Denominator = 0.0;
dist = 0.0;
Angle = 0.0;



originDistance = -1 * ((vNormal.x * pointonplane.x) +
(vNormal.y * pointonplane.y) +
(vNormal.z * pointonplane.z));


distance1 = ((vNormal.x * vLine[0].x) +
(vNormal.y * vLine[0].y) +
(vNormal.z * vLine[0].z)) + originDistance;

distance2 = ((vNormal.x * vLine[1].x) +
(vNormal.y * vLine[1].y) +
(vNormal.z * vLine[1].z)) + originDistance;

if(distance1 * distance2 >= 0) {
t3dpoint r; //linia nie przebija plaszczyzny
r.x = 1.0f; r.y = 1.0f; r.z = 1.0f;
return r;
}




vLineDir.x = vLine[1].x - vLine[0].x;
vLineDir.y = vLine[1].y - vLine[0].y;
vLineDir.z = vLine[1].z - vLine[0].z;

m_magnitude = sqrt((vLineDir.x * vLineDir.x) +
(vLineDir.y * vLineDir.y) +
(vLineDir.z * vLineDir.z) );

if (m_magnitude == 0.0) m_magnitude = 1.0f;


vLineDir.x = vLineDir.x/m_magnitude;
vLineDir.y = vLineDir.y/m_magnitude;
vLineDir.z = vLineDir.z/m_magnitude;



Numerator = -1 * (vNormal.x * vLine[0].x +
vNormal.y * vLine[0].y +
vNormal.z * vLine[0].z + originDistance);




Denominator = ( (vNormal.x * vLineDir.x) + (vNormal.y * vLineDir.y) + (vNormal.z * vLineDir.z) );

if( Denominator == 0.0) {

vIntersection = vLine[0];
return vIntersection;
} else {



dist = Numerator / Denominator;



vPoint.x = (vLine[0].x + (vLineDir.x * dist));
vPoint.y = (vLine[0].y + (vLineDir.y * dist));
vPoint.z = (vLine[0].z + (vLineDir.z * dist));

result.x = vPoint.x; // Return the intersection point
result.y = vPoint.y;
result.z = vPoint.z;

}

return result;

}

[/quote]











after calc this point you should create a new face .....




hope ihelped lol
Thanks. I understand some of it, and have managed to get intersection points. The hard part is using this in Silverlight as I can't seem to render the fixture to a UIElement. Btw, this is 2D.
for me its harder to explain this in 2d because of equation y=ax+b when whe have prependicular line to OX line ( there is one X and infinite Y :P)




for those equation lets try and use vertex.z = 0 then ;) for any normal or vertex or plane equation
I've managed to get Farseer to take care of most of the intersection points and such. But the resulting vertices of each new body has to someone be displayed as an UIElement. This is what's now tripping me up sad.gif
sorry cant help you at this stage i dont know ms silversight (but i have installed it lol) and farser




try this http://www.google.pl/search?hl=pl&client=opera&hs=4NP&rls=en&channel=suggest&q=drawin+on+UIElement&aq=f&aqi=&aql=&oq=




:P

lol don't think I haven't tried! biggrin.gif Trying to find how to create a UIElement for a given fixture and attach it.

This topic is closed to new replies.

Advertisement