World类

作者: 大旺旺的弟弟小旺旺 | 来源:发表于2021-10-21 18:47 被阅读0次

    世界类的创建过程

    world = new World(new Vector2(0, -120), true);
    

    重力方向向下,所以为负数,是否可以睡眠,对于所有的动态刚体来说,当不发进行碰撞模拟的时候就进入睡眠状态。

    在创建世界的过程中实际使用的代码为:

    World world = new World(new Vec2(0,0));
    world.setAllowSleep(flag);
    

    对于world.setAllowSleep(flag);它会遍历所有的body,然后将其设置为flag,

    扩展:

    对于刚体创建出来,会放到世界刚体链表的头部,

    new World(new Vec2(0,0));创建它会初始化实体,初始化动态树,还有成员变量的初始化。

      public World(Vec2 gravity, IWorldPool pool, BroadPhase broadPhase) {
        this.pool = pool;
        m_destructionListener = null;
        m_debugDraw = null;
    
        m_bodyList = null;
        m_jointList = null;
    
        m_bodyCount = 0;
        m_jointCount = 0;
    
        m_warmStarting = true;
        m_continuousPhysics = true;
        m_subStepping = false;
        m_stepComplete = true;
    
        m_allowSleep = true;
        m_gravity.set(gravity);
    
        m_flags = CLEAR_FORCES;
    
        m_inv_dt0 = 0f;
    
        m_contactManager = new ContactManager(this, broadPhase);
        m_profile = new Profile();
    
        m_particleSystem = new ParticleSystem(this);
    
        initializeRegisters();
      }
    

    先理清思路,在对里面的作用分开说。

    initializeRegisters()

    使用那种方式创建图形
    1.使用cir属性绘制圆
    2.使用polygon绘制等
    
    private void initializeRegisters() {
      addType(pool.getCircleContactStack(), ShapeType.CIRCLE, ShapeType.CIRCLE);
      addType(pool.getPolyCircleContactStack(), ShapeType.POLYGON, ShapeType.CIRCLE);
      addType(pool.getPolyContactStack(), ShapeType.POLYGON, ShapeType.POLYGON);
      addType(pool.getEdgeCircleContactStack(), ShapeType.EDGE, ShapeType.CIRCLE);
      addType(pool.getEdgePolyContactStack(), ShapeType.EDGE, ShapeType.POLYGON);
      addType(pool.getChainCircleContactStack(), ShapeType.CHAIN, ShapeType.CIRCLE);
      addType(pool.getChainPolyContactStack(), ShapeType.CHAIN, ShapeType.POLYGON);
    }
    

    他们各种组合都放起来。

    private void addType(IDynamicStack<Contact> creator, ShapeType type1, ShapeType type2) {
      ContactRegister register = new ContactRegister();
      register.creator = creator;
      register.primary = true;
      contactStacks[type1.ordinal()][type2.ordinal()] = register;
    
      if (type1 != type2) {
        ContactRegister register2 = new ContactRegister();
        register2.creator = creator;
        register2.primary = false;
        contactStacks[type2.ordinal()][type1.ordinal()] = register2;
      }
    }
    

    后面在进行刚体范围比较的时候,会根据相应的图形来使用不同的检测方式。比如下面这个两个:

    • 第一个案例
    final ContactRegister reg = contactStacks[type1.ordinal()][type2.ordinal()];
    if (reg != null) {
      if (reg.primary) {
        Contact c = reg.creator.pop();
        c.init(fixtureA, indexA, fixtureB, indexB);
        return c;
      } else {
        Contact c = reg.creator.pop();
        c.init(fixtureB, indexB, fixtureA, indexA);
        return c;
      }
    }
    
    • 第二个案例
      public void pushContact(Contact contact) {
        Fixture fixtureA = contact.getFixtureA();
        Fixture fixtureB = contact.getFixtureB();
    
        if (contact.m_manifold.pointCount > 0 && !fixtureA.isSensor() && !fixtureB.isSensor()) {
          fixtureA.getBody().setAwake(true);
          fixtureB.getBody().setAwake(true);
        }
    
        ShapeType type1 = fixtureA.getType();
        ShapeType type2 = fixtureB.getType();
    
        IDynamicStack<Contact> creator = contactStacks[type1.ordinal()][type2.ordinal()].creator;
        creator.push(contact);
      }
    

    createBody

    第一个创建类方法,使用它创建刚体,创建需要一个参数,BodyDef,它可以设置刚体的特性,它是运动的还是静态的。

    userData = null;    //用户数据,比如创建一个地球,可以吧地球类存储在刚体里面
    position = new Vec2();    //位置
    angle = 0f;     //角度   后面改需要通过transform方法改
    linearVelocity = new Vec2();  //线性速度
    angularVelocity = 0f;   //角速度
    linearDamping = 0f;  //线性阻尼
    angularDamping = 0f;   //角速度阻尼
    allowSleep = true;   //是不是运行睡眠 
    awake = true;  //
    fixedRotation = false;  //是不是运行自身转动,比如装了之后会翻转
    bullet = false;  //子弹特性(慎用)
    type = BodyType.STATIC;   //类型 
    active = true;  //是不是活跃,不活跃将不会模拟   静态将不会模拟
    gravityScale = 1.0f;   //重力缩放
    

    刚体创建过程

     public Body(final BodyDef bd, World world) {
        assert (bd.position.isValid());
        assert (bd.linearVelocity.isValid());
        assert (bd.gravityScale >= 0.0f);
        assert (bd.angularDamping >= 0.0f);
        assert (bd.linearDamping >= 0.0f);
    
        m_flags = 0;
    
        if (bd.bullet) {
          m_flags |= e_bulletFlag;
        }
        if (bd.fixedRotation) {
          m_flags |= e_fixedRotationFlag;
        }
        if (bd.allowSleep) {
          m_flags |= e_autoSleepFlag;
        }
        if (bd.awake) {
          m_flags |= e_awakeFlag;
        }
        if (bd.active) {
          m_flags |= e_activeFlag;
        }
    
        m_world = world;
        //位置
        m_xf.p.set(bd.position);
        //角度
        m_xf.q.set(bd.angle);
        //中心
        m_sweep.localCenter.setZero();
        // 位置 (copy)
        m_sweep.c0.set(m_xf.p);
        m_sweep.c.set(m_xf.p);
        // 角度copy
        m_sweep.a0 = bd.angle;
        m_sweep.a = bd.angle;
        m_sweep.alpha0 = 0.0f;
    
        m_jointList = null;
        m_contactList = null;
        m_prev = null;
        m_next = null;
    
        m_linearVelocity.set(bd.linearVelocity);
        m_angularVelocity = bd.angularVelocity;
    
        m_linearDamping = bd.linearDamping;
        m_angularDamping = bd.angularDamping;
        m_gravityScale = bd.gravityScale;
    
        m_force.setZero();
        m_torque = 0.0f;
    
        m_sleepTime = 0.0f;
    
        m_type = bd.type;
    
        if (m_type == BodyType.DYNAMIC) {
          m_mass = 1f;
          m_invMass = 1f;
        } else {
          m_mass = 0f;
          m_invMass = 0f;
        }
    
        m_I = 0.0f;
        m_invI = 0.0f;
    
        m_userData = bd.userData;
    
        m_fixtureList = null;
        m_fixtureCount = 0;
      }
    

    创建一个刚体就将里面的参数进行一次初始化。

    创建夹具

    FixtureDef属性:

    shape = null;
    userData = null;
    friction = 0.2f;
    restitution = 0f;
    density = 0f;
    filter = new Filter();
    isSensor = false;
    

    创建过程,从fixtureDef进行一次数据的复制

    //值的一次复制
    m_userData = def.userData;
    m_friction = def.friction;
    m_restitution = def.restitution;
    m_body = body;
    m_next = null;
    m_filter.set(def.filter);
    m_isSensor = def.isSensor;
    m_shape = def.shape.clone();
    // Reserve proxy space
    //代理空间
    int childCount = m_shape.getChildCount();
    if (m_proxies == null) {
        m_proxies = new FixtureProxy[childCount];
        for (int i = 0; i < childCount; i++) {
            m_proxies[i] = new FixtureProxy();
            m_proxies[i].fixture = null;
            m_proxies[i].proxyId = BroadPhase.NULL_PROXY;
        }
    }
    
    if (m_proxies.length < childCount) {
        FixtureProxy[] old = m_proxies;
        int newLen = MathUtils.max(old.length * 2, childCount);
        m_proxies = new FixtureProxy[newLen];
        System.arraycopy(old, 0, m_proxies, 0, old.length);
        for (int i = 0; i < newLen; i++) {
            if (i >= old.length) {
                m_proxies[i] = new FixtureProxy();
            }
            m_proxies[i].fixture = null;
            m_proxies[i].proxyId = BroadPhase.NULL_PROXY;
        }
    }
    m_proxyCount = 0;
    m_density = def.density;
    

    Body中的create方法

      / * 创建之后  将其加入到树中间
       * 根据其 对质量进行重新计算
       */
      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;
      }
    

    setTransform方法

    重新设置位置和角度

    public final void setTransform (b2Vec2 position, float angle) {
        assert (m_world.isLocked() == false);
        if (m_world.isLocked() == true) {
            return;
        }
    
        m_xf.q.set(angle);
        m_xf.p.set(position);
    
        // m_sweep.c0 = m_sweep.c = Mul(m_xf, m_sweep.localCenter);
        b2Transform.mulToOutUnsafe(m_xf, m_sweep.localCenter, m_sweep.c);
        m_sweep.a = angle;
    
        m_sweep.c0.set(m_sweep.c);
        m_sweep.a0 = m_sweep.a;
    
        b2BroadPhase broadPhase = m_world.m_contactManager.m_broadPhase;
        for (b2Fixture f : m_fixtureList) {
            f.synchronize(broadPhase, m_xf, m_xf);
        }
    }
    

    重新设置位置之后,就重新分配树的结构,以及lower和upper。

    设置线速度 角速度 力

    暂且认为是存储一个变量。

    • 线速度
    public final void setLinearVelocity (b2Vec2 v) {
        if (m_type == b2BodyType.STATIC) {
            return;
        }
    
        if (b2Vec2.dot(v, v) > 0.0f) {
            setAwake(true);
        }
    
        m_linearVelocity.set(v);
    }
    
    • 角速度
    public final void setAngularVelocity (float w) {
        if (m_type == b2BodyType.STATIC) {
            return;
        }
    
        if (w * w > 0f) {
            setAwake(true);
        }
    
        m_angularVelocity = w;
    }
    
    public final void applyForce (b2Vec2 force, b2Vec2 point, boolean wake) {
        if (m_type != b2BodyType.DYNAMIC) {
            return;
        }
    
        if (isAwake() == false) {
            setAwake(true);
        }
    
        // m_force.addLocal(force);
        // Vec2 temp = tltemp.get();
        // temp.set(point).subLocal(m_sweep.c);
        // m_torque += Vec2.cross(temp, force);
    
        m_force.x += force.x;
        m_force.y += force.y;
        // m_sweep就是它的位置
        m_torque += (point.x - m_sweep.c.x) * force.y - (point.y - m_sweep.c.y) * force.x;
    }
    //力不在中心就会有一个旋转
    

    在中心加力 就不会有扭转力

    public final void applyForceToCenter (b2Vec2 force, boolean wake) {
        if (m_type != b2BodyType.DYNAMIC) {
            return;
        }
    
        if (isAwake() == false) {
            setAwake(true);
        }
    
        m_force.x += force.x;
        m_force.y += force.y;
    }
    

    为什么设置了就设置睡眠,可能是因为位置发生变化,已经没啥用了, 设置不活跃,下次模拟的时候在进行模拟。

    相关文章

      网友评论

        本文标题:World类

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