日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

GL绘制自定义线条3_自定义线帽

發布時間:2024/5/14 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 GL绘制自定义线条3_自定义线帽 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

安卓Path搭配Paint可以設置線帽,我想能不能把我自己的線條繪制Demo也加上類似的功能。

線頭規則描述:

????????1、設一個線寬一半的線段,坐標為(0, 0)到(-lineWidth / 2, 0)。

????????2、設步驟1的線段有一垂直于它的向量(0,1),然后傳入最近兩次觸摸坐標,并將第二次觸摸坐標減去第一次觸摸觸摸坐標,得到當前畫線的前進方向向量,然后求與(0, 1)向量夾角。

????????3、以從步驟2中得到的夾角,到該夾角+180度為止,以一定的角度步進量旋轉步驟1的線段,形成一個切合線段的半圓。

????????4、最后添加一個(-lineWidth / 2, 0)到(lineWidth / 2, 0)的線段并旋轉到步驟3的最終角度,方便和線段本體對接。

線尾規則描述:

????????1、只需把線頭的規則中的步驟二改為,最后一次的之前一次的觸摸坐標 減去 最后一次的觸摸坐標作為方向向量即可(和前進方向相反)。

????????2、去冗余處理,每前進一次,就把之前添加的線尾半圓頂點刪掉。

????????關鍵代碼:

????????

/**給線頭添加符合線寬的邊界,便于和纖體本身鏈接**/private void lineCapAddBorder(double angle, float firstVec[], List<float[]> newVecs) {try {float rotatedVec0[] = rotate2d(new float[] {-mLineWidth / 2f, 0}, angle + 180);float rotatedVec1[] = rotate2d(new float[] {mLineWidth / 2f, 0}, angle + 180);float newVec[] = new float[6];//偏移到對應位置newVec[0] = rotatedVec0[0] + firstVec[0];newVec[1] = rotatedVec0[1] + firstVec[1];newVec[3] = rotatedVec1[0] + firstVec[0];newVec[4] = rotatedVec1[1] + firstVec[1];newVecs.add(newVec);} catch (Exception e) {e.printStackTrace();}}/**繪制線頭* @param isHead 是否曲線頭部添加線帽,否則視為曲線尾部添加線帽**/private int lineCap(boolean isHead, @NonNull float firstVec[], @NonNull float secVec[], int color) {if (null == firstVec) {return -1;}if (mHeadPointBuf == null) {mHeadCapPointByteBuffer = ByteBuffer.allocateDirect(mHeadInitVertexCount * 4); //頂點數 * sizeof(float)mHeadCapPointByteBuffer.order(ByteOrder.nativeOrder());mHeadPointBuf = mHeadCapPointByteBuffer.asFloatBuffer();mHeadPointBuf.position(0);mHeadCapPointBufferPos = 0;}//按初始化大小初始化RGBA字節數組和RGBA數組if (mHeadColorBuf == null) {mHeadCapColorByteBuffer = ByteBuffer.allocateDirect(mHeadInitColorCount * 4);mHeadCapColorByteBuffer.order(ByteOrder.nativeOrder());mHeadColorBuf = mHeadCapColorByteBuffer.asFloatBuffer();mHeadColorBuf.position(0);mHeadCapColorBufferPos = 0;}/**1、了解線條開始的方向,將半徑線條繞旋轉該方向與標準測量用向量的夾角的角度量* 2、旋轉180度時按照一定步進產生多個頂點,todo 但怎么確定旋轉的方向是順時針還是逆時針?以什么為依據判斷?以傳入向量方向為參考,但具體怎么做?*/float initVert[] = new float[] { //初始時左端點的坐標,初始時在原點兩側,然后以傳入的頂點作為偏移量-mLineWidth / 2f, 0};//旋轉并在過程中產生頂點float actualVec[] = new float[3];actualVec[0] = secVec[0] - firstVec[0];actualVec[1] = secVec[1] - firstVec[1];double angle = calcAngleOfVectorsOnXYPanel(mStandardVec, actualVec); //對比基準向量旋轉了多少度int step = 6; //改成只有90度可以得到一個尖頭筆帽List<float[]> newVecs = new LinkedList<>();if (!isHead) {//給曲線結尾加一段和線寬等長的邊lineCapAddBorder(angle, firstVec, newVecs);}//半圓線頭for (double degreeBias = angle; degreeBias <= 180 + angle; degreeBias += step) {try {float rotatedVec[] = rotate2d(initVert, degreeBias);float newVec[] = new float[6];//偏移到對應位置newVec[0] = rotatedVec[0] + firstVec[0];newVec[1] = rotatedVec[1] + firstVec[1];newVec[3] += firstVec[0];newVec[4] += firstVec[1];newVecs.add(newVec);} catch (Exception e) {e.printStackTrace();}}if (isHead) {//給曲線開頭加一段和線寬等長的邊lineCapAddBorder(angle, firstVec, newVecs);}for (float[] newVec : newVecs) {for (int i = 0; i < newVec.length; i++) {checkCapacity();mPointBuf.put(mPointBufferPos++, newVec[i]);}for (int i = 0; i < newVec.length / 3; i++) {checkCapacity();//寫入顏色值r,g,b,afloat alpha = (float) (((color & 0xFF000000) >> 24) & 0x000000FF) / 255f;float blue = (float) ((color & 0x000000FF)) / 255f;float green = (float) ((color & 0x0000FF00) >> 8) / 255f;float red = (float) ((color & 0x00FF0000) >> 16) / 255f;mColorBuf.put(mColorBufferPos++, red);mColorBuf.put(mColorBufferPos++, green);mColorBuf.put(mColorBufferPos++, blue);mColorBuf.put(mColorBufferPos++, alpha);}}return newVecs.size() * newVecs.get(0).length;}

最后效果:

旋轉步進設定為90度,因此能顯示尖頭效果:

?設定為15度,則可以形成非常圓潤的線頭:

以線條方式繪制,即可看到頂點構成如下圖:

?基本再現了Android path + paint的大部分線條效果了。

總結

以上是生活随笔為你收集整理的GL绘制自定义线条3_自定义线帽的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。