创建一个追踪摄像机(2)
為了生成曲線,函數(shù)需要通過4個在沿著重量值在0和1之間的路徑上連貫的位置。由于重量在這些2個值之間增加,曲線返回在更遠的路徑上的坐標(biāo)。
當(dāng)所提供的重量值為0,曲線將返回正確的坐標(biāo)在第二個輸入坐標(biāo)。當(dāng)所提供的重量值為1,曲線將返回一個準(zhǔn)確的坐標(biāo)在第三個輸入位置。然而,所有4個值在這些計算中來使用, 來確保在第二個和第三個位置之間的平滑路徑,并同樣向前進到下一組運行點。
這個可以使用圖表來舉例說明,在圖所示。如果使用點0,1,2和3來計算曲線,重量在0.0,由此產(chǎn)生的位置會是1。如果重量增加到1.0,曲線坐標(biāo)軌跡將沿著在點1和點2之間的線,當(dāng)重量到達1.0,將到達點2。注意,從這個點的,曲線坐標(biāo)沒有返回值在線上,朝點0或點3,即使它們將通過曲線函數(shù):這些外部點僅使用來計算在中心的2個點之間的曲線角度。
一旦重量到達1.0,曲線可以移動到下一組點,進入點1,2,3和4。然后重量再次從0.0增加到1.0后,導(dǎo)致計算的坐標(biāo),沿著點2和點3之間的線。
從這組點,它不可能返回在點0和1之間的曲線坐標(biāo),或者在點4和5之間(圖表中顯示灰色),有要處理的路徑這些部分的不足外部點。
通過在點到點之間的移動路徑,一個平滑曲線可以減少,穿過所有定義的位置。這一切在三維空間也能做的很好。
提示:當(dāng)定義一個路徑,別忘記它將采取完全相同的大量時間在每一個連貫的路徑點之間移動。因此,你應(yīng)該嘗試去確保點近似等距。點有不同于其它的大的差距將導(dǎo)致更快的移動,在固定時間間隔內(nèi)穿過增加的距離,點更接近在一起將導(dǎo)致移動緩慢,因為少距離必須要去移動。
為了創(chuàng)建一個封閉的路徑,允許飛機去循環(huán),無縫的回到它最初的點再重新開始,我們必須確保最終的曲線的三個點與三個點的第一個相同。當(dāng)三個點的重量到達1.0時,曲線坐標(biāo)將終于到達回正確的在移動路徑上的點1的位置,允許整個路徑從再次從最開始就可以被跟蹤。
我們在PaperPlaneObject代碼中實現(xiàn)它,通過存儲2個類級變量,一個int值稱為_splineIndex,它定義4個點的第一個索引來使用曲線計算;一個浮點值稱為_splineWeight,它允許我們來沿著曲線在定義點之間穿過路徑。
在Update函數(shù)中,我們添加一個小的總額到_splineWeight變量中。如果它到達或超過1.0,我們要將它減1.0,并增加_splineIndex。如果_splineIndex通過移動路徑的最后的數(shù)組點,它重新設(shè)置回開始。這些更新沿著曲線移動飛機,并當(dāng)它到達它的移動路徑的重點后,重新設(shè)置回起點。
在這些更新模式下,我們調(diào)用GetPlanePosition函數(shù)來執(zhí)行曲線計算,并返回最終飛行坐標(biāo)。這個函數(shù),期望曲線索引和曲線重量值來作為參數(shù)來傳遞,下面代碼將描述。
private Vector3 GetPlanePosition(int splineIndex, float splineWeight) {Vector3 ret;// If the weight exceeds 1, reduce by 1 and move to the next index if (splineWeight > 1){splineWeight -= 1;splineIndex += 1;}// Keep the spline index within the array boundssplineIndex = splineIndex % _movementPath.Length;// Calculate the spline positionret = Vector3.CatmullRom(_movementPath[splineIndex],_movementPath[(splineIndex + 1) % _movementPathLength],_movementPath[(splineIndex + 2) % _movementPathLength],_movementPath[(splineIndex + 3) % _movementPathLength], splineWeight);return ret; }這代碼首先檢查曲線重量是否大于1。如果是,它就減去1并且切換到下一個曲線索引(我們將一會兒看到這個原因)。其次是檢查循環(huán)曲線索引,是否它超過_movementPath數(shù)組項目的界限。
曲線坐標(biāo)然后會簡單的計算,通過傳遞4個矢量坐標(biāo)和曲線重量到Vector3.CatmullRom函數(shù)。注意,然而,因為我們在曲線索引指上使用指數(shù)運算符,如果它們超過數(shù)組長度,它們會循環(huán)回到最初的開始。這個運算允許我們?nèi)崿F(xiàn)我們的閉合環(huán)路(要求重復(fù)前3個點),而不必實際在數(shù)組中重復(fù)它們:它們只是一開始就重復(fù)使用,當(dāng)?shù)竭_數(shù)組末尾時。
隨著有能力手動去計算飛行坐標(biāo),我們現(xiàn)在可以設(shè)置飛行的坐標(biāo)和沿著軌跡去平滑移動。這是好的開始,但這是非常明顯的可視化問題,當(dāng)它在運動時:飛行總是對著同一個方向。當(dāng)然,總是朝著移動的方向(紙飛機通常來說不會側(cè)面飛行的很好)。
幸運的是,這是非常容易讓飛行看上去它是正在飛行的。我們需要做的第一件事是計算另一個飛行坐標(biāo),僅遠一點沿著軌跡。我們通過調(diào)用GetPlanePosition函數(shù),在1秒鐘內(nèi)來完成它,這個時候添加0.1到曲線重量中。此外的原因是GetPlanePosition函數(shù)檢查是否重量超過1.0,因為這一秒可以引起溢出的發(fā)生。
第二個調(diào)用允許我們看到現(xiàn)在在哪里飛行,下一秒后將會在哪里。飛行的方向必須從這些點到下一秒所在的點,因為它的軌跡是移動的。因此我們需要一個旋轉(zhuǎn)飛機的方法以便它面朝從第一個位置到下一個秒所要到的位置。
這個旋轉(zhuǎn)可以使用另一個便利的靜態(tài)的矩陣函數(shù)來完成:CreateWorld。CreateWorld函數(shù)創(chuàng)建一個世界矩陣(它是最后我們要在每一個對象的Update方法中嘗試去做的)以便它放置在特別的位置上,面對特別的方向。這就是我們所需要的:位置是我們已計算出來的第一條曲線,方向從這到下一條曲線點。
通過從下一個位置減去當(dāng)前位置來簡單計算方向。由此產(chǎn)生的矢量準(zhǔn)備作為參數(shù)傳遞給CreateWorld。
有一個小問題任然存在:飛機是持續(xù)向一側(cè)飛行的,因為它的一側(cè)已經(jīng)在SketchUp模式下定義了。要修正這個問題,矩陣計算后,我們簡單旋轉(zhuǎn)90度角來旋轉(zhuǎn)它。
計算位置和飛行方向的完整代碼如下代碼所示。
// Calculate the current position and store in the Position property Vector3 Position = GetPlanePosition(_splineIndex, _splineWeight);// Calculate the next position too so we know which way we are moving Vector3 nextPosition = GetPlanePosition(_splineIndex, _splineWeight + 0.1f);// Find the movement direction Vector3 delta = nextPosition - Position;// Create the world matrix for the plane Transformation = Matrix.CreateWorld(Position, delta, Vector3.Up); // The plane needs to be rotated 90 degrees so that it points // forward, so apply a rotation ApplyTransformation(Matrix.CreateRotationY(MathHelper.ToRadians(-90)));最終結(jié)果是我們有一個平滑的逼真的在房屋間圍繞場景飛行。你可以通過運行ChaseCam工程看到實際效果—最初的視圖使用一個不會追逐飛行軌跡的相機,而是慢慢的環(huán)繞這個場景,允許簡單的看到飛行軌跡。
轉(zhuǎn)載于:https://www.cnblogs.com/appleseeker/archive/2012/05/24/e5889be5bbbae4b880e4b8aae8bfbde8b8aae69184e5838fe69cba2.html
總結(jié)
以上是生活随笔為你收集整理的创建一个追踪摄像机(2)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Retina时代的前端视觉优化
- 下一篇: ZOJ1221 Risk 图形的遍历