こんにちは。いつもお世話になっております。
HTML5
+JavaScript
+Three.js
で三次元タートルグラフィックスに挑戦しています。
レポジトリ:http://github.com/katahiromz/3D
※ ソースは http://github.com/katahiromz/3D からダウンロードして下さい。
タートルグラフィックスとは、位置と向きを持ったタートル(亀)を操作して図形を描画しようというものです。今回は三次元のタートルグラフィックスです。数学は素人なので手加減よろしくお願い致します。
次のソースについて:http://github.com/katahiromz/3D/blob/master/4.html
add_line
関数で一本の線分を描いています。set_pos
関数で位置をセットしています。set_dir
関数で向きをセットしています。walk
関数で現在の向きで前進して線分を描きます。turn_dir
関数で指定された向きベクトル(dx, dy, dz)
だけ回転して向きを更新します。turn_angle
関数でangle1
度とangle2
度だけ回転します。init
関数は全体の初期化処理です。draw
関数は全体の描画処理です。animate
関数は全体のアニメーション処理です。koch
関数は平面的にコッホ曲線を再帰的に描画します。tree
関数は平面的に木構造を再帰的に描画します。
問題は、draw
関数内部でコッホ曲線と45度傾いた木構造を描いていますが、木が平面的にならないことです。
turn_dir
かturn_angle
の設計か実装が間違えているのでしょうか。個人製作なので、仕様は自由に変更できます。4.html
を修正して木を真っ平らになるようにできないでしょうか。正しく3次元タートルグラフィックスを実装できないでしょうか。よろしくお願い致します。
追記。後出しですが、z==0のとき二次元タートルグラフィックスと互換性のある設計でなければいけません。
追記2. draw関数は変更しません。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/21 07:36
2020/07/21 08:15
回答1件
0
ベストアンサー
追記の条件を満たしてはいませんが、とりあえず「二次元タートルグラフィックスを三次元空間内に配置する」例としては以下のような実装で動作しているかと思います。二次元平面の法線ベクトルを set_normal() で設定しています。
set_dir() は三次元空間内の進行方向を設定できますが、それだけでは進行方向基準で上下左右がどこなのかを決定できません。
HTML
1<!DOCTYPE html> 2<html> 3 <head> 4 <meta charset="utf-8"> 5 <title>My first three.js app</title> 6 <style> 7 body { margin: 0; } 8 canvas { display: block; } 9 </style> 10 </head> 11 <body> 12 <!-- Please download file "three.min.js" from https://raw.githubusercontent.com/mrdoob/three.js/dev/build/three.min.js --> 13 <script src="./three.min.js"></script> 14 <!-- Please download file "OrbitControls.js" from https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/js/controls/OrbitControls.js --> 15 <script src="./OrbitControls.js"></script> 16 <!-- Please download file "Vector3.js" from https://github.com/mrdoob/three.js/blob/master/src/math/Vector3.js --> 17 <script src="./Vector3.js"></script> 18 <!-- Please download file "Quaternion.js" from https://github.com/mrdoob/three.js/blob/master/src/math/Quaternion.js --> 19 <script src="./Quaternion.js"></script> 20 <script> 21 var scene, renderer, camera, controls; 22 var turtle_x = 0, turtle_y = 0, turtle_z = 0; 23 var turtle_dx = 0, turtle_dy = 0, turtle_dz = 0, turtle_spin = 0; 24 var normal_x = 0, normal_y = 0, normal_z = 1; 25 var pen_on = true; 26 27 function add_line(x0, y0, z0, x1, y1, z1) { 28 var points = []; 29 points.push(new THREE.Vector3(x0, y0, z0)); 30 points.push(new THREE.Vector3(x1, y1, z1)); 31 32 var geometry = new THREE.BufferGeometry().setFromPoints(points); 33 var material = new THREE.LineBasicMaterial({ color: 0xffffff }); 34 35 var line = new THREE.Line(geometry, material); 36 scene.add(line); 37 } 38 function set_pos(x, y, z=0) { 39 turtle_x = x; 40 turtle_y = y; 41 turtle_z = z; 42 } 43 function set_normal(x, y, z=1) { 44 var r = Math.sqrt(x*x + y*y + z*z); 45 normal_x = x / r; 46 normal_y = y / r; 47 normal_z = z / r; 48 } 49 function set_dir(dx, dy, dz=0) { 50 var r = Math.sqrt(dx*dx + dy*dy + dz*dz); 51 turtle_dx = dx / r; 52 turtle_dy = dy / r; 53 turtle_dz = dz / r; 54 } 55 function walk(r) { 56 var x0 = turtle_x, y0 = turtle_y, z0 = turtle_z; 57 turtle_x += r * turtle_dx; 58 turtle_y += r * turtle_dy; 59 turtle_z += r * turtle_dz; 60 if (pen_on) 61 add_line(x0, y0, z0, turtle_x, turtle_y, turtle_z); 62 } 63 function add_spin(delta) { 64 turtle_spin += delta; 65 } 66 function turn_angle(angle) { 67 var quaternion = new THREE.Quaternion(); 68 quaternion.setFromAxisAngle( new THREE.Vector3( normal_x, normal_y, normal_z ).normalize(), angle * Math.PI / 180 ); 69 70 var vector = new THREE.Vector3( turtle_dx, turtle_dy, turtle_dz ); 71 vector.applyQuaternion( quaternion ); 72 set_dir(vector.x, vector.y, vector.z); 73 } 74 function init() { 75 renderer = new THREE.WebGLRenderer(); 76 renderer.setSize(window.innerWidth, window.innerHeight); 77 document.body.appendChild(renderer.domElement); 78 79 camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500); 80 camera.position.set(0, 0, 100); 81 camera.lookAt(0, 0, 0); 82 83 controls = new THREE.OrbitControls(camera, renderer.domElement); 84 controls.enableDamping = true; 85 controls.dampingFactor = 0.25; 86 controls.enableZoom = true; 87 controls.autoRotate = true; 88 89 scene = new THREE.Scene(); 90 scene.add(new THREE.AxisHelper(50)); 91 } 92 function koch(degree, step) { 93 if (degree == 0) { 94 walk(step); 95 } else { 96 koch(degree - 1, step/3); 97 turn_angle(60); 98 koch(degree - 1, step/3); 99 turn_angle(-120); 100 koch(degree - 1, step/3); 101 turn_angle(60); 102 koch(degree - 1, step/3); 103 } 104 } 105 function tree(size, angle, depth) { 106 if (depth == 0) 107 return; 108 walk(size); 109 turn_angle(angle); 110 tree(size * 0.75, angle, depth - 1); 111 turn_angle(-2 * angle); 112 tree(size * 0.75, angle, depth - 1); 113 turn_angle(angle); 114 walk(-size); 115 } 116 function draw() { 117 set_pos(0, 0, 0); 118 set_dir(0, 100, 0); 119 set_normal(0, 0, 1); 120 koch(6, 50); 121 set_pos(0, 0, 0); 122 set_dir(0, 100, 100); 123 set_normal(1, 0, 0); 124 tree(10, 40, 10); 125 } 126 function animate() { 127 controls.update(); 128 requestAnimationFrame(animate); 129 renderer.render(scene, camera); 130 } 131 132 init(); 133 draw(); 134 animate(); 135 </script> 136 </body> 137</html>
上の例は左右に曲がるだけですが、上下にも曲がれるようにするなら以下のような実装でいいのかなあ。一応、動作しているように思えます。
上下に曲がる場合は法線ベクトルも回転させるような感じです。適切な処理かどうかは不明です。
HTML
1(文字数オーバーのようなので、上の例の65行目までをここに貼り付けて下さい) 2 function turn_angle1(angle) { 3 var quaternion = new THREE.Quaternion(); 4 quaternion.setFromAxisAngle( new THREE.Vector3( normal_x, normal_y, normal_z ).normalize(), angle * Math.PI / 180 ); 5 6 var vector = new THREE.Vector3( turtle_dx, turtle_dy, turtle_dz ); 7 vector.applyQuaternion( quaternion ); 8 set_dir(vector.x, vector.y, vector.z); 9 } 10 function turn_angle2(angle) { 11 var quaternion = new THREE.Quaternion(); 12 quaternion.setFromAxisAngle( new THREE.Vector3( normal_x, normal_y, normal_z ).normalize(), 90 * Math.PI / 180 ); 13 14 var vector = new THREE.Vector3( turtle_dx, turtle_dy, turtle_dz ); 15 vector.applyQuaternion( quaternion ); 16 var temp_x = vector.x; 17 var temp_y = vector.y; 18 var temp_z = vector.z; 19 20 quaternion = new THREE.Quaternion(); 21 quaternion.setFromAxisAngle( new THREE.Vector3( temp_x, temp_y, temp_z ).normalize(), angle * Math.PI / 180 ); 22 23 vector = new THREE.Vector3( normal_x, normal_y, normal_z ); 24 vector.applyQuaternion( quaternion ); 25 set_normal(vector.x, vector.y, vector.z); 26 27 vector = new THREE.Vector3( turtle_dx, turtle_dy, turtle_dz ); 28 vector.applyQuaternion( quaternion ); 29 set_dir(vector.x, vector.y, vector.z); 30 } 31 function init() { 32 renderer = new THREE.WebGLRenderer(); 33 renderer.setSize(window.innerWidth, window.innerHeight); 34 document.body.appendChild(renderer.domElement); 35 36 camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 500); 37 camera.position.set(0, 0, 100); 38 camera.lookAt(0, 0, 0); 39 40 controls = new THREE.OrbitControls(camera, renderer.domElement); 41 controls.enableDamping = true; 42 controls.dampingFactor = 0.25; 43 controls.enableZoom = true; 44 controls.autoRotate = true; 45 46 scene = new THREE.Scene(); 47 scene.add(new THREE.AxisHelper(50)); 48 } 49 function koch(degree, step) { 50 if (degree == 0) { 51 walk(step); 52 } else { 53 koch(degree - 1, step/3); 54 turn_angle1(60); 55 koch(degree - 1, step/3); 56 turn_angle1(-120); 57 koch(degree - 1, step/3); 58 turn_angle1(60); 59 koch(degree - 1, step/3); 60 } 61 } 62 function tree(size, angle1, depth, angle2=0) { 63 if (depth == 0) 64 return; 65 walk(size); 66 turn_angle1(angle1); 67 turn_angle2(angle2); 68 tree(size * 0.75, angle1, depth - 1, angle2); 69 turn_angle2(-angle2); 70 turn_angle1(-2 * angle1); 71 turn_angle2(angle2); 72 tree(size * 0.75, angle1, depth - 1, angle2); 73 turn_angle2(-angle2); 74 turn_angle1(angle1); 75 walk(-size); 76 } 77 function draw() { 78 set_pos(0, 0, 0); 79 set_dir(0, 100, 0); 80 set_normal(0, 0, 1); 81 koch(6, 50); 82 set_pos(0, 0, 0); 83 set_dir(0, 100, 100); 84 set_normal(1, 0, 0); 85 tree(10, 40, 10, 10); 86 } 87 function animate() { 88 controls.update(); 89 requestAnimationFrame(animate); 90 renderer.render(scene, camera); 91 } 92 93 init(); 94 draw(); 95 animate(); 96 </script> 97 </body> 98</html>
投稿2020/07/21 13:29
総合スコア366
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/22 08:03 編集
2020/07/22 12:42
2020/07/23 11:22
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。