美文网首页Box学习
Box2d源码分析(刚体)

Box2d源码分析(刚体)

作者: 大旺旺的弟弟小旺旺 | 来源:发表于2021-09-23 07:47 被阅读0次

    概述中知道了什么是世界,如何模拟世界重力,以及时间步和另外两个参数的使用,以及意义。世界的存在,有了物体才可以更加的完美。
    刚体就是世界中的物体,可以仿真各种物体,对世界中物体的操作基本 就是对刚体的操作。
    1.刚体定义
    2.创建并加入到世界中
    3.刚体的形状
    4.显示出刚体的调试视图

    刚体

    a rigid Body,一般的看到的万物的形状都可以看作是刚体,刚体也是学习的核心,可以用来模拟所有的物体,它可以模拟出碰撞、反弹、运动轨迹等各种物体现象模拟和数据都是基于刚体实现的,所以属性比较多,位置、速度、质量、反弹系数等。

    创建刚体

    创建刚体,不仅仅是创建一个刚体,还需要创建bodyDef和fixtureDef,共同创建出来。

    • b2BodyDef:创建需要的信息
    • b2Body:创建刚体
    • b2FixtureDef:创建刚体的信息。
      对于刚体来说,包含的信息比较多以及自身的特性,所以需要创建一个b2BodyDef和b2FixtureDef。所以需要创建这两个,并成功的设置相关的属性。


      image.png
      image.png

      上面只是刚体自身属性和外部属性,我们仍然使用Body来创建。
      创建代码

    BodyDef bodyDef = new BodyDef();
    bodyDef.type = this.type;
    bodyDef.position.set(getX(Align.center),getY(Align.center));
    this.body = Constant.world.createBody(bodyDef);
    if (shape == null){
       PolygonShape polygonShape = new PolygonShape();
       polygonShape.setAsBox(getWidth()/2 , getHeight()/2);
       shape = polygonShape;
    }
    FixtureDef fixtureDef = new FixtureDef();
    fixtureDef.shape = shape;
    if (categoryBits != -1){
      fixtureDef.filter.categoryBits = categoryBits;
    }
    if (maskBits != -1) {
         fixtureDef.filter.maskBits = (short) maskBits;
    }
    fixtureDef.density = 100;
    body.createFixture(fixtureDef);
    shape.dispose();
    body.setUserData(this);
    

    源码分析世界创建body的过程。

    long bodyAddr = 
            jniCreateBody(addr, 
                                def.type.getValue(),
                                def.position.x, 
                                def.position.y, 
                                def.angle, 
                                def.linearVelocity.x,
                                def.linearVelocity.y, 
                                def.angularVelocity, 
                                def.linearDamping, 
                                def.angularDamping, 
                                def.allowSleep, 
                                def.awake,
                                def.fixedRotation, 
                                def.bullet, 
                                def.active, 
                                def.gravityScale);
    Body body = freeBodies.obtain();
    body.reset(bodyAddr);
    this.bodies.put(body.addr, body);
    return body;
    

    reset方法

    protected void reset (long addr) {
        this.addr = addr;
        this.userData = null;
        for (int i = 0; i < fixtures.size; i++)
                this.world.freeFixtures.free(fixtures.get(i));
                fixtures.clear();
                this.joints.clear();
        }
    }
    

    创建body,body有fixturedef和joints以及userData.;将他们清掉。
    这个创建和c++创建有一些区别,等下面补充的时候在加。

    夹具

    fixture的使用,夹具是一个固定设施,用来定义一些属性,材料本身的特性,比如摩擦力、密度、质量等。它可以设置刚体的形状,如果没有形状是不可以进行碰撞模拟的。
    一般的常见图形有园和矩形,还有一些简单的 。对于fixtureDef只是短暂停的存储,它里面有属性fixture,我没让你创建的时候也是将数据在复制到fixture。并且fixtrue必须依附在刚体上才可以有作用,比如你的躯体脱离了你这个人,只是一个行尸走肉,并没有什么用户,一个刚体可以包含不止一个。
    比如一个人,头部的硬度和肚子的硬度反弹系数不同,我们就需要创建两个。也就说刚体创建之后可以对其在增加fixture,实现形状的组合

    FixtureDef fixtureDef = new FixtureDef();
            fixtureDef.shape = shape;
            if (categoryBits != -1){
                fixtureDef.filter.categoryBits = categoryBits;
            }
            if (maskBits != -1) {
                fixtureDef.filter.maskBits = (short) maskBits;
            }
            fixtureDef.density = 100;
            body.createFixture(fixtureDef);
          
    

    源码实现

     public final Fixture createFixture(FixtureDef def) {
        assert (m_world.isLocked() == false);
    
        if (m_world.isLocked() == true) {
          return null;
        }
    
        Fixture fixture = new Fixture();
        fixture.create(this, def);
    
        if ((m_flags & e_activeFlag) == e_activeFlag) {
          BroadPhase broadPhase = m_world.m_contactManager.m_broadPhase;
          fixture.createProxies(broadPhase, m_xf);
        }
    
        fixture.m_next = m_fixtureList;
        m_fixtureList = fixture;
        ++m_fixtureCount;
    
        fixture.m_body = this;
    
        // Adjust mass properties if needed.
        if (fixture.m_density > 0.0f) {
          resetMassData();
        }
    
        // Let the world know we have a new fixture. This will cause new contacts
        // to be created at the beginning of the next time step.
        m_world.m_flags |= World.NEW_FIXTURE;
    
        return fixture;
      }
    

    创建一个 fixture,然后将创建好的fixtureDef传入 进行初始化,然后将其加入到清单中,最后将fixture设置给body对象,将fixture回传。这个时候图形就没有什么作用了,可以进行清楚操作。

    如何理解bodydef和fixturedef

    BodyDef:在创建之前将刚体的属性准备好, 创建的时候将属性值传递给内部的私有属性。数据传递之后,他就没有啥用处了,可以继续使用,重新修改,让下一个继续使用。所以无法使用bodydef来修改属性。需要修改可以通过下面的方法

    body.setActive(xxx);
    body.getTransform().setPosition();
    
    image.png

    bodyDef对应body中的属性修改。对于fixture也是一样的。


    image.png

    我们创建之后需要可以使用上面的方法对属性进行修改。

    形状

    刚体的形状,在世界模拟中,根据形状进行碰撞模拟。我们也了解到刚体的形状可以根据多个fixture进行组合而成,也就是说它们可以加入多个fixture.

    圆形

    圆形创建就很简单了,只有一个参数半径就可以了,默认值是0,这里创建的单位都是米,他和像素的转换关系为 30px = 1m;将创建的图形传给你夹具就是我们创建出刚体的形状。

    矩形

    创建矩形可以使用PolygonShape创建它是一个多边形的类,他没有什么构造函数,但是可以调用相应的函数来返回相应的形状。,比如矩形可使用setAsBox创建。
    sexAsBox的使用以刚体的中心坐标位置为中心点的矩形,及就是宽和高都是i相对于刚体坐标位置对称的,需要传入两个参数宽和高。这里是半宽实际的宽和高是传入的二倍。并且像素和宽高的对应关系
    需要进行转换,比如创建一个60x100的矩形,需要传入的参数是30/30 50/30;

    回顾一下

    创建def,创建body,创建fixture 创建图形 添加fixture.

    看到效果

    打开调试视图,box2d是一个引擎,我们并不可以看到,需要我们打开调试试图,否则就一无所有。
    我们可以使用step进行模拟,在模拟之后调用调试视图得到显示的状态

    相关文章

      网友评论

        本文标题:Box2d源码分析(刚体)

        本文链接:https://www.haomeiwen.com/subject/kbbggltx.html