大量のパーティクルを3Dモデルの頂点座標に配置したい
受付中
回答 1
投稿
- 評価
- クリップ 0
- VIEW 1,701
お世話になります。
大量に作成したパーティクルを読み込んだ3Dモデルの頂点座標に配置したいのですが、以下の2点で問題があります。
①object.scale.set();、object.rotation.set();で変更した大きさ、傾きの通りに頂点座標を更新したい
②頂点座標が密集していた場合、パーティクル間の隙間を空けたい
①はverticesNeedUpdate等をやってみたのですが変わりませんでした。他にやり方があるのでしょうか?
②は表示モデルの大きさ次第になると思いますが、どのような方法がありますでしょうか?
ご教示の程よろしくお願い致します
<html>
<head>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.1/TweenMax.min.js"></script>
<script src="js/OrbitControls.js"></script>
<script src="js/TDSLoader.js"></script>
<script>
// ページの読み込みを待つ
window.addEventListener('load', init);
function init() {
// サイズを指定
const width = innerWidth;
const height = innerHeight;
let rot = 0; // 角度
// レンダラーを作成
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#myCanvas'),
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
// シーンを作成
const scene = new THREE.Scene();
// カメラを作成
const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);
// カメラの初期座標を設定
camera.position.set(0, 0, 5);
// カメラコントローラーを作成
const controls = new THREE.OrbitControls(camera);
// 平行光源を作成
const directionalLight = new THREE.DirectionalLight(0xFFFFFF);
directionalLight.position.set(1, 1, 1);
scene.add(directionalLight);
// 環境光を追加
const ambientLight = new THREE.AmbientLight(0xFFFFFF);
scene.add(ambientLight);
const eggGeometry = new THREE.Geometry();
const loader = new THREE.TDSLoader();
loader.setPath('imgs/');
loader.load('js/egg.3ds', (object) => {
if (object) {
let eggVerticesArray = object.children[0].geometry.attributes.position.array;
for (let i = 0; i < eggVerticesArray.length; i+=3) {
eggGeometry.vertices.push(new THREE.Vector3(
eggVerticesArray[i + 0],
eggVerticesArray[i + 1],
eggVerticesArray[i + 2],
));
}
console.log(eggGeometry.vertices);
}
object.scale.set(0.3, 0.3, 0.3);
object.rotation.set(180,0,0);
// scene.add(object);必要なのは座標なのでシーンには追加しない
});
const geometry = new THREE.Geometry();
// 配置する範囲
const SIZE = 5000;
// 配置する個数
const LENGTH = 80000;
for (let i = 0; i < LENGTH; i++) {
geometry.vertices.push(new THREE.Vector3(
SIZE * (Math.random() - 0.5),
SIZE * (Math.random() - 0.5),
SIZE * (Math.random() - 0.5),
));
}
// パーティクルを作成
const material = new THREE.PointsMaterial({
size: 5,
color: 0x0eff7d,
map: new THREE.TextureLoader().load('imgs/snow.png'),
blending: THREE.AdditiveBlending,
transparent: true,
depthWrite: false,
});
// 物体を作成
const mesh = new THREE.Points(geometry, material);
scene.add(mesh);
function xxx() {
for (var i = 0; i < eggGeometry.vertices.length; i++) {
TweenMax.to(geometry.vertices[i], 1, {
x: eggGeometry.vertices[i].x,
y: eggGeometry.vertices[i].y,
z: eggGeometry.vertices[i].z,
}, 0);
}
}
setTimeout(function() {
xxx();
}, 1000);
tick();
// 毎フレーム時に実行されるループイベントです
function tick() {
rot += 0.05;
// ラジアンに変換する
const radian = rot * Math.PI / 180;
// 角度に応じてカメラの位置を設定
camera.position.x = 100 * Math.sin(radian);
camera.position.y = 10 * Math.sin(radian);
camera.position.z = 100 * Math.cos(radian);
// 原点方向を見つめる
camera.lookAt(new THREE.Vector3(0, 0, 0));
// mesh.rotation.y += 0.01;
// レンダリング
renderer.render(scene, camera);
requestAnimationFrame(tick);
geometry.verticesNeedUpdate = true;
geometry.elementNeedUpdate = true;
geometry.computeBoundingSphere();
eggGeometry.verticesNeedUpdate = true;
eggGeometry.elementNeedUpdate = true;
eggGeometry.computeBoundingSphere();
}
}
</script>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
0
①ついて
loader.load('js/egg.3ds', (object) => {
if (object) {
let eggVerticesArray = object.children[0].geometry.attributes.position.array;
for (let i = 0; i < eggVerticesArray.length; i+=3) {
eggGeometry.vertices.push(new THREE.Vector3(
eggVerticesArray[i + 0],
eggVerticesArray[i + 1],
eggVerticesArray[i + 2],
));
}
部分を
loader.load('js/egg.3ds', (object) => {
if (object) {
let eggVerticesArray = object.children[0].geometry.attributes.position.array;
for (let i = 0; i < eggVerticesArray.length; i+=3) {
eggGeometry.vertices.push(new THREE.Vector3(
eggVerticesArray[i + 0]*scaleX,
eggVerticesArray[i + 1]*scaleY,
eggVerticesArray[i + 2]*scaleZ,
));
}
と変更して、初期値を設定して(scaleX scaleY scaleZはnumber型)
その後は
mesh.scaleを変更すれば良いと思います。
②について
モデリングの段階で処理するのが楽です。
blenderでやるのならばsubdivision surfaceをかけると頂点の密度が均一になると思います
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.37%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる