2016-04-04 26 views
0

Üç.js'de üç koordinat belirterek bir spline çizebilirim: başlangıç, orta ve son. Bu şekilde, eğri 'start' koordinatlarından başlar, ortalığa kadar yükselir ve 'son' koordinatlarına düşer. Bu, jsbin için aynıdır. Bununla birlikte, şimdi sadece spline'ın sadece yarısını, yani 'orta' dan 'son' kısmına kadar olan kısmı çizmek istiyorum.3.js'de yalnızca spline'ın yarısının nasıl çizileceğini gösterir

Bu geleneksel spline. enter image description here

Ancak, aşağıdaki gibi sadece düşen yarısını almak istiyorum, ancak sahneyi uydurmak istiyorum. enter image description here

DÜZENLEME: 'sahne uygun' tek düşen kısım isteyen hakkında bahsedilen

<html> 
<body> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r75/three.js"></script> 

<script> 
    // global variables 
    var renderer; 
    var scene; 
    var camera; 
    var geometry; 

    var control; 

    var count = 0; 
    var animationTracker; 

    init(); 
    drawSpline(); 

    function init() 
    { 
     // create a scene, that will hold all our elements such as objects, cameras and lights. 
     scene = new THREE.Scene(); 

     // create a camera, which defines where we're looking at. 
     camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000); 

     // create a render, sets the background color and the size 
     renderer = new THREE.WebGLRenderer(); 
     renderer.setClearColor(0x000000, 1.0); 
     renderer.setSize(window.innerWidth, window.innerHeight); 

     // position and point the camera to the center of the scene 
     camera.position.x = 0; 
     camera.position.y = 40; 
     camera.position.z = 40; 
     camera.lookAt(scene.position); 

     // add the output of the renderer to the html element 
     document.body.appendChild(renderer.domElement); 
    } 

    function drawSpline(numPoints) 
    { 
     var numPoints = 100; 
//  var start = new THREE.Vector3(-5, 0, 20); 
     var start = new THREE.Vector3(-5, 0, 20); 
     var middle = new THREE.Vector3(0, 35, 0); 
     var end = new THREE.Vector3(5, 0, -20); 

     var curveQuad = new THREE.QuadraticBezierCurve3(start, middle, end); 

     var tube = new THREE.TubeGeometry(curveQuad, numPoints, 0.5, 20, false); 
     var mesh = new THREE.Mesh(tube, new THREE.MeshNormalMaterial({ 
      opacity: 0.9, 
      transparent: true 
     })); 

     scene.add(mesh); 
     renderer.render(scene, camera); 
    } 
</script> 
</body> 
</html> 

aşağıdaki kodu ekleme. Demek istediğim, düşen görüntünün, tüm resmin şimdi işgal ettiği kadar yer kaplamasıydı. Aksi takdirde, eğer spline'dan 'mid' sonra sadece köşeleri kırpacak olsaydı, o zaman spline'ın kısmı, aşağıdaki ikinci resimde olduğu gibi (boya kullanılarak kesilir) çok küçük olurdu.

+0

Elimde, jsBin'iniz herhangi bir çıktı üretmiyor. Ayrıca, jsBin'iniz 3 işlevi tanımlar: init, drawLine ve drawSpline, ancak drawLine asla çağrılmaz/çağrılmaz. –

+0

@AndrewWillems, çıktıyı göremediğiniz için üzgünüz. Bir kez daha kontrol ettim ve görebiliyorum. Yukarıdaki kodu yazdınız. Evet, drawLine() gerekli değildir, bunu göz ardı edebilirsiniz. – PepperBoy

+0

Sadece bildiğiniz gibi ... yorumunuzu/yanıtınızı aldıktan sonra kontrol ettim ve jsBin'iniz Firefox'ta çalışmıyor (v45.0.1) ancak Chrome'da çalışır (V49.0.2623.87). –

cevap

1

3d quadratic bezier eğrisinin yarısını (veya herhangi bir oranını) çekmenin bir yolunu aşağıda gösteriyorum. Matematik DeCasteljau'nun algoritmasına dayanmaktadır (eğer doğru anlıyorsam). Matematik, kodda eklediğim ekstra işlevlerde, diğer bir deyişle splitQuadraticBezierCurve ve getPointAtT'da gösterilmektedir. THREE.js, getPointAtT, özellikle getPoint benzeri bir şey yapan bazı işlevlere sahiptir ve ayrıca getTangent işlevi de vardır. Ancak, getTangent'u nasıl kullanacağımı henüz tam olarak bilmiyorum, bu yüzden sadece matematiği kendim uyguladım. Bu zaten zor değil.

enter image description here

vektör (veya nokta) için v standları, ve v0, v1 ve v2 başlangıçtaki elde edilmiştir,:

eğrisi bölme gerisinde yatan temel prensip daha aşağıdaki şemada anlaşılabilir ikinci dereceden eğri ve orijinal start, middle ve end puanlarıdır. v01 ve v12, belirtilen satırlar boyunca t (sizin durumunuzda, 0,5) bir mesafedir ve v012, v01 ve v12 arasındaki bir mesafe t'dur. Fonksiyon, orijinal ikinci dereceden eğrinin ilk (eleman 0) ve ikinci (eleman 1) 'yarıları' ile 2 elemanlı bir dizi döndürür. İlk 'yarı' eğrinin başlangıç, orta ve bitiş noktaları, v0, v01 & v012'dur. İkinci 'yarım' eğri için başlangıç, orta ve bitiş noktaları v012, v12 & v2'dur.

kodu ikinci 'yarı' eğrisi için aşağıdaki görüntüyü verir:

enter image description here

Bu görüntü el kırpılır. Ekranı "doldurmak" için şekil almak el ile yapıldı. Bunu yapmak için "doldurma" programlı olarak değişmekle ve/veya isteyerek ve/veya değiştirerek neyle ilgilendiğinize bağlıdır: kameranın konumu?kameranın açısı? kameranın görüş alanı? nesnenin pozisyonu? Görünüm genişliği/yükseklik/oranlar? Böylece, ben buna hitap etmedim. Ancak, bu cevabın en azından ikinci dereceden bir bezier eğrisini nasıl böleceğinizi göstereceğini umuyorum.

// global variables 
var renderer; 
var scene; 
var camera; 
var geometry; 

var control; 

var count = 0; 
var animationTracker; 

init(); 
drawSpline(); 

function init() 
{ 
    // create a scene, that will hold all our elements such as objects, cameras and lights. 
    scene = new THREE.Scene(); 

    // create a camera, which defines where we're looking at. 
    camera = new THREE.PerspectiveCamera(20, window.innerWidth/window.innerHeight, 0.1, 1000); 

    // create a render, sets the background color and the size 
    renderer = new THREE.WebGLRenderer(); 
    renderer.setClearColor(0x000000, 1.0); 
    renderer.setSize(window.innerWidth, window.innerHeight); 

    // position and point the camera to the center of the scene 
    camera.position.set(0, 40, 40); 
    camera.lookAt(new THREE.Vector3(0, 15, 0)); 

    // add the output of the renderer to the html element 
    document.body.appendChild(renderer.domElement); 
} 

function getPointAtT(vA, vB, t) { 
    return new THREE.Vector3(
     vA.x + (vB.x - vA.x) * t, 
     vA.y + (vB.y - vA.y) * t, 
     vA.z + (vB.z - vA.z) * t 
    ); 
} 

function splitQuadraticBezierCurve(quad, t) { 
    var v0 = quad.v0; 
    var v1 = quad.v1; 
    var v2 = quad.v2; 
    var v01 = getPointAtT(v0, v1, t); 
    var v12 = getPointAtT(v1, v2, t); 
    var v012 = getPointAtT(v01, v12, t); 
    var firstHalf = new THREE.QuadraticBezierCurve3(v0, v01, v012); 
    var secondHalf = new THREE.QuadraticBezierCurve3(v012, v12, v2 ); 
    return [firstHalf, secondHalf]; 
} 

function drawSpline() 
{ 
    var numPoints = 100; 
    var start = new THREE.Vector3(-5, 0, 20); 
    var middle = new THREE.Vector3(0, 30, 0); 
    var end = new THREE.Vector3(5, 0, -20); 

    var curveQuad = new THREE.QuadraticBezierCurve3(start, middle, end); 
    var FIRST_HALF = 0; 
    var SECOND_HALF = 1; 
    var curveProportion = 0.5; 
    var secondHalfCurveQuad = splitQuadraticBezierCurve(curveQuad, curveProportion)[SECOND_HALF]; 
    var tube = new THREE.TubeGeometry(secondHalfCurveQuad, numPoints, 0.5, 20, false); 
    var mesh = new THREE.Mesh(tube, new THREE.MeshNormalMaterial({ 
     opacity: 0.9, 
     transparent: true 
    })); 

    scene.add(mesh); 
    renderer.render(scene, camera); 
} 
+0

çok teşekkürler Andrew. Bu çok kullanışlı ve şıktı. – PepperBoy

İlgili konular