mirror of
https://github.com/cocos/cocos-engine.git
synced 2026-09-07 00:02:53 +08:00
651 lines
22 KiB
JavaScript
651 lines
22 KiB
JavaScript
|
|
'use strict';
|
|
|
|
const jsbPhy = globalThis['jsb.physics'];
|
|
|
|
jsbPhy['CACHE'] = {
|
|
trimesh: {},
|
|
convex: {},
|
|
height: {},
|
|
material: {},
|
|
};
|
|
|
|
jsbPhy['OBJECT'] = {
|
|
books: [],
|
|
ptrToObj: {},
|
|
raycastOptions: {
|
|
origin: null, unitDir: null,
|
|
distance: 0,
|
|
mask: 0,
|
|
queryTrigger: true,
|
|
},
|
|
};
|
|
|
|
jsbPhy['CONFIG'] = {
|
|
heightScale: 1 / 5000,
|
|
};
|
|
|
|
const books = jsbPhy['OBJECT'].books;
|
|
const ptrToObj = jsbPhy['OBJECT'].ptrToObj;
|
|
const raycastOptions = jsbPhy['OBJECT'].raycastOptions;
|
|
|
|
const TriggerEventObject = {
|
|
type: 'onTriggerEnter',
|
|
selfCollider: null,
|
|
otherCollider: null,
|
|
impl: null,
|
|
};
|
|
|
|
const CollisionEventObject = {
|
|
type: 'onCollisionEnter',
|
|
selfCollider: null,
|
|
otherCollider: null,
|
|
contacts: [],
|
|
impl: null,
|
|
};
|
|
|
|
function emitTriggerEvent (t, c0, c1, impl) {
|
|
TriggerEventObject.type = t;
|
|
TriggerEventObject.impl = impl;
|
|
if (c0.needTriggerEvent) {
|
|
TriggerEventObject.selfCollider = c0;
|
|
TriggerEventObject.otherCollider = c1;
|
|
c0.emit(t, TriggerEventObject);
|
|
}
|
|
if (c1.needTriggerEvent) {
|
|
TriggerEventObject.selfCollider = c1;
|
|
TriggerEventObject.otherCollider = c0;
|
|
c1.emit(t, TriggerEventObject);
|
|
}
|
|
}
|
|
|
|
const quat = new cc.Quat();
|
|
const contactsPool = [];
|
|
const contactBufferElementLength = 12;
|
|
class ContactPoint {
|
|
constructor(e) {
|
|
this.event = e;
|
|
this.impl = null;
|
|
this.colliderA = null;
|
|
this.colliderB = null;
|
|
this.index = 0;
|
|
}
|
|
get isBodyA () { return this.colliderA.uuid === this.event.selfCollider.uuid; }
|
|
getLocalPointOnA (o) {
|
|
this.getWorldPointOnB(o);
|
|
cc.Vec3.subtract(o, o, this.colliderA.node.worldPosition);
|
|
}
|
|
getLocalPointOnB (o) {
|
|
this.getWorldPointOnB(o);
|
|
cc.Vec3.subtract(o, o, this.colliderB.node.worldPosition);
|
|
}
|
|
getWorldPointOnA (o) {
|
|
this.getWorldPointOnB(o);
|
|
}
|
|
getWorldPointOnB (o) {
|
|
const i = this.index * contactBufferElementLength;
|
|
o.x = this.impl[i]; o.y = this.impl[i + 1]; o.z = this.impl[i + 2];
|
|
}
|
|
getLocalNormalOnA (o) {
|
|
this.getWorldNormalOnA(o);
|
|
cc.Quat.conjugate(quat, this.colliderA.node.worldRotation);
|
|
cc.Vec3.transformQuat(o, o, quat);
|
|
}
|
|
getLocalNormalOnB (o) {
|
|
this.getWorldNormalOnB(o);
|
|
cc.Quat.conjugate(quat, this.colliderB.node.worldRotation);
|
|
cc.Vec3.transformQuat(out, out, quat);
|
|
}
|
|
getWorldNormalOnA (o) {
|
|
this.getWorldNormalOnB(o);
|
|
if (!this.isBodyA) cc.Vec3.negate(o, o);
|
|
}
|
|
getWorldNormalOnB (o) {
|
|
const i = this.index * contactBufferElementLength + 3;
|
|
o.x = this.impl[i]; o.y = this.impl[i + 1]; o.z = this.impl[i + 2];
|
|
}
|
|
}
|
|
|
|
function emitCollisionEvent (t, c0, c1, impl, b) {
|
|
CollisionEventObject.type = t;
|
|
CollisionEventObject.impl = impl;
|
|
const contacts = CollisionEventObject.contacts;
|
|
contactsPool.push.apply(contactsPool, contacts);
|
|
contacts.length = 0;
|
|
const contactCount = b.length / contactBufferElementLength;
|
|
for (let i = 0; i < contactCount; i++) {
|
|
let c = contactsPool.length > 0 ? contactsPool.pop() : new ContactPoint(CollisionEventObject);
|
|
c.colliderA = c0; c.colliderB = c1;
|
|
c.impl = b; c.index = i; contacts.push(c);
|
|
}
|
|
if (c0.needCollisionEvent) {
|
|
CollisionEventObject.selfCollider = c0;
|
|
CollisionEventObject.otherCollider = c1;
|
|
c0.emit(t, CollisionEventObject);
|
|
}
|
|
if (c1.needCollisionEvent) {
|
|
CollisionEventObject.selfCollider = c1;
|
|
CollisionEventObject.otherCollider = c0;
|
|
c1.emit(t, CollisionEventObject);
|
|
}
|
|
}
|
|
|
|
class PhysicsWorld {
|
|
get impl () { return this._impl }
|
|
constructor() { this._impl = new jsbPhy.World(); }
|
|
|
|
setGravity (v) {
|
|
this._impl.setGravity(v.x, v.y, v.z);
|
|
}
|
|
|
|
setAllowSleep (v) {
|
|
this._impl.setAllowSleep(v);
|
|
}
|
|
|
|
setDefaultMaterial (v) { }
|
|
|
|
step (f, t, m) {
|
|
// books.forEach((v) => { v.syncToNativeTransform(); });
|
|
this._impl.step(f);
|
|
}
|
|
|
|
raycast (r, o, p, rs) {
|
|
raycastOptions.origin = r.o;
|
|
raycastOptions.unitDir = r.d;
|
|
raycastOptions.mask = o.mask >>> 0;
|
|
raycastOptions.distance = o.maxDistance;
|
|
raycastOptions.queryTrigger = !!o.queryTrigger;
|
|
const isHit = this._impl.raycast(raycastOptions);
|
|
if (isHit) {
|
|
const hits = this._impl.raycastResult();
|
|
for (let i = 0; i < hits.length; i++) {
|
|
const hit = hits[i];
|
|
const out = p.add();
|
|
out._assign(hit.hitPoint, hit.distance, ptrToObj[hit.shape].collider, hit.hitNormal);
|
|
rs.push(out);
|
|
}
|
|
}
|
|
return isHit;
|
|
}
|
|
|
|
raycastClosest (r, o, out) {
|
|
raycastOptions.origin = r.o;
|
|
raycastOptions.unitDir = r.d;
|
|
raycastOptions.mask = o.mask >>> 0;
|
|
raycastOptions.distance = o.maxDistance;
|
|
raycastOptions.queryTrigger = !!o.queryTrigger;
|
|
const isHit = this._impl.raycastClosest(raycastOptions);
|
|
if (isHit) {
|
|
const hit = this._impl.raycastClosestResult();
|
|
out._assign(hit.hitPoint, hit.distance, ptrToObj[hit.shape].collider, hit.hitNormal);
|
|
}
|
|
return isHit;
|
|
}
|
|
|
|
emitEvents () {
|
|
this.emitTriggerEvent();
|
|
this.emitCollisionEvent();
|
|
this._impl.emitEvents();
|
|
}
|
|
|
|
syncSceneToPhysics () {
|
|
this._impl.syncSceneToPhysics();
|
|
}
|
|
|
|
syncAfterEvents () {
|
|
// this._impl.syncSceneToPhysics()
|
|
}
|
|
|
|
destroy () { this._impl.destroy() }
|
|
|
|
emitTriggerEvent () {
|
|
const teps = this._impl.getTriggerEventPairs();
|
|
const len = teps.length / 3;
|
|
for (let i = 0; i < len; i++) {
|
|
const t = i * 3;
|
|
const sa = ptrToObj[teps[t + 0]], sb = ptrToObj[teps[t + 1]];
|
|
if (!sa || !sb) continue;
|
|
const c0 = sa.collider, c1 = sb.collider;
|
|
if (!(c0 && c0.isValid && c1 && c1.isValid)) continue;
|
|
if (!c0.needTriggerEvent && !c1.needTriggerEvent) continue;
|
|
const state = teps[t + 2];
|
|
if (state === 1) {
|
|
emitTriggerEvent('onTriggerStay', c0, c1, teps);
|
|
} else if (state === 0) {
|
|
emitTriggerEvent('onTriggerEnter', c0, c1, teps);
|
|
} else {
|
|
emitTriggerEvent('onTriggerExit', c0, c1, teps);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
emitCollisionEvent () {
|
|
const ceps = this._impl.getContactEventPairs();
|
|
const len2 = ceps.length / 4;
|
|
for (let i = 0; i < len2; i++) {
|
|
const t = i * 4;
|
|
const sa = ptrToObj[ceps[t + 0]], sb = ptrToObj[ceps[t + 1]];
|
|
if (!sa || !sb) continue;
|
|
const c0 = sa.collider, c1 = sb.collider;
|
|
if (!(c0 && c0.isValid && c1 && c1.isValid)) continue;
|
|
if (!c0.needCollisionEvent && !c1.needCollisionEvent) continue;
|
|
const state = ceps[t + 2];
|
|
if (state === 1) {
|
|
emitCollisionEvent('onCollisionStay', c0, c1, ceps, ceps[t + 3]);
|
|
} else if (state === 0) {
|
|
emitCollisionEvent('onCollisionEnter', c0, c1, ceps, ceps[t + 3]);
|
|
} else {
|
|
emitCollisionEvent('onCollisionExit', c0, c1, ceps, ceps[t + 3]);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
function bookNode (v) {
|
|
if (v._physicsBookIndex === undefined) {
|
|
v._physicsBookIndex = books.length;
|
|
books.push(v);
|
|
}
|
|
}
|
|
|
|
function unBookNode (v) {
|
|
const index = v._physicsBookIndex;
|
|
if (index !== undefined) {
|
|
books[index] = books[books.length - 1];
|
|
books[index]._physicsBookIndex = index;
|
|
books.length -= 1;
|
|
v._physicsBookIndex = undefined;
|
|
}
|
|
}
|
|
|
|
function updateCollisionMatrix () {
|
|
const phy = cc.PhysicsSystem.instance;
|
|
const world = phy.physicsWorld.impl;
|
|
const cm = phy.collisionMatrix;
|
|
if (cm.updateArray && cm.updateArray.length > 0) {
|
|
cm.updateArray.forEach((e) => {
|
|
const key = `${1 << e}`;
|
|
const mask = cm[key];
|
|
world.setCollisionMatrix(e, mask);
|
|
});
|
|
cm.updateArray.length = 0;
|
|
}
|
|
}
|
|
|
|
class RigidBody {
|
|
get impl () { return this._impl }
|
|
get rigidBody () { return this._com }
|
|
get isAwake () { return this._impl.isAwake(); }
|
|
get isSleepy () { return false }
|
|
get isSleeping () { return this._impl.isSleeping(); }
|
|
constructor() {
|
|
updateCollisionMatrix();
|
|
this._impl = new jsbPhy.RigidBody();
|
|
this._isUsingCCD = false;
|
|
}
|
|
|
|
initialize (v) {
|
|
v.node.updateWorldTransform();
|
|
this._com = v;
|
|
this._impl.initialize(v.node.native, v.type, v._group);
|
|
bookNode(v.node);
|
|
}
|
|
|
|
onEnable () {
|
|
this.setType(this._com.type);
|
|
this.setMass(this._com.mass);
|
|
this.setAllowSleep(this._com.allowSleep);
|
|
this.setLinearDamping(this._com.linearDamping);
|
|
this.setAngularDamping(this._com.angularDamping);
|
|
this.setLinearFactor(this._com.linearFactor);
|
|
this.setAngularFactor(this._com.angularFactor);
|
|
this.useGravity(this._com.useGravity);
|
|
this._impl.onEnable();
|
|
}
|
|
|
|
onDisable () { this._impl.onDisable(); }
|
|
|
|
onDestroy () {
|
|
unBookNode(this._com.node);
|
|
this._impl.onDestroy();
|
|
}
|
|
|
|
setGroup (v) { this._impl.setGroup(v); }
|
|
getGroup () { return this._impl.getGroup(); }
|
|
addGroup (v) { this.setGroup(this.getGroup() | v); }
|
|
removeGroup (v) { this.setGroup(this.getGroup() & ~v); }
|
|
setMask (v) { this._impl.setMask(v>>>0); }
|
|
getMask () { return this._impl.getMask(); }
|
|
addMask (v) { this.setMask(this.getMask() | v); }
|
|
removeMask (v) { this.setMask(this.getMask() & ~v); }
|
|
|
|
setType (v) { this._impl.setType(v); }
|
|
setMass (v) { this._impl.setMass(v); }
|
|
setAllowSleep (v) { this._impl.setAllowSleep(v); }
|
|
setLinearDamping (v) {
|
|
const dt = cc.PhysicsSystem.instance.fixedTimeStep;
|
|
this._impl.setLinearDamping((1 - (1 - v) ** dt) / dt);
|
|
}
|
|
setAngularDamping (v) {
|
|
const dt = cc.PhysicsSystem.instance.fixedTimeStep;
|
|
this._impl.setAngularDamping((1 - (1 - v) ** dt) / dt);
|
|
}
|
|
isUsingCCD () { return this._isUsingCCD; }
|
|
useCCD (v) {
|
|
this._isUsingCCD = v;
|
|
return this._impl.useCCD(v);
|
|
}
|
|
useGravity (v) { this._impl.useGravity(v); }
|
|
setLinearFactor (v) { this._impl.setLinearFactor(v.x, v.y, v.z); }
|
|
setAngularFactor (v) { this._impl.setAngularFactor(v.x, v.y, v.z); }
|
|
wakeUp () { this._impl.wakeUp(); }
|
|
sleep () { this._impl.sleep(); }
|
|
clearState () { this._impl.clearState(); }
|
|
clearForces () { this._impl.clearForces(); }
|
|
clearVelocity () { this._impl.clearVelocity(); }
|
|
setSleepThreshold (v) { this._impl.setSleepThreshold(v); }
|
|
getSleepThreshold () { return this._impl.getSleepThreshold(); }
|
|
getLinearVelocity (o) { o.set(this._impl.getLinearVelocity()); }
|
|
setLinearVelocity (v) { this._impl.setLinearVelocity(v.x, v.y, v.z); }
|
|
getAngularVelocity (o) { o.set(this._impl.getAngularVelocity()); }
|
|
setAngularVelocity (v) { this._impl.setAngularVelocity(v.x, v.y, v.z); }
|
|
applyForce (f, p) { if (p == null) { p = cc.Vec3.ZERO; } this._impl.applyForce(f.x, f.y, f.z, p.x, p.y, p.z); }
|
|
applyLocalForce (f, p) { if (p == null) { p = cc.Vec3.ZERO; } this._impl.applyLocalForce(f.x, f.y, f.z, p.x, p.y, p.z); }
|
|
applyImpulse (f, p) { if (p == null) { p = cc.Vec3.ZERO; } this._impl.applyImpulse(f.x, f.y, f.z, p.x, p.y, p.z); }
|
|
applyLocalImpulse (f, p) { if (p == null) { p = cc.Vec3.ZERO; } this._impl.applyLocalImpulse(f.x, f.y, f.z, p.x, p.y, p.z); }
|
|
applyTorque (t) { this._impl.applyTorque(t.x, t.y, t.z); }
|
|
applyLocalTorque (t) { this._impl.applyLocalTorque(t.x, t.y, t.z); }
|
|
}
|
|
|
|
const ESHAPE_FLAG = {
|
|
NONE: 0,
|
|
QUERY_FILTER: 1 << 0,
|
|
QUERY_SINGLE_HIT: 1 << 2,
|
|
DETECT_TRIGGER_EVENT: 1 << 3,
|
|
DETECT_CONTACT_EVENT: 1 << 4,
|
|
DETECT_CONTACT_POINT: 1 << 5,
|
|
DETECT_CONTACT_CCD: 1 << 6,
|
|
}
|
|
|
|
class Shape {
|
|
get impl () { return this._impl; }
|
|
get collider () { return this._com; }
|
|
get attachedRigidBody () { return this._attachedRigidBody; }
|
|
constructor() { updateCollisionMatrix(); };
|
|
initialize (v) {
|
|
v.node.updateWorldTransform();
|
|
this._com = v;
|
|
this._impl.initialize(v.node.native);
|
|
ptrToObj[this._impl.getImpl()] = this;
|
|
bookNode(v.node);
|
|
}
|
|
onLoad () {
|
|
this.setMaterial(this._com.sharedMaterial);
|
|
this.setCenter(this._com.center);
|
|
this.setAsTrigger(this._com.isTrigger);
|
|
}
|
|
onEnable () { this._impl.onEnable(); }
|
|
onDisable () { this._impl.onDisable(); }
|
|
onDestroy () {
|
|
unBookNode(this._com.node);
|
|
ptrToObj[this._impl.getImpl()] = null
|
|
delete ptrToObj[this._impl.getImpl()];
|
|
this._impl.onDestroy();
|
|
}
|
|
setMaterial (v) {
|
|
const ins = cc.PhysicsSystem.instance;
|
|
if (!v) v = ins.defaultMaterial;
|
|
if (!jsbPhy['CACHE'].material[v.id]) {
|
|
jsbPhy['CACHE'].material[v.id] = ins.physicsWorld.impl.createMaterial(v.id, v.friction, v.friction, v.restitution, 2, 2);
|
|
}
|
|
this._impl.setMaterial(v.id, v.friction, v.friction, v.restitution, 2, 2);
|
|
}
|
|
setAsTrigger (v) { this._impl.setAsTrigger(v); }
|
|
setCenter (v) { this._impl.setCenter(v.x, v.y, v.z); }
|
|
getAABB(v) { v.copy(this._impl.getAABB());}
|
|
getBoundingSphere (v) { v.copy(this._impl.getBoundingSphere());}
|
|
updateEventListener () {
|
|
var flag = 0;
|
|
flag |= ESHAPE_FLAG.DETECT_CONTACT_CCD;
|
|
if (this._com.isTrigger) flag |= ESHAPE_FLAG.IS_TRIGGER;
|
|
if (this._com.needTriggerEvent || this._com.needCollisionEvent) flag |= ESHAPE_FLAG.NEED_EVENT;
|
|
this._impl.updateEventListener(flag);
|
|
}
|
|
setGroup (v) { this._impl.setGroup(v); }
|
|
getGroup () { return this._impl.getGroup(); }
|
|
addGroup (v) { this.setGroup(this.getGroup() | v); }
|
|
removeGroup (v) { this.setGroup(this.getGroup() & ~v); }
|
|
setMask (v) { this._impl.setMask(v>>>0); }
|
|
getMask () { return this._impl.getMask(); }
|
|
addMask (v) { this.setMask(this.getMask() | v); }
|
|
removeMask (v) { this.setMask(this.getMask() & ~v); }
|
|
}
|
|
|
|
class SphereShape extends Shape {
|
|
constructor() { super(); this._impl = new jsbPhy.SphereShape(); }
|
|
updateRadius () { this._impl.setRadius(this.collider.radius); }
|
|
onLoad () {
|
|
super.onLoad();
|
|
this.updateRadius();
|
|
}
|
|
}
|
|
|
|
class BoxShape extends Shape {
|
|
constructor() { super(); this._impl = new jsbPhy.BoxShape(); }
|
|
updateSize () {
|
|
const v = this.collider.size;
|
|
this._impl.setSize(v.x, v.y, v.z);
|
|
}
|
|
onLoad () {
|
|
super.onLoad();
|
|
this.updateSize();
|
|
}
|
|
}
|
|
|
|
class CapsuleShape extends Shape {
|
|
constructor() { super(); this._impl = new jsbPhy.CapsuleShape(); }
|
|
setRadius (v) { this._impl.setRadius(v); }
|
|
setDirection (v) { this._impl.setDirection(v); }
|
|
setCylinderHeight (v) { this._impl.setCylinderHeight(v); }
|
|
onLoad () {
|
|
super.onLoad();
|
|
this.setRadius(this._com.radius);
|
|
this.setDirection(this._com.direction);
|
|
this.setCylinderHeight(this._com.cylinderHeight);
|
|
}
|
|
}
|
|
|
|
class PlaneShape extends Shape {
|
|
constructor() { super(); this._impl = new jsbPhy.PlaneShape(); }
|
|
setConstant (v) { this._impl.setConstant(v); }
|
|
setNormal (v) { this._impl.setNormal(v.x, v.y, v.z); }
|
|
onLoad () {
|
|
super.onLoad();
|
|
this.setNormal(this._com.normal);
|
|
this.setConstant(this._com.constant);
|
|
}
|
|
}
|
|
|
|
function getConvexMesh (v) {
|
|
if (!jsbPhy.CACHE.convex[v._uuid]) {
|
|
const posArr = cc.physics.utils.shrinkPositions(v.readAttribute(0, 'a_position'));
|
|
const world = cc.PhysicsSystem.instance.physicsWorld.impl;
|
|
const convex = { positions: new Float32Array(posArr), positionLength: posArr.length / 3 }
|
|
jsbPhy.CACHE.convex[v._uuid] = world.createConvex(convex);
|
|
}
|
|
return jsbPhy.CACHE.convex[v._uuid];
|
|
}
|
|
|
|
function getTriangleMesh (v) {
|
|
if (!jsbPhy.CACHE.trimesh[v._uuid]) {
|
|
const indArr = v.readIndices(0);
|
|
// const posArr = cc.physics.utils.shrinkPositions(v.readAttribute(0, 'a_position'));
|
|
const posArr = v.readAttribute(0, 'a_position');
|
|
const world = cc.PhysicsSystem.instance.physicsWorld.impl;
|
|
const trimesh = {
|
|
positions: new Float32Array(posArr), positionLength: posArr.length / 3,
|
|
triangles: new Uint16Array(indArr), triangleLength: indArr.length / 3,
|
|
isU16: true,
|
|
}
|
|
jsbPhy.CACHE.trimesh[v._uuid] = world.createTrimesh(trimesh);
|
|
}
|
|
return jsbPhy.CACHE.trimesh[v._uuid];
|
|
}
|
|
|
|
function getHeightField (v) {
|
|
if (!jsbPhy.CACHE.height[v._uuid]) {
|
|
const rows = v.getVertexCountI();
|
|
const columns = v.getVertexCountJ();
|
|
const samples = new Int16Array(rows * columns);
|
|
const heightScale = jsbPhy['CONFIG'].heightScale;
|
|
for (let i = 0; i < rows; i++) {
|
|
for (let j = 0; j < columns; j++) {
|
|
samples[j + i * columns] = v.getHeight(i, j) / heightScale;
|
|
}
|
|
}
|
|
const height = { rows, columns, samples };
|
|
const world = cc.PhysicsSystem.instance.physicsWorld.impl;
|
|
jsbPhy.CACHE.height[v._uuid] = world.createHeightField(height);
|
|
}
|
|
return jsbPhy.CACHE.height[v._uuid];
|
|
}
|
|
|
|
class CylinderShape extends Shape {
|
|
constructor() { super(); this._impl = new jsbPhy.CylinderShape(); }
|
|
setRadius (v) { this.updateGeometry() }
|
|
setDirection (v) { this.updateGeometry() }
|
|
setHeight (v) { this.updateGeometry() }
|
|
updateGeometry () { this._impl.setCylinder(this._com.radius, this._com.height, this._com.direction); }
|
|
initialize (v) {
|
|
if (!jsbPhy.CACHE.convex["CYLINDER"]) {
|
|
const primitive = cc.physics.utils.cylinder(0.5, 0.5, 2, { radialSegments: 32, heightSegments: 1 });
|
|
const posArr = cc.physics.utils.shrinkPositions(primitive.positions);
|
|
const convex = { positions: new Float32Array(posArr), positionLength: posArr.length / 3 };
|
|
const handle = cc.PhysicsSystem.instance.physicsWorld.impl.createConvex(convex);
|
|
jsbPhy.CACHE.convex["CYLINDER"] = handle;
|
|
}
|
|
this._com = v;
|
|
this._impl.setCylinder(v.radius, v.height, v.direction);
|
|
this._impl.setConvex(jsbPhy.CACHE.convex["CYLINDER"]);
|
|
super.initialize(v);
|
|
}
|
|
}
|
|
|
|
class ConeShape extends Shape {
|
|
constructor() { super(); this._impl = new jsbPhy.ConeShape(); }
|
|
setRadius (v) { this.updateGeometry() }
|
|
setDirection (v) { this.updateGeometry() }
|
|
setHeight (v) { this.updateGeometry() }
|
|
updateGeometry () { this._impl.setCone(this._com.radius, this._com.height, this._com.direction); }
|
|
initialize (v) {
|
|
if (!jsbPhy.CACHE.convex["CONE"]) {
|
|
const primitive = cc.physics.utils.cylinder(0, 0.5, 1, { radialSegments: 32, heightSegments: 1 });
|
|
const posArr = cc.physics.utils.shrinkPositions(primitive.positions);
|
|
const convex = { positions: new Float32Array(posArr), positionLength: posArr.length / 3 };
|
|
const handle = cc.PhysicsSystem.instance.physicsWorld.impl.createConvex(convex);
|
|
jsbPhy.CACHE.convex["CONE"] = handle;
|
|
}
|
|
this._com = v;
|
|
this._impl.setCone(v.radius, v.height, v.direction);
|
|
this._impl.setConvex(jsbPhy.CACHE.convex["CONE"]);
|
|
super.initialize(v);
|
|
}
|
|
}
|
|
|
|
class TrimeshShape extends Shape {
|
|
constructor() { super(); this._impl = new jsbPhy.TrimeshShape(); }
|
|
setConvex (v) { this._impl.useConvex(v); }
|
|
setMesh (v) {
|
|
if (!v) return;
|
|
const isConvex = this._com.convex;
|
|
this._impl.useConvex(isConvex);
|
|
const handle = isConvex ? getConvexMesh(v) : getTriangleMesh(v);
|
|
this._impl.setMesh(handle);
|
|
}
|
|
initialize (v) {
|
|
this._com = v;
|
|
this.setConvex(v.convex);
|
|
this.setMesh(v.mesh);
|
|
super.initialize(v);
|
|
}
|
|
}
|
|
|
|
class TerrainShape extends Shape {
|
|
constructor() { super(); this._impl = new jsbPhy.TerrainShape(); }
|
|
setTerrain (v) {
|
|
if (!v) return;
|
|
const handle = getHeightField(v);
|
|
this._impl.setTerrain(handle, v.tileSize, v.tileSize, jsbPhy['CONFIG'].heightScale);
|
|
}
|
|
initialize (v) {
|
|
this._com = v;
|
|
this.setTerrain(v.terrain);
|
|
super.initialize(v);
|
|
}
|
|
}
|
|
|
|
class Joint {
|
|
get impl () { return this._impl; }
|
|
get joint () { return this._com; }
|
|
setEnableCollision (v) { this._impl.setEnableCollision(v); }
|
|
setConnectedBody (v) { this._impl.setConnectedBody(v ? v.body.impl.getNodeHandle() : 0); }
|
|
initialize (v) {
|
|
this._com = v;
|
|
this._impl.initialize(v.node.native);
|
|
ptrToObj[this._impl.getImpl()] = this;
|
|
this.onLoad();
|
|
}
|
|
onLoad () {
|
|
this.setConnectedBody(this._com.connectedBody);
|
|
this.setEnableCollision(this._com.enableCollision);
|
|
}
|
|
onEnable () { this._impl.onEnable(); }
|
|
onDisable () { this._impl.onDisable(); }
|
|
onDestroy () {
|
|
ptrToObj[this._impl.getImpl()] = null
|
|
delete ptrToObj[this._impl.getImpl()];
|
|
this._impl.onDestroy();
|
|
}
|
|
}
|
|
|
|
class DistanceJoint extends Joint {
|
|
constructor() { super(); this._impl = new jsbPhy.DistanceJoint(); }
|
|
setPivotA (v) { this._impl.setPivotA(v.x, v.y, v.z); }
|
|
setPivotB (v) { this._impl.setPivotB(v.x, v.y, v.z); }
|
|
onLoad () {
|
|
super.onLoad();
|
|
this.setPivotA(this._com.pivotA);
|
|
this.setPivotB(this._com.pivotB);
|
|
}
|
|
}
|
|
|
|
class RevoluteJoint extends Joint {
|
|
constructor() { super(); this._impl = new jsbPhy.RevoluteJoint(); }
|
|
setAxis (v) { this._impl.setAxis(v.x, v.y, v.z); }
|
|
setPivotA (v) { this._impl.setPivotA(v.x, v.y, v.z); }
|
|
setPivotB (v) { this._impl.setPivotB(v.x, v.y, v.z); }
|
|
onLoad () {
|
|
super.onLoad();
|
|
this.setAxis(this._com.axis);
|
|
this.setPivotA(this._com.pivotA);
|
|
this.setPivotB(this._com.pivotB);
|
|
}
|
|
}
|
|
|
|
cc.physics.selector.register("physx", {
|
|
PhysicsWorld: PhysicsWorld,
|
|
RigidBody: RigidBody,
|
|
SphereShape: SphereShape,
|
|
BoxShape: BoxShape,
|
|
PlaneShape: PlaneShape,
|
|
CapsuleShape: CapsuleShape,
|
|
ConeShape: ConeShape,
|
|
CylinderShape: CylinderShape,
|
|
TrimeshShape: TrimeshShape,
|
|
TerrainShape: TerrainShape,
|
|
PointToPointConstraint: DistanceJoint,
|
|
HingeConstraint: RevoluteJoint,
|
|
});
|