如何畫出一個(gè)旋轉(zhuǎn)的立方體

代碼地址和動(dòng)效圖

?先上代碼和圖.

github地址

?cube

?用到了什么

如果你寫過自定義view,那么你一定聽過說過Matrix,Matrix就是一個(gè)3*3的矩陣,他可以負(fù)責(zé)圖像的旋轉(zhuǎn),位移等操作.如果你對Matrix不太了解,可以去看看Matrix相關(guān).
Matrix 原理
Matrix 詳解

而Camera則是能提供"3D 版的Matrix",也就是說一個(gè)平面,可以通過Camera進(jìn)行旋轉(zhuǎn)甚至左右前后移動(dòng),然后會(huì)得到一個(gè)Matrix,該Matrix就可以讓平面產(chǎn)生形變某弦,從而達(dá)到3D的效果.
Matrix Camera

如何實(shí)現(xiàn)

如何畫出一個(gè)立方體

主要分為2步

  1. 把面旋轉(zhuǎn)成水平或者垂直
  2. 旋轉(zhuǎn)完畢后 把面移到對應(yīng)的位置
    因?yàn)?D坐標(biāo)系和2D坐標(biāo)系都位于屏幕左上角,所以要調(diào)整下中心點(diǎn).所以3D坐標(biāo)系和2D坐標(biāo)系都要調(diào)整中心點(diǎn).
    /**
     * 
     * @param position 面的序號(hào) 0~3 面的序號(hào)后面提到
     * @param canvas 
     */
    void drawCube(int position,Canvas canvas) {
        camera.save();
        //1.旋轉(zhuǎn)成水平或者垂直
        camera.rotateX(position % 2 * 90);
        //2.旋轉(zhuǎn)完畢后 把面移到對應(yīng)的位置
        switch (position) {
            case 0:
                break;
            case 1:
                camera.translate(0,100,100);
                break;
            case 2:
                camera.translate(0,0,200);
                break;
            case 3:
                camera.translate(0,100,-100);
                break;

        }
        camera.getMatrix(matrix);
        camera.restore();

        //3.由于3D坐標(biāo)系原點(diǎn)默認(rèn)是屏幕左上角, 故調(diào)整3D中心點(diǎn)洲赵。而前乘再后乘,是matrix的一個(gè)小技巧
        matrix.preTranslate(-viewWidth / 2, -viewHeight / 2);
        matrix.postTranslate(viewWidth / 2, viewHeight / 2);


        //4. 調(diào)整2D坐標(biāo)系 并且畫出正方體
        canvas.save();
        canvas.concat(matrix);
        canvas.translate(viewWidth / 2, viewHeight / 2);
        paint.setColor(colors[position % 2]);
        canvas.drawRect(rectF, paint);
        canvas.restore();
    }

確定各個(gè)面和旋轉(zhuǎn)軸

各個(gè)面的序號(hào)

結(jié)合動(dòng)效圖,可以看到立方體在旋轉(zhuǎn)的過程中,最多只能看到3個(gè)面.
首先給各個(gè)面標(biāo)上序號(hào).
0,1,2,3是立方體的旋轉(zhuǎn)的面(旋轉(zhuǎn)過程中最多展示2個(gè)面,2,3在下面的圖中無法看到,用箭頭標(biāo)示).
4是立方體的側(cè)面(始終展示).
4的對立面始終不展示我就不標(biāo)出來了


Paste_Image.png

可以看到上圖的立方體是有傾斜角,初始狀態(tài)的立方體是


Paste_Image.png
坐標(biāo)系

android的3D的坐標(biāo)系和2D是有一些不一樣的.在Matrix Camera提到過.
而該立方體的坐標(biāo)系是:

  1. 0面中心為原點(diǎn)
  2. x,y軸正方向分別是0面右方和上方
  3. 0面朝里是z軸正方向

?開始旋轉(zhuǎn)

繞Y軸旋轉(zhuǎn)45度

初始狀態(tài)的立方體有一定的傾斜角,這是因?yàn)榱⒎襟w按Y軸旋轉(zhuǎn)45度.要不然我們只能看到一個(gè)平面的正方體.

繞X軸進(jìn)行旋轉(zhuǎn)動(dòng)畫.

      //degree 是旋轉(zhuǎn)角度
    void drawCube(int position,Canvas canvas) {
        camera.save();
        camera.rotateY(45);
        camera.rotateX(degree + position % 2 * 90);
                ...
    }

各個(gè)面畫得先后順序

  1. 0~3面的繪畫順序根據(jù)旋轉(zhuǎn)角度做了特例判斷
  2. 4面最后畫
float degree = value * 360;
        if(degree >= 0 && degree < 90 ) {
            drawCube(1,canvas);
            drawCube(0,canvas);
        }

        if(degree >= 90 && degree < 135) {
            drawCube(2,canvas);
            drawCube(1,canvas);
        }

        if(degree >= 135 && degree < 180) {
            drawCube(1,canvas);
            drawCube(2,canvas);
        }

        if(degree >= 180 && degree < 225) {
            drawCube(3,canvas);
            drawCube(2,canvas);
        }

        if(degree >= 225 && degree < 270) {
            drawCube(2,canvas);
            drawCube(3,canvas);
        }

        if(degree >= 270 && degree <= 360) {
            drawCube(3,canvas);
            drawCube(0,canvas);
        }

        camera.save();
        camera.rotateY(45);
        camera.rotateX(value * 360);
        camera.rotateY(90);
        camera.translate(100,0,100);
        camera.getMatrix(matrix);
        camera.restore();

        // control center
        matrix.preTranslate(-viewWidth / 2, -viewHeight / 2);
        matrix.postTranslate(viewWidth / 2, viewHeight / 2);

        canvas.save();
        canvas.concat(matrix);
        canvas.translate(viewWidth / 2, viewHeight / 2);
        paint.setColor(0xFFFDFDE3);
        canvas.drawRect(rectF, paint);
        canvas.restore();

基本上就這樣了,主要是練習(xí)了下matrix的使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子抗果,更是在濱河造成了極大的恐慌端盆,老刑警劉巖切黔,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暮的,死亡現(xiàn)場離奇詭異,居然都是意外死亡感挥,警方通過查閱死者的電腦和手機(jī)缩搅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來触幼,“玉大人硼瓣,你說我怎么就攤上這事≈们” “怎么了堂鲤?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長霉祸。 經(jīng)常有香客問我筑累,道長,這世上最難降的妖魔是什么丝蹭? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任慢宗,我火速辦了婚禮,結(jié)果婚禮上奔穿,老公的妹妹穿的比我還像新娘镜沽。我一直安慰自己,他們只是感情好贱田,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布缅茉。 她就那樣靜靜地躺著,像睡著了一般男摧。 火紅的嫁衣襯著肌膚如雪蔬墩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天耗拓,我揣著相機(jī)與錄音拇颅,去河邊找鬼。 笑死乔询,一個(gè)胖子當(dāng)著我的面吹牛樟插,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼黄锤,長吁一口氣:“原來是場噩夢啊……” “哼搪缨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鸵熟,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤副编,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后旅赢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體齿桃,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年煮盼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片带污。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡僵控,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鱼冀,到底是詐尸還是另有隱情报破,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布千绪,位于F島的核電站充易,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏荸型。R本人自食惡果不足惜盹靴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瑞妇。 院中可真熱鬧稿静,春花似錦、人聲如沸辕狰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蔓倍。三九已至悬钳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間偶翅,已是汗流浹背默勾。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留倒堕,地道東北人灾测。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親媳搪。 傳聞我的和親對象是個(gè)殘疾皇子铭段,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容