Box2D 中的光线投射?

发布于 2024-12-23 16:53:24 字数 1514 浏览 0 评论 0原文

我正在创建一个项目,其中有随机的 Box2d 主体。现在我在DRAW方法中根据用户的TouchesMoved画一条线我需要使用RayCasting > Box2d 的方法检查该线和 Box2D 主体之间是否有交集

我在 Draw 方法中使用以下代码

for(int i = 0; i < [pointTouches count]; i+=2)
{
    CGPoint startPoint = CGPointFromString([pointTouches objectAtIndex:i]);

    CGPoint endPoint = CGPointFromString([pointTouches objectAtIndex:i+1]);

    ccDrawLine(startPoint, endPoint);

    b2Vec2 start=[self toMeters:startPoint];

    b2Vec2 end=[self toMeters:endPoint];

    [self checkIntersectionbtw:start:end];
}

-(void)checkIntersectionbtw:(b2Vec2)point1:(b2Vec2)point2
{
    RaysCastCallback callback;

world->RayCast(&callback, point1,point2);

if (callback.m_fixture)
{
    NSLog(@"intersected");
    checkPoint = true;
}
}

-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{ 

    UITouch *myTouch = [touches anyObject];

    CGPoint currentTouchArea = [myTouch locationInView:[myTouch view]];
    CGPoint lastTouchArea = [myTouch previousLocationInView:[myTouch view]];

    currentTouchArea = [[CCDirector sharedDirector] convertToGL:currentTouchArea];
    lastTouchArea = [[CCDirector sharedDirector] convertToGL:lastTouchArea];

    [pointTouches addObject:NSStringFromCGPoint(currentTouchArea)];
    [pointTouches addObject:NSStringFromCGPoint(lastTouchArea)];


}

,但回调仅在绘制的线完全通过实体时告诉交点。当用户从外部某个点开始并将该点留在 box2d 体内时,回调不会说线相交。我可能做错了什么?

i am creating a project in which i have random Box2d bodies. Now i am drawing a line on basis of TouchesMoved by user in the DRAW method. i need to use the RayCasting method of Box2d to check for intersection between that line and the Box2D bodies.

i am using the following code for it in my Draw method

for(int i = 0; i < [pointTouches count]; i+=2)
{
    CGPoint startPoint = CGPointFromString([pointTouches objectAtIndex:i]);

    CGPoint endPoint = CGPointFromString([pointTouches objectAtIndex:i+1]);

    ccDrawLine(startPoint, endPoint);

    b2Vec2 start=[self toMeters:startPoint];

    b2Vec2 end=[self toMeters:endPoint];

    [self checkIntersectionbtw:start:end];
}

-(void)checkIntersectionbtw:(b2Vec2)point1:(b2Vec2)point2
{
    RaysCastCallback callback;

world->RayCast(&callback, point1,point2);

if (callback.m_fixture)
{
    NSLog(@"intersected");
    checkPoint = true;
}
}

-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{ 

    UITouch *myTouch = [touches anyObject];

    CGPoint currentTouchArea = [myTouch locationInView:[myTouch view]];
    CGPoint lastTouchArea = [myTouch previousLocationInView:[myTouch view]];

    currentTouchArea = [[CCDirector sharedDirector] convertToGL:currentTouchArea];
    lastTouchArea = [[CCDirector sharedDirector] convertToGL:lastTouchArea];

    [pointTouches addObject:NSStringFromCGPoint(currentTouchArea)];
    [pointTouches addObject:NSStringFromCGPoint(lastTouchArea)];


}

but the callback only tells the intersection when the line drawn completely passes the bodies. when user starts from some point outside and leaves the point inside the box2d body the callback doesn't say the line intersected. what am i possibly doing wrong??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

别想她 2024-12-30 16:53:24

你画的是直线还是曲线?对于一条线,我假设您仅使用检测到的第一个点和最后一个点。对于曲线,您可以使用检测到的所有点来形成您正在绘制的曲线。

如果你正在画一条曲线,那么我想我理解了这个问题。您正在使用触摸系统检测到的连续点来计算相交线。这些连续的点彼此非常接近,这会产生非常小的光线投射,并且可能发生的情况是,您可能会在球内投射起点和终点的线,这可能会产生负面碰撞。

如果目标是检测您是否正在触摸球,我建议使用在触摸下维护的传感器,然后在更新方法中检查与此代码的碰撞:

for (b2ContactEdge* ce = sensorbody->GetContactList(); ce; ce = ce->next)
{   
    b2Contact* c = ce->contact;

    if(c->IsTouching())
    {
         const b2Body* bodyA = c->GetFixtureA()->GetBody();
         const b2Body* bodyB = c->GetFixtureB()->GetBody();

         const b2Body* ballBody = (bodyA == sensorbody)?bodyB:bodyA;

         ...


    }
}

如果您确实想使用光线投射,那么我建议保存几个连续的点并用它们制作一个向量,以避免小光线投射。

编辑:抱歉,我写的示例是用 C++ 编写的,但您应该能够找到 Objective-C 的等效项。

Are you drawing a line or a curve? For a line, I assume that you only use the first point and the last point detected. For a curve, you use all the points detected to form the curve that you are drawing.

If you are drawing a curve then think I understand the problem. You are calculating the intersection line using the consecutive points detected by the touch system. These consecutive points are very close to each other which makes very small ray casts, and what might be happening is that you might be casting the line with a starting and ending point inside the balls, which might issue a negative collision.

If the objective is to detect if you are touching the balls, I suggest using a sensor maintained under the touch, and then checking a collision with this code in your update method:

for (b2ContactEdge* ce = sensorbody->GetContactList(); ce; ce = ce->next)
{   
    b2Contact* c = ce->contact;

    if(c->IsTouching())
    {
         const b2Body* bodyA = c->GetFixtureA()->GetBody();
         const b2Body* bodyB = c->GetFixtureB()->GetBody();

         const b2Body* ballBody = (bodyA == sensorbody)?bodyB:bodyA;

         ...


    }
}

If you really want to use a raycast, then I suggest saving a few consecutive points and make a vector with them, to avoid the small ray cast.

edit: Sorry, The example I wrote is in C++, but you should be able to find an equivalent for Objective-C.

尐籹人 2024-12-30 16:53:24

Box2D 的光线投射会忽略它们击中的任何“后”面边缘,因此如果光线在固定装置内开始,则该固定装置将被忽略。最简单的事情就是向两个方向投射相同的光线。

Box2D's raycasts ignore any 'back' facing edges they hit, so if the ray starts inside a fixture, that fixture will be ignored. Simplest thing to do is cast the same ray in both directions.

少女净妖师 2024-12-30 16:53:24

当射线在体内开始时我面临的情况。我用光线投射方法进行爆炸计算,是的,我的爆炸发生在人体内。过了一会儿,我做了下一个丑陋但有效的黑客:

if(i < numRays / 2 && Math.sqrt(
   Math.pow(person.getBody().getPosition().x - ray.p1.x, 2) +
   Math.pow(person.getBody().getPosition().y - ray.p1.y, 2)) < PERSON_RADIUS) {
//apply force to person center, not to raycast intersection point
//1 < numRays / 2 because half or power should go to another direction and not affect person
}

I face situation when ray starts inside body. I worked on explosion calculation with raycasting method, and yes, my explosion happens inside of person. After a while I make next ugly but working hack:

if(i < numRays / 2 && Math.sqrt(
   Math.pow(person.getBody().getPosition().x - ray.p1.x, 2) +
   Math.pow(person.getBody().getPosition().y - ray.p1.y, 2)) < PERSON_RADIUS) {
//apply force to person center, not to raycast intersection point
//1 < numRays / 2 because half or power should go to another direction and not affect person
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文