5

Three.js を使用して形状を押し出すことにより、SVG パス (lineto および moveto) に 3D 感を与えようとしましたが、そのプロセスによって除去できないアーティファクトが発生します。

レンダリングした 3D 形状に奇妙なアーティファクトが生じる原因は何ですか? それらを削除する方法はありますか?

アーティファクトは、下のサンプル画像で矢印でマークされています。

ここに画像の説明を入力

実際の例はこちら: http://jsfiddle.net/pHn2B/24/

コードは次のとおりです。

// コールバックでピッキング

// three.js r.52
varコンテナ、
    情報、
    カメラ、
    シーン、
    ライト、
    幾何学、
    メッシュ、
    プロジェクター、
    レンダラー、
    コントロール;
    オブジェクト = [];

// ドム
コンテナ = document.createElement( 'div' );
document.body.appendChild(コンテナ);

// 情報
info = document.createElement( 'div' );
info.style.position = '絶対';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = '中心';
info.innerHTML = "ドラッグしてカメラを回転、クリックして選択";
container.appendChild( 情報 );

// レンダラー
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );

// シーン
シーン = 新しい THREE.Scene();

// カメラ
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 0, 300, 500 );
scene.add( カメラ );

// コントロール
コントロール = 新しい THREE.OrbitControls( カメラ );

// ライト
scene.add( new THREE.AmbientLight( 0x222222 ) );

// ライト
光 = 新しい THREE.PointLight( 0xaaaaaa );
light.position = camera.position;
scene.add(ライト);

// ジオメトリ
ジオメトリ = 新しい THREE.CubeGeometry( 100, 100, 500 );

// 素材
material = new THREE.MeshLambertMaterial( { color: 0xff0000,ambient: 0xff0000, overdraw: true } );

//メッシュ
メッシュ = 新しい THREE.Mesh( ジオメトリ、マテリアル );
mesh.position.set( -100, -100, 200 );
mesh.name = "赤いオブジェクト";
mesh.callback = function() { info.innerHTML = this.name; }
scene.add(メッシュ);

objects.push( メッシュ );

// ジオメトリ
////////////
    // 習慣 //
    ////////////

var starPoints2 = 新しい THREE.Shape();

starPoints2.moveTo(307.94,275.49);
starPoints2.lineTo(296.26,275.23);
starPoints2.lineTo(286.64,272.99);
starPoints2.lineTo(279.78,269.31);
starPoints2.lineTo(274.14,263.55);
starPoints2.lineTo(271.65,260.21);
starPoints2.lineTo(269.2,261.06);
starPoints2.lineTo(254.83,268.51);
starPoints2.lineTo(242.11,272.97);
starPoints2.lineTo(227.59,275.23);
starPoints2.lineTo(209.91,275.48);
starPoints2.lineTo(197.47,273.63);
starPoints2.lineTo(187.91,270.13);
starPoints2.lineTo(180.48,265.09);
starPoints2.lineTo(175.32,258.88);
starPoints2.lineTo(172.2,251.44);
starPoints2.lineTo(171.1,242.23);
starPoints2.lineTo(172.24,233.63);
starPoints2.lineTo(175.49,226.24);
starPoints2.lineTo(181,219.54);
starPoints2.lineTo(189.42,213.3);
starPoints2.lineTo(201.36,207.73);
starPoints2.lineTo(217.23,203.25);
starPoints2.lineTo(238.28,200.1);
starPoints2.lineTo(269.37,198.47);
starPoints2.lineTo(269.98,182.93);
starPoints2.lineTo(268.74,171.32);
starPoints2.lineTo(266.05,163.7);
starPoints2.lineTo(261.58,157.72);
starPoints2.lineTo(255.24,153.24);
starPoints2.lineTo(247.06,150.32);
starPoints2.lineTo(235.44,149.13);
starPoints2.lineTo(224.71,150.05);
starPoints2.lineTo(215.91,153);
starPoints2.lineTo(210.23,156.86);
starPoints2.lineTo(207.64,160.85);
starPoints2.lineTo(207.19,165.28);
starPoints2.lineTo(209.34,169.86);
starPoints2.lineTo(212.01,174.15);
starPoints2.lineTo(212.14,177.99);
starPoints2.lineTo(209.8,181.78);
starPoints2.lineTo(204.22,185.79);
starPoints2.lineTo(197.62,187.68);
starPoints2.lineTo(188.65,187.43);
starPoints2.lineTo(182.41,185.39);
starPoints2.lineTo(178.45,181.77);
starPoints2.lineTo(176.2,176.9);
starPoints2.lineTo(176.03,170.64);
starPoints2.lineTo(178.2,164.13);
starPoints2.lineTo(183.09,157.69);
starPoints2.lineTo(191.04,151.36);
starPoints2.lineTo(202.01,145.82);
starPoints2.lineTo(216.09,141.57);
starPoints2.lineTo(232.08,139.24);
starPoints2.lineTo(250.07,139.18);
starPoints2.lineTo(266.13,141.23);
starPoints2.lineTo(279.05,145.06);
starPoints2.lineTo(289.15,150.3);
starPoints2.lineTo(295.91,156.19);
starPoints2.lineTo(300.73,163.41);
starPoints2.lineTo(303.85,172.47);
starPoints2.lineTo(305.07,183.78);
starPoints2.lineTo(305.07,241.97);
starPoints2.lineTo(306,251.51);
starPoints2.lineTo(308.18,256.39);
starPoints2.lineTo(311.72,259.09);
starPoints2.lineTo(317.31,260.01);
starPoints2.lineTo(324.71,259.01);
starPoints2.lineTo(332.45,255.86);
starPoints2.lineTo(335.57,257.53);
starPoints2.lineTo(337.6,260.44);
starPoints2.lineTo(336.94,262.33);
starPoints2.lineTo(328.27,268.74);
starPoints2.lineTo(317.89,273.41);
starPoints2.lineTo(307.94,275.49);
/*
starPoints2.moveTo(245.79,125.33);
starPoints2.lineTo(232.93,124.53);
starPoints2.lineTo(222.21,121.74);
starPoints2.lineTo(213.14,117.11);
starPoints2.lineTo(207.36,111.92);
starPoints2.lineTo(203.7,105.75);
starPoints2.lineTo(201.94,98.18);
starPoints2.lineTo(202.34,90.12);
starPoints2.lineTo(204.86,83.4);
starPoints2.lineTo(210.01,76.81);
starPoints2.lineTo(217.49,71.33);
starPoints2.lineTo(227.17,67.31);
starPoints2.lineTo(238.35,65.2);
starPoints2.lineTo(243.99,64.95);
starPoints2.lineTo(255.92,66.06);
starPoints2.lineTo(266.21,69.28);
starPoints2.lineTo(274.98,74.44);
starPoints2.lineTo(280.64,80.19);
starPoints2.lineTo(284.02,86.85);
starPoints2.lineTo(285.26,94.52);
starPoints2.lineTo(284.27,102.84);
starPoints2.lineTo(281.24,109.66);
starPoints2.lineTo(276.03,115.43);
starPoints2.lineTo(267.89,120.46);
starPoints2.lineTo(257.68,123.93);
starPoints2.lineTo(245.79,125.33);
*/
var smileyEye1Path = 新しい THREE.Path();

smileyEye1Path.moveTo(221.69,258.13);
smileyEye1Path.lineTo(215.2,255.08);
smileyEye1Path.lineTo(210.86,250.57);
smileyEye1Path.lineTo(208.4,244.49);
smileyEye1Path.lineTo(207.92,237.03);
smileyEye1Path.lineTo(209.69,230.71);
smileyEye1Path.lineTo(213.82,224.85);
smileyEye1Path.lineTo(220.9,219.34);
smileyEye1Path.lineTo(230.95,214.67);
smileyEye1Path.lineTo(245.76,210.86);
smileyEye1Path.lineTo(266.59,208.36);
smileyEye1Path.lineTo(269.48,208.76);
smileyEye1Path.lineTo(269.99,212.88);
smileyEye1Path.lineTo(269.99,244.81);
smileyEye1Path.lineTo(269.34,247.02);
smileyEye1Path.lineTo(266.07,250.04);
smileyEye1Path.lineTo(255.27,255.23);
smileyEye1Path.lineTo(242.52,258.58);
smileyEye1Path.lineTo(230.57,259.43);
smileyEye1Path.lineTo(221.69,258.13);

/*
smileyEye1Path.moveTo(238.44,116.65);
smileyEye1Path.lineTo(231.99,114.29);
smileyEye1Path.lineTo(227.23,110.22);
smileyEye1Path.lineTo(223.94,104.53);
smileyEye1Path.lineTo(222.41,96.92);
smileyEye1Path.lineTo(223.05,88.57);
smileyEye1Path.lineTo(225.65,82.21);
smileyEye1Path.lineTo(230.07,77.36);
smileyEye1Path.lineTo(235.93,74.4);
smileyEye1Path.lineTo(243.68,73.34);
smileyEye1Path.lineTo(246.08,73.43);
smileyEye1Path.lineTo(253.37,75.08);
smileyEye1Path.lineTo(258.65,78.43);
smileyEye1Path.lineTo(262.47,83.41);
smileyEye1Path.lineTo(264.59,90.25);
smileyEye1Path.lineTo(264.64,98.93);
smileyEye1Path.lineTo(262.63,106.12);
smileyEye1Path.lineTo(258.87,111.5);
smileyEye1Path.lineTo(253.73,115.1);
smileyEye1Path.lineTo(246.81,116.94);
smileyEye1Path.lineTo(238.44,116.65);
*/
var starShape = starPoints2;

starShape.holes.push( smileyEye1Path );

    var 押し出し設定 = {
        //サイズ: 1、高さ: 1、曲線セグメント: 100、ステップ = 10、
        // フォント、太さ、スタイル、
        金額:20、
        bevelEnabled: 真、
        bevelThickness: 0.5、
        bevelSize: 0.5,
        bevelSegments: 8,
        // 押し出しパス:
        // 曲げパス:
        材料: 0,
        押し出し材料: 1
        //、
        //uvGenerator: BoundingUVGenerator
       //uvGenerator: THREE.ExtrudeGeometry.WorldUVGenerator
    };

    var starGeometry = new THREE.ExtrudeGeometry( starShape、extrudeSettings );

    var materialFront = new THREE.MeshLambertMaterial( { color: 0xffff00,ambient: 0xffff00, overdraw: false, transparent:false, opacity: 1.0, side: THREE.DoubleSide } );
    var materialSide = new THREE.MeshLambertMaterial( { color: 0xff8800,ambient: 0xff8800, overdraw: false, transparent:false, opacity: 1.0, side: THREE.DoubleSide } );

//var crateTexture = new THREE.ImageUtils.loadTexture( 'http://www.kahkonen.com/asiakkaat/crate2.gif');
//var crateTexture = new THREE.ImageUtils.generateDataTexture(10,10,{r:255,g:0,b:0});

//var materialFront = new THREE.MeshBasicMaterial( { map: crateTexture } );

var materialArray = [ materialFront, materialSide ];
var materialArray = [ materialFront, materialSide ];

var starMaterial = new THREE.MeshFaceMaterial(materialArray);

    var star = new THREE.Mesh( starGeometry, starMaterial );

    star.position.set(-150,-150,0);
    シーン.追加(スター);
/*  
    // モデルにワイヤーフレームを追加
    var wireframeTexture = new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, transparent: false } );
    var star = new THREE.Mesh( starGeometry, wireframeTexture );
    star.position.set(50,10,0);
    シーン.追加(スター);
*/
objects.push( スター );

// プロジェクター
プロジェクター = 新しい THREE.Projector();

// リスナー
document.addEventListener( 'mousedown', onDocumentMouseDown, false)

// キーボード ハンドラ
関数 onDocumentMouseDown( イベント ) {

    event.preventDefault();

    var ベクトル = 新しい THREE.Vector3(
        ( event.clientX / window.innerWidth ) * 2 - 1,
        - ( event.clientY / window.innerHeight ) * 2 + 1,
        0.5 );

    プロジェクター.unprojectVector(ベクトル、カメラ);

    var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );

    var 交差 = ray.intersectObjects( オブジェクト );    

    if (交差.長さ > 0) {

        交差[0].object.callback();

    }

}

// 与える
関数 render() {

    コントロール.update()

    renderer.render(シーン、カメラ);
}

// アニメーション化            
(関数アニメーション() {

    requestAnimationFrame(アニメーション);
    与える();
}());

テクスチャを追加してアーティファクトを削除しようとしましたが、テクスチャがまったく表示されません:

ここに画像の説明を入力

他の問題 (アーティファクトの問題に関連する場合と関連しない場合があります) は、エッジを通して背景が見えることです。

テクスチャは必須ではありませんが、アーティファクトの除去は必須です。

テクスチャを追加するために使用したコードは以下で、完全なコードはフィドルにあります (リンクはコードの後に​​あります)。

var crateTexture = new THREE.ImageUtils.loadTexture( 'http://www.kahkonen.com/asiakkaat/crate.gif'); var crateTexture = new THREE.ImageUtils.generateDataTexture(10,10,{r:255,g:0,b:0}); var materialFront = new THREE.MeshBasicMaterial( { map: crateTexture } );

// http://jsfiddle.net/pHn2B/27/

サンプル画像は Chrome のものです。Firefox でも同様の現象が発生します。

4

3 に答える 3

3

CanvasRendererこれは、 z バッファリングの問題によって引き起こされるの既知の制限です。多くの細長い面を持つジオメトリによってさらに悪化します。モデルは で正しくレンダリングされWebGLRendererます。

ExtrudeGeometryもともとテキスト用に書かれていましたが、それが生成する UV を見ると、UV の頂点位置の x および y コンポーネントを使用するだけで、この場合、範囲 [ 0, 1 ] の外にある値が生成されます。 . コールバック関数で独自の UV ジェネレーターを提供するオプションがあります。

最初に、キューブにテクスチャを正常に追加できることを確認してください。

three.js r.58

于 2013-04-19T15:32:16.923 に答える
2

さらに参考までに。@Westlangleyの答えは、形状にテクスチャを取得するための正しい方向に私を導きます. 重要なのは、ある範囲から別の範囲への値のスケーリング、ワールド座標から UV 範囲内のシェイプへのスケーリングでした。これは 0 ~ 1 でなければなりません。

そこで、THREE.ExtrudeGeometry.WorldUVGenerator をコピーして名前を THREE.ExtrudeGeometry.BoundingBoxUVGenerator に変更し、メンバー関数 generateTopUV() でこれらの行を置き換えました。

        戻る [
            new THREE.Vector2( ax, y ),
            new THREE.Vector2( bx, by ),
            new THREE.Vector2( cx, cy )
        ];

これ等と一緒に:

    var bb = 押し出し形状.getBoundingBox();
    var bb_minX = bb.minX;
    var bb_minY = bb.minY;
    var bb_width = bb.maxX - bb_minX;
    var bb_height = bb.maxY - bb_minY;
        if (bb_width == 0) bb_width = 1;
        if (bb_height == 0) bb_height = 1;
        return [new THREE.Vector2( (ax - bb_minX) / bb_width, (ay - bb_minY) / bb_height ),
            new THREE.Vector2( (bx - bb_minX) / bb_width, (by - bb_minY) / bb_height ),
            new THREE.Vector2( (cx - bb_minX) / bb_width, (cy - bb_minY) / bb_height )
        ];

そして、テクスチャが「魔法のように」適切な場所に現れました!

( https://github.com/mrdoob/three.js/issues/1811から同様の名前の関数を試した人向け。範囲変換が奇妙な方法で行われるため、機能しません。)

これは、頂点座標が実際に 0 ~ 1 の範囲にある場合や、座標が負の場合にも機能します。また、何らかの理由で width と height が 0 の場合は 0 を返します。

考えられるほとんどの目的で、これはデフォルトの THREE.ExtrudeGeometry.WorldUVGenerator よりもはるかに便利です。また、デフォルトのジェネレーターは 0 ~ 1 の範囲の座標を持つ頂点に対してのみ機能するため、このジェネレーターの目的を想像することさえできません。しかし、three.js は初めてなので、まだ想像できない理由があるかもしれません。

于 2013-04-20T04:11:26.773 に答える
1

以前も同じ問題がありました。
また、メンバー関数 generateSideWallUV() を
次の行に置き換えました。

if ( Math.abs( ay - by ) < 0.01 ) {
            return [
                new THREE.Vector2( ax, 1 - az ),
                new THREE.Vector2( bx, 1 - bz ),
                new THREE.Vector2( cx, 1 - cz ),
                new THREE.Vector2( dx, 1 - dz )
            ];
} else {
            return [
                new THREE.Vector2( ay, 1 - az ),
                new THREE.Vector2( by, 1 - bz ),
                new THREE.Vector2( cy, 1 - cz ),
                new THREE.Vector2( dy, 1 - dz )
            ];
        }

これらの行で:

var amount = extrudeOptions.amount;
if ( Math.abs( ay - by ) < 0.01 ) {
            return [
                new THREE.Vector2( (ax - bb_minX) / bb_width, 1-(az / amount) ),
                new THREE.Vector2( (bx - bb_minX) / bb_width, 1-(bz  / amount) ),
                new THREE.Vector2( (cx - bb_minX) / bb_width, 1-(cz  / amount) ),
                new THREE.Vector2( (dx - bb_minX) / bb_width, 1- (dz  / amount) )
            ];
        } else {
            return [
                new THREE.Vector2( (ay - bb_minY) / bb_height, 1-(az / amount )),
                new THREE.Vector2( (by - bb_minY) / bb_height, 1-(bz / amount )),
                new THREE.Vector2( (cy - bb_minY) / bb_height, 1-(cz / amount )),
                new THREE.Vector2( (dy - bb_minY) / bb_height, 1-(dz / amount ))
            ];
        }`
于 2013-11-01T16:25:50.910 に答える