衝突を検出することはできますが、オブジェクトのエッジを互いにスナップしてオーバーラップを防ぐなどのスナップ/磁気効果を実装できませんでした 。ここでは 3D オブジェクトの助けが必要であり、アクティブなオブジェクトの位置に Vec3 を使用しています。
次のアプローチでは、衝突検出はすべてのケースで完全に機能し、磁気効果は何らかの形で機能しますが、完全ではありません。オブジェクトが x 軸または z 軸に沿って移動している場合はうまく機能しますが、オブジェクトの移動が斜め方向 (x 軸と z 軸に沿って同時に移動している) の場合は問題が発生します。
次のアプローチには満足していませんが、磁気検出機能と衝突検出機能の両方を実装する新しいアプローチを探しているのはそのためです。Threejs でソリューションを使用する必要はありません。座標の一般的なソリューションまたはアルゴリズムを Threejs に変換できます。
let collide = this.detectCollisionCubes(activeObject, collidingObject, vec3);
let magneticEffect = new MagneticEffect(activeObject, vec3, collidingObject);
vec3 = magneticEffect.setNewPosition();
activeObject.position.copy(vec3);
detectCollisionCubes = function(a, d, vec3){
// a is active object's positon
// d is colliding object
let aHeight = Math.abs(a.getHeight());
let aWidth = Math.abs(a.getWidth());
let aDepth = Math.abs(a.getDepth());
let b1 = vec3.y - aHeight / 2;
let t1 = vec3.y + aHeight / 2;
let r1 = vec3.x + aWidth / 2;
let l1 = vec3.x - aWidth / 2;
let f1 = vec3.z - aDepth / 2;
let B1 = vec3.z + aDepth / 2;
let dHeight = Math.abs(d.getHeight());
let dWidth = Math.abs(d.getWidth());
let dDepth = Math.abs(d.getDepth());
let b2 = d.position.y - dHeight / 2;
let t2 = d.position.y + dHeight / 2;
let r2 = d.position.x + dWidth / 2;
let l2 = d.position.x - dWidth / 2;
let f2 = d.position.z - dDepth / 2;
let B2 = d.position.z + dDepth / 2;
if (t1 < b2 || r1 < l2 || b1 > t2 || l1 > r2 || f1 > B2 || B1 < f2) {
return false;
}
return true;
}
経由で磁気効果を作成しようとしています
this.currentObject = currentObject;
this.collisionObject = collisionObject;
this.collisionType = null;
this.objectType = null;
this.currentPosition = currentPosition;
this.currentObjectHeight = Math.abs(currentObject.getHeight());
this.currentObjectWidth = Math.abs(currentObject.getWidth());
this.collisionObjectHeight = Math.abs(collisionObject.getHeight());
this.collisionObjectWidth = Math.abs(collisionObject.getWidth());
this.collisionObjectDepth = Math.abs(collisionObject.getDepth());
this.objectTop = currentObject.position.y + (this.currentObjectHeight/2);
this.objectBottom = currentObject.position.y - (this.currentObjectHeight/2);
this.collideTop = collisionObject.position.y + (this.collisionObjectHeight/2);
this.collideBottom = collisionObject.position.y - (this.collisionObjectHeight/2);
this.zAxisDifference = Math.abs(Math.abs(currentPosition.z) - Math.abs(collisionObject.position.z));
this.xAxisDifference = Math.abs(Math.abs(currentPosition.x) - Math.abs(collisionObject.position.x));
// Extra code here
if (
this.objectTop < this.collideBottom
) {
this.collisionType = collisionTypes.verticalBottom;
} else if (
this.objectBottom > this.collideTop
) {
this.collisionType = collisionTypes.verticalTop;
} else if (
this.currentPosition.x > this.collisionObject.position.x &&
this.zAxisDifference < 2
) {
this.collisionType = collisionTypes.horizentalXLeft;
} else if (
this.currentPosition.x < this.collisionObject.position.x &&
this.zAxisDifference < 2
) {
this.collisionType = collisionTypes.horizentalXRight;
} else if (
this.currentPosition.z > this.collisionObject.position.z &&
this.xAxisDifference < 2
) {
this.collisionType = collisionTypes.horizentalZLeft;
} else if (
this.currentPosition.z < this.collisionObject.position.z &&
this.xAxisDifference < 2
) {
this.collisionType = collisionTypes.horizentalZRight;
}
MagneticEffect.prototype.setNewPosition = function () {
if (this.collisionType === collisionTypes.verticalBottom) {
this.currentPosition.y = this.collideBottom + 0.5;
} else if (this.collisionType === collisionTypes.verticalTop) {
this.currentPosition.y = this.collideTop - 0.5;
} else if (this.collisionType === collisionTypes.horizentalXRight) {
this.currentPosition.x = this.collisionObject.position.x - this.collisionObjectWidth - 0.5;
} else if (this.collisionType === collisionTypes.horizentalXLeft) {
this.currentPosition.x = this.collisionObject.position.x + this.collisionObjectWidth + 0.5;
} else if (this.collisionType === collisionTypes.horizentalZRight) {
this.currentPosition.z = this.collisionObject.position.z - this.collisionObjectWidth - 0.5;
} else if (this.collisionType === collisionTypes.horizentalZLeft) {
this.currentPosition.z = this.collisionObject.position.z + this.collisionObjectWidth + 0.5;
}
return this.currentPosition;
};