日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

java 游戲編程 (九)

系統 2136 0
本篇主要對java處理三維圖形基本的知識做一下復習。有些地方上篇沒仔細討論。
涉及到上一篇的所有類,做一下規整,還有新的類應用描述。
1.Vector3D
這個類描述三維向量。三維向量就是(x,y,z)一個空間點,或從(0,0,0)到(x,y,z)的向量。
提供了向量加 向量減 向量乘 和向量除
還有返回了向量的長度? 空間直線的長度計算公式:根號下(x+-x1)的平方+(y+-y1)+(z+-z1)的平方
區長度方法為
        
public float length() {
        return (float)Math.sqrt(x*x + y*y + z*z);
    }

  

旋轉,比如沿x軸旋轉
    
    public void rotateX(float cosAngle, float sinAngle) {
        float newY = y*cosAngle - z*sinAngle;
        float newZ = y*sinAngle + z*cosAngle;
        y = newY;
        z = newZ;
    }

  

因為沿x軸旋轉,x的值忽略,重新對y,z賦值。
這里的形參是預先計算出來的值。
至于這個 float newY = y*cosAngle - z*sinAngle公式做如下解釋
java 游戲編程 (九)
這個圖畫的很不好,
一個點旋轉到另一個點
x=rcosb
y=rsinb
轉過角a后,x1=rcos(a+b) y1=rsin(a+b);
得到 x1=rcosbcosa-rsinbsina? 1=rsinbcosa+rsinacosb
最后
x1=xcosb-ysinb
y1=xsinb+ycosb
沿著其他軸轉一樣。
所以又了以上rotateX的計算方法。
2.ViewWindow
這個類具備了視圖窗口的功能,并且提供投影。
再議3D的數學:
3D圖形的生成就是? 三維圖形到鏡頭的連接線或向量,這些連接線經過視圖窗口,在視圖窗口成像。鏡頭離試圖窗口越近,成像效果越大,這是三角問題。這個角度可以看做鏡頭到試圖窗口的法線向量與連線的夾角。這個成像與屏幕坐標不一致,還要換算為屏幕坐標。
來看一下。
    
    public void project(Vector3D v) {
       //投影到視圖窗口
        v.x = distanceToCamera * v.x / -v.z;
        v.y = distanceToCamera * v.y / -v.z;
       //轉換為屏幕坐標
        v.x = convertFromViewXToScreenX(v.x);
        v.y = convertFromViewYToScreenY(v.y);
    }

  

這里形參 v 是具體的三維物體
改變其x和y的值,是通過三角函數等比例關系進行計算
distanceToCamera是視圖窗口到鏡頭的法線長度
經過重新復制的v.x和v.y然后換算為屏幕坐標。
convertFromViewXToScreenX方法見上以篇
z是深度坐標,忽略計算。

多邊形問題
多邊形就是一堆頂點
3.Polygon3D
這個類將多邊形表示成一堆頂點。通過Vector3D[] 存放
看看其中幾個方法
    
   public Polygon3D(Vector3D[] vertices) {
        this.v = vertices;
        numVertices = vertices.length;
        calcNormal();
    }
   public Vector3D calcNormal() {
        if (normal == null) {
            normal = new Vector3D();
        }
        temp1.setTo(v[2]);
        temp1.subtract(v[1]);
        temp2.setTo(v[0]);
        temp2.subtract(v[1]);
        normal.setToCrossProduct(temp1, temp2);
        normal.normalize();
        return normal;
    }

  

這是計算法線。法線的計算是通過求兩個向量的交積得到。至于向量交積的計算網上有。
法線有方向,方向是通過求點積得到。
為什么需要法線向量?
通過法線向量(帶方向的)與鏡頭與視圖窗口垂直線 的夾角來判斷三維物體是否正對鏡頭
如果是銳角表示正對,否則是背對。
        
    public boolean isFacing(Vector3D u) {
        temp1.setTo(u);
        temp1.subtract(v[0]);
        return (normal.getDotProduct(temp1) >= 0);
    }

  


    
    public void ensureCapacity(int length) {
        if (v.length < length) {
            Vector3D[] newV = new Vector3D[length];
            System.arraycopy(v,0,newV,0,v.length);
            for (int i=v.length; i<newV.length; i++) {
                newV[i] = new Vector3D();
            }
            v = newV;
        }
    }


  

因為初次運行數組初始化長度不夠,會引起數組越界,這個方法保證多邊形的容量可以容納多邊形頂點個數

    
    public void project(ViewWindow view) {
        for (int i=0; i<numVertices; i++) {
            view.project(v[i]);
        }
    }

  

將多邊形投影到視圖窗口。

4.Transform3D
這個類主要表示旋轉和平移,提供了三角函數算法。通過這個類計算旋轉角度后的三角函數值,并調用Vector3D的旋轉方法。
還有一個成員Vector3D location,代表了它作用于的Vector3D.

5.My3DTest1
這個類的事件監聽就不再做解釋了。
定義了幾個成員
    
    private Transform3D myTransform = new Transform3D(0,0,-500);
    private Polygon3D transformedPolygon = new Polygon3D();
    private ViewWindow viewWindow;

  

下面會提到。
    
    public void update(long elapsedTime) {
        if (exit.isPressed()) {
            stop();
            return;
        }
        elapsedTime = Math.min(elapsedTime, 100);

        treeTransform.rotateAngleY(0.002f*elapsedTime);

        if (zoomIn.isPressed()) {
            treeTransform.getLocation().z += 0.5f*elapsedTime;
        }
        if (zoomOut.isPressed()) {
            treeTransform.getLocation().z -= 0.5f*elapsedTime;
        }
    }

  


這里是沿y軸旋轉
treeTransform.rotateAngleY(0.002f*elapsedTime);
經過計算得到了cosAngleY 和 sinAngleY兩個三角函數值
看關鍵的draw方法中的
trandformAndDraw(g, p);
    
 private void trandformAndDraw(Graphics2D g,
    		Polygon3D poly)
    {
        transformedPolygon.setTo(poly);
        transformedPolygon.add(myTransform);
        transformedPolygon.project(viewWindow);
        GeneralPath path = new GeneralPath();
        Vector3D v = transformedPolygon.getVertex(0);
        path.moveTo(v.x, v.y);
        for (int i=1; i<transformedPolygon.getNumVertices(); i++) {
            v = transformedPolygon.getVertex(i);
            path.lineTo(v.x, v.y);
        }
        g.setColor(Color.red);
        g.fill(path);
    }

  


??????? transformedPolygon.setTo(poly);
??????? transformedPolygon.add(myTransform);
??????? transformedPolygon.project(viewWindow);
這三句代碼很重要。
? transformedPolygon.setTo(poly);
將多邊形中的vector全都set到transformedPloygon中
transformedPolygon.add(myTransform);
這里就是進行旋轉的功能,我進入方法內部說明一下。
add方法做了兩件事情:
1.addRotation(myTransform);
    
    public void addRotation(Transform3D myTransform) {
        for (int i=0; i<numVertices; i++) {
           v[i].addRotation(myTransform);
        }
        normal.addRotation(myTransform);
    }
	public void addRotation(Transform3D myTransform) {
		// TODO Auto-generated method stub
	     rotateX(myTransform.getCosAngleX(), myTransform.getSinAngleX());
	     rotateZ(myTransform.getCosAngleZ(), myTransform.getSinAngleZ());
	     rotateY(myTransform.getCosAngleY(), myTransform.getSinAngleY());
	}

  

這里就是我前面說道的Vector3D里面的旋轉函數方程了。經過旋轉計算后,每一個頂點都會發生坐標的轉移,也就實現了旋轉。
2.add(myTransform.getLocation());
    
    public void add(Vector3D u) {
       for (int i=0; i<numVertices; i++) {
           v[i].add(u);
       }
    }


  

3. transformedPolygon.project(viewWindow);
投影到視圖窗口
最后程序循環連線畫出了三維多邊形,并填充了顏色。

java 游戲編程 (九)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 全南县| 吉木萨尔县| 潼关县| 江津市| 余姚市| 北辰区| 翁源县| 金秀| 高雄市| 肇源县| 张北县| 丰原市| 桂平市| 分宜县| 嘉义县| 淅川县| 宁波市| 台中县| 哈尔滨市| 辛集市| 抚松县| 通渭县| 孙吴县| 温宿县| 顺昌县| 文山县| 玛纳斯县| 利津县| 太白县| 白银市| 顺昌县| 恩施市| 阜宁县| 垫江县| 酒泉市| 武穴市| 富民县| 茶陵县| 天台县| 大连市| 乳源|