2

三角形の頂点で構成されたソリッドでテクスチャのない 3D 形状と、すべての x、y、z ポイントを含む頂点の配列へのアクセスを考えると、この形状を歪めるためにいくつかの「磁気」フィールドを実装するにはどうすればよいでしょうか? たとえば、すべての磁場は、オブジェクト内またはオブジェクト外のランダムな位置 x、y、z、および強度のポイントです。この形状の頂点の近くにある場合、それはそれに「引き寄せ」られ、近くになるほど強くなります (これも強度値によって調整されます) ... 滑らかな隆起と隆起につながります。

私は現在、ThreeJS (JavaScript/WebGL) を使用しているので、JavaScript、ThreeJS、または疑似コードでのヘルプは完璧かもしれませんが、何でもうまくいきます! ありがとう!

ここに画像の説明を入力

4

4 に答える 4

1

(@ananthonlineで説明されているように)陰関数曲面に変換したくない場合は、「磁石」の強度と位置に基づいてすべての頂点を微調整できます。以下は新しい頂点を作成せず、既存の頂点を引き付けるだけであることに注意してください。これは、アプリケーションに応じて、長所または短所になる可能性があります。

磁石の位置を指定すると、次のように各頂点を新しい位置にM微調整できます。VV'

point V =     [incoming vertex]
point M =     [magnet location]
float range = [chosen nominal range for the magnetic effect]

float range2 = range * range  [range squared, for comparison with squared distance]
vector MV = V - M             [vector from M to V]
float alpha = range2 / (range2 + dot(MV, MV))  [weighting factor]
point V' =  alpha * M + (1-alpha) * V          [new, "magnetized" position]

rangeからの距離の数倍の頂点は、M最小限の影響しか受けません。内の頂点はrange強く引き付けられますが、狂うことはありません。各磁化された頂点は、元の位置との間の線上のどこかにありM、「パッカー」効果を作成します。磁化された位置は、引き付けられた領域を犠牲にして、磁石の近くでより密になります。

磁気効果の正確な形状が気に入らない場合(たとえば、特定の距離を超える頂点がまったく移動しないようにしたい場合)、の式を微調整できますalphaalphaを超えないように注意してください。大きくなるにつれて1近づきます。0dot(MV, MV)

于 2012-06-21T19:22:56.610 に答える
1

必要なのは、暗黙的なサーフェスまたはメタボールのような動作です。(IMO) 暗黙的なサーフェスの背後にある基本の非常に優れた説明については、こちらを参照してください。概念を理解すれば、これを 3D に拡張するのは非常に簡単です。また、三角測量を自分で作成する必要がないことに注意してください (既にメッシュがあるため)。

于 2012-06-21T15:45:32.830 に答える
0

次のThreeJSは、一部オフになっている可能性がありますが、ある程度機能するようになりました。効果はまだ説得力がないように見えるかもしれませんが、よくわかりません。ConstraintViaMagnets関数が問題の核心です(HTMLとソースをここで完全に実行します;デモをここで実行します):

'use strict';
var app = null;

window.onload = function() {
    app = new App();
    app.init();
}

App.prototype.init = function() {
    this.scene = new THREE.Scene();
    this.addCamera();
    this.addLights();
    this.addSphere();
    this.addRenderer();
    this.render();
    app.animate();
};

App.prototype.distortViaMagnets = function() {
    var maxMagnets = this.magnets.length, maxVertices = this.sphere.geometry.vertices.length;
    var magneticMaxValue = this.getDistance3d( {x: 0, y: 0, z: 0}, {x: 1000, y: 1000, z: 1000} );
    var strength = 1000, factor = 3;
    for (var i = 0; i < maxMagnets; i++) {
        for (var vertexI = 0; vertexI < maxVertices; vertexI++) {
            var magnet = this.magnets[i];
            var vertex = this.sphere.geometry.vertices[vertexI];

            var distance = this.getDistance3d(magnet, vertex);
            var power = magneticMaxValue / distance / strength;

            vertex.x += ( (magnet.x - vertex.x) * power ) * factor;
            vertex.y += ( (magnet.y - vertex.y) * power ) * factor;
            vertex.z += ( (magnet.z - vertex.z) * power ) * factor;
        }
    }
}

App.prototype.animate = function() {
    app.mainGroup.rotation.y -= .003;

    requestAnimationFrame(app.animate);
    app.renderer.render(app.scene, app.camera);
};

App.prototype.addCamera = function() {
    this.camera = new THREE.CombinedCamera(this.width, this.height, 45, 1, 10000);
    this.camera.position.set(0, 0, 400 - 200);
    this.camera.lookAt( new THREE.Vector3(0, 0, 0) );
    this.scene.add(this.camera);
}

App.prototype.addSphere = function() {
    this.mainGroup = new THREE.Object3D();

    var radius = 50, segments = 30 * 3, rings = 30 * 3;
    var geometry = new THREE.SphereGeometry(radius, segments, rings);
    geometry.dynamic = true;

    var material = new THREE.MeshPhongMaterial( {color: 0xffffff, opacity: 1} );
    this.sphere = new THREE.Mesh(geometry, material);
    this.sphere.dynamic = true;
    this.sphere.position.set(0, 0, 0);
    this.sphere.doubleSided = true;

    this.addMagnets();
    this.distortViaMagnets();

    this.mainGroup.add(this.sphere);

    this.scene.add(this.mainGroup);
}

App.prototype.addMagnets = function(vertex) {
    var max = this.sphere.geometry.vertices.length, maxMagnets = 1;
    for (var i = 1; i <= 2; i++) {
        var index = Misc.getRandomInt(0, max - 1);
        var vertex = app.sphere.geometry.vertices[index];
        var magnetI = this.magnets.length;
        this.magnets[magnetI] = this.distortVertex( {x: vertex.x, y: vertex.y, z: vertex.z}, 10 );
        this.showMagnet(this.magnets[magnetI]);
    }

    var magnetI = 0;
    this.magnets[magnetI] = {x: 58, y: 0, z: 0};
    this.showMagnet(this.magnets[magnetI]);
}

App.prototype.getDistance3d = function(vertex1, vertex2) {
    var xfactor = vertex2.x - vertex1.x;
    var yfactor = vertex2.y - vertex1.y;
    var zfactor = vertex2.z - vertex1.z;
    return Math.sqrt( (xfactor*xfactor) + (yfactor*yfactor) + (zfactor*zfactor) );
}

App.prototype.showMagnet = function(vertex) {
    var radius = 1.5, segments = 10, rings = 10;
    var geometry = new THREE.SphereGeometry(radius, segments, rings);

    var material = new THREE.MeshPhongMaterial( {color: 0x11ee33, opacity: .6} );
    var sphere = new THREE.Mesh(geometry, material);
    sphere.position.set(vertex.x, vertex.y, vertex.z);

    this.mainGroup.add(sphere);
}

App.prototype.distortVertex = function(vertex, distortion) {
    vertex.x = Misc.distort(vertex.x, distortion);
    vertex.y = Misc.distort(vertex.y, distortion);
    vertex.z = Misc.distort(vertex.z, distortion);
    return vertex;
}

App.prototype.addRenderer = function() {
    this.renderer = new THREE.WebGLRenderer( {antialias: true} );
    this.renderer.setSize(this.width, this.height);
    var elmMain = document.getElementById('main');
    elmMain.appendChild(this.renderer.domElement);
}

App.prototype.render = function() {
    this.renderer.render(this.scene, this.camera);
};

App.prototype.addLights = function() {
    var light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set(-50, 250, 250);
    this.scene.add(light);
};

function App() {
    this.width = window.innerWidth;
    this.height = window.innerHeight;
    this.camera = null;
    this.sphere = null;
    this.controls = null;
    this.mainGroup = null;
    this.renderer = null;
    this.scene = null;
    this.magnets = [];
    this.debugElm = null;
}
于 2012-06-21T19:46:34.933 に答える
0

three.js については何も知りませんが、放物線については知っています。そして、それはあなたが使うことができるもののようです。

これは答えのようには見えませんが、このビデオを見てください: http://www.youtube.com/watch?v=8HvZHo-LSvQ . 放物線の描き方を動画で紹介しています。あなたの場合、フォーカス ポイントはオブジェクト内のポイント ( strength of magnet = depth of focus point)、軸の原点は磁石、y 軸は頂点の法線になります。

残念ながら、この方法を実行するとエッジが切れてしまい、代わりにある種の正弦波が必要になることは間違いありませんが、これが先に進む方法のヒントになることを願っています. 私はあなたをさらに探しますが、これは私の最初の直感でした.

于 2012-06-21T16:02:16.503 に答える