質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.06%

  • JavaScript

    13279questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • Three.js

    84questions

    Three.jsはWebGLをサポートしているJavaScriptの3D描画用ライブラリです。

threeJS、Planeの上にSphere(球体)をぴったり乗せる方法

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 121

SaintKnowledge

score 187

COBOLer & PHPerですが、必要上、Javascriptもゴリゴリ書く方です。

現在、ThreeJSに触れてます。PlaneやSphere(球体)の描画自体は問題無く動作しています。OrbitControlsでグリグリ回すのも大丈夫です。

一つ分からないのが、適当な座標にPlaneと球体を配置するのではなく、Planeの座標上ぴったりに球体を置きたいのですが、方法が分かりません。将来的には、plane.verticesで頂点を書き換えて傾斜を付けたいので、どの位置に球体を置いてもPlane上にぴったりくっつけたいのですが、試行錯誤してもどうしても球体が少し埋まったような見栄えになったり、潜った感じになったり浮いた感じになったりします。

ぴったり上に乗っている、Planeの傾斜に正しく沿っている、という状況がわかりづらいのですが、方法や確認方法をご存知の方はいらっしゃいませんでしょうか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

check解決した方法

0

結果的に、CANNON.JSと組み合わせて、いい具合に跳ねない位置にy値を合わせることで、何とかしました。
いまいち納得いかない感じではありますが。。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

球体ということですので、raycaster.intersectObject が使えそうです。

https://threejs.org/docs/#api/core/Raycaster

このデモが近そうと思いますが、どうでしょう
https://threejs.org/examples/#webgl_interactive_raycasting_points

具体的なステップとしては、
1・傾斜したplaneの外側に、球を置く基準となる1点を用意する。球の中央の値でも可
2・その点から、planeの中心に対して、intersectObjectを実行。
3・返り値に対して球をセットする

var basePos  = new THREE.Vector3(// 省略。球の中心地点とする);
var planeCenter = new THREE.Vector3(// 省略。planeの中心地点とする。);
var ballToPlane = basePos.clone().sub(planeCenter).normalize(); // 球の中心から板の中心に向かうベクトルを作成し、さらに正規化
var ray = new THREE.Raycaster(basePos, ballToPlane); // ボールの位置から板に向かうrayを作成
var hits = ray.intersectObject(plane); // rayとplaneとの衝突を検知
if(hits && hits.length > 0){  
  // 衝突点にそのままボールの中央をセットしてしまうとめりこむので、ボールの半径分外側に移動させる
  var addPos = ballToPlane.multiply(-1).multiply(ballRadius); // sphereを作ったときに使った半径があれば使いまわせます
  var ballPos = hits[0].point.clone().add(addPos); //衝突検出した値と、上のめりこみ防止用の値を足す
  ball.Pos.copy(ballPos); //sphereの位置にセットして終了
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/17 23:15 編集

    詳細にありがとうございます。
    うまく衝突判断が出来ないみたいで、hitsに引っかからず、Vector3の使い方が悪いのかも。。イベント系言語がちょっと苦手なもので。。

    new THREE.Vector3(sphere.position.x, sphere.position.y, sphere.position.z);
    *このやり方では、球sphereの中心では無いですかね?

    キャンセル

  • 2017/12/17 23:21

    sphereが、SphereGeometryから作ったものであれば、positionはsphereの中心であっています。
    取れない原因となると…もしかしたら、

    ```
    var hits = ray.intersectObject(plane, true);
    ```
    これで取れたりするかもしれません(子階層チェック)

    キャンセル

  • 2017/12/18 00:26 編集

    何度もありがとうございます。
    なんか、うまくいかないです。多分自分のやり方が悪いのかと思います。

    plane、sphereともに、座標位置をx,y,zともに0、rotationも0、としても衝突判断していないよう。。以下の通りですが、お気付きの点があればと思います。。


    var planeGeometry = new THREE.PlaneGeometry(100, 60, 16, 16);
    var planeMaterial = new THREE.MeshBasicMaterial({color: 0x1B5E20, wireframe:true});
    var plane = new THREE.Mesh(planeGeometry, planeMaterial);
    plane.rotation.x = 0;
    plane.position.x = 0;
    plane.position.y = 0;
    plane.position.z = 0;
    scene.add(plane);

    // 実際はここで、planeGeometry.verticesを使って16のマス目に斜面を付けています。

    var sphere = new THREE.Mesh(new THREE.SphereGeometry(1, 20, 20), new THREE.MeshLambertMaterial({
    color: 0xffff00,
    Ambient: 0xffff00
    }));
    sphere.position.x = 0;
    sphere.position.y = 0;
    sphere.position.z = 0;

    // scene addの前に、ご教示のロジックを追加。
    var basePos = new THREE.Vector3(sphere.position.x, sphere.position.y, sphere.position.z);
    var planeCenter = new THREE.Vector3(plane.position.x, plane.position.y, plane.position.z);
    var ballToPlane = basePos.clone().sub(planeCenter).normalize(); // 球の中心から板の中心に向かうベクトルを作成し、さらに正規化
    console.log(ballToPlane);

    var ray = new THREE.Raycaster(basePos, ballToPlane); // ボールの位置から板に向かうrayを作成
    var hits = ray.intersectObject(plane, true); // rayとplaneとの衝突を検知

    console.log(hits);

    if(hits && hits.length > 0){
    // 衝突点にそのままボールの中央をセットしてしまうとめりこむので、ボールの半径分外側に移動させる
    var addPos = ballToPlane.multiply(-1).multiply(1); // sphereを作ったときに使った半径があれば使いまわせます
    var ballPos = hits[0].point.clone().add(addPos); //衝突検出した値と、上のめりこみ防止用の値を足す
    ball.Pos.copy(ballPos); //sphereの位置にセットして終了
    console.log(ball.Pos.copy(ballPos));
    }


    scene.add(sphere);

    キャンセル

  • 2017/12/18 00:18

    console.log(hits);
    にて、hits が空っぽ、になってしまいます。

    キャンセル

  • 2017/12/18 00:27

    > plane、sphereともに、座標位置をx,y,zともに0、rotationも0

    これがやりがちな、しかしやってはいけない部分です。
    `Raycaster`は、ある点からある物体(面)に向けたベクトルにて衝突検出を行うため、この値でセットをしてしまうと長さゼロのベクトルになり、衝突を検出することができません。

    また、申し訳ないことに、自分のコードも間違っていたようで、正しくは
    ```
    var ballToPlane = planeCenter.clone().sub(basePos).normalize(); // 球の中心から板の中心に向かうベクトルを作成し、さらに正規化
    ```
    でした(ベクトルの方角が逆を向いていた)
    貼り付けてもらったソースに上記の修正を加えたところ、衝突点が検出できることを確認しました。

    キャンセル

  • 2017/12/18 00:54 編集

    なるほど、指摘ありがとうございます。

    平面での衝突判断はうまくいったようですが、planeGeometry.verticesで斜面(頂点の修正)を付けると、全く衝突しなくなりまして。。

    自分でも調べてみます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 91.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaScript

    13279questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

  • Three.js

    84questions

    Three.jsはWebGLをサポートしているJavaScriptの3D描画用ライブラリです。