在canvas 2D API下實現3D效…

原文:http://www.cssass.com/blog/index.php/2011/976.html

html5的canvas爲我們提供了瀏覽器原生支持的繪圖API。
(或者怎麼說呢,大多數瀏覽器已經爲我們提供了原生的繪圖API:HTML5的canvas)
目前,這個API只提供2D context,並不支持3D繪圖,但是web上從來就不缺牛人,各種canvas下繪製的3D效果層出不窮,令人吱吱稱讚。
有3D聖誕樹:http://www.romancortes.com/blog/how-i-did-the-1kb-christmas-tree
有3D的FPS:使用 HTML 5 canvas 和光線投影算法創建僞 3D 遊戲
還有3D俄羅斯:http://www.benjoffe.com/code/games/torus/
不勝枚舉…

其實,無論canvas是否提供API,在我們目前這種二維顯示設備下顯示,勢必都要將3維形狀投影到2維平面座標上。無論多炫的3D效果也只是二維平面上的投影。
對於此,讀過《三體》特別是第三部《死神永生》的同學或許會大有感觸吧。

人們總是喜歡用這樣一個類比:想象生活在三維空間中的一張二維平面畫中的扁片人,不管這幅畫多麼豐富多彩,其中的二維人只能看到周圍世界的側面,在他們眼 中,周圍的人和事物都是一些長短不一的線段而已。只有當一個二維扁片人從畫中飄出來,進人三維空間,再回頭看那幅畫,才能看到畫的全貌。
這個類比,其實也只是進一步描述了四維感覺的不可描述。

關於《三體——死神永生》裏四維空間(不算時間維)的討論,這裏還有篇有意思的博文:四維世界的堵車問題

好了,言歸正傳。
下面提供一個三維到二維的投影算法(from www.benjoffe.com):

var theta = 4.2; //轉角
var eleva = 0.6; //仰角
function iso(x,y,z){
var dist = Math.sqrt(x*x+y*y);
var angle = (x==0 && y==0) ? 0 : Math.atan(y/x) + theta + ((x<0)? Math.PI : 0);

x=Math.cos(angle)*dist;
y=-Math.sin(angle)*dist;
var fact = (y*Math.cos(eleva) + z*Math.sin(eleva)+8)/8;
y=y*Math.sin(eleva) - z*Math.cos(eleva);
x*=fact;
y*=fact;

return {
x: x,
y: y
};
}

輸入是x,y,z三個三維座標下的值,輸出是x,y兩個二維座標值。

我們應用一下:
下面是一個3D球

以上代碼是對球面的方程 x^2+y^2+z^2=r^2進行求解,將解(x,y,z)代入iso方法,最後根據輸出二維座標進行繪圖。
對於這個球面方程的解法,也是各有各的寫法。
(這裏有個Functions 3D的應用,用來將方程式輸出成3D圖形:http://www.benjoffe.com/code/tools/functions3d/

如果你知道這篇文章的話:笛卡爾情書的祕密——心形函數的繪製
我相信你也很可能知道網上還有一個3D版是心形函數:(x^2 + (9/4)y^2 + z^2 – 1)^3 – x^2*z^3 – (9/80)y^2*z^3 = 0
下面我將使用上面的iso方法在canvas中繪製出來。

我都給你畫了這麼多心了,難道非得讓我把自己的心掏出來嗎~~~~

咳咳…

回來,我們知道,三維空間下的座標系不止直角座標一種,還有 圓柱座標系,球座標系等等。
下面我們將iso方法轉換一下,是輸入使用球座標系值(θ,Φ,r)——轉角,仰角,球半徑。
首先我們先要知道,三維直角座標系於球座標系的換算式:

x=rsinθcosφ  
y=rsinθsinφ   
z=rcosθ

呃哦…
代入iso函數後我們發現iso變的更簡單了:

var theta = 4.2; //轉角
var eleva = 0.6; //仰角
function iso(a,b,r){
var x,y,z
x=r*Math.cos(a+this.theta)*Math.sin(b);
y=r*Math.sin(a+this.theta)*Math.sin(b);
z=r*Math.cos(b);

var fact = (y*Math.cos(this.eleva) + z*Math.sin(this.eleva)+8)/8;
y=y*Math.sin(this.eleva) + z*Math.cos(this.eleva);
x*=fact;
y*=fact;
return {
x: x,
y: y
};
}

下面是我們使用球座標系繪製的三維圖形(三維投射到二維的圖形)

標籤: 3D, canvas, html5, 心形函數, 投影算法

這篇文章發佈於 2011年02月24號,星期四,17:36,歸類於 Html, Javascript。 您可以跟蹤這篇文章的評論通過 RSS 2.0 feed。 您可以留下評論,或者從您的站點trackback

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章