世界类的创建过程
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;
}
为什么设置了就设置睡眠,可能是因为位置发生变化,已经没啥用了, 设置不活跃,下次模拟的时候在进行模拟。
网友评论