簡體   English   中英

多邊形頂點作為UV坐標

[英]Polygon vertices as UV coordinates

我正在使用Graphics類在Java中使用3D渲染器,它現在能夠繪制任何帶有彩色面的形狀,但是我想知道是否可以對面進行紋理化? 我見過很多人在Javascript中創建軟件渲染器,所以肯定有一個等效的函數/方法,但是他們在Java中這樣做...
到目前為止我已經環顧四周但是我能找到的只是Graphics.setClip(Shape),我覺得它不合適,因為它只是設置背景紋理,如果頂點移動也不會拉伸紋理 - 這只是在2D中,當與相機成一定角度時,它還需要拉伸/傾斜紋理(想想旋轉立方體的兩側)。

我真的不知道從哪里開始,我不能使用XOR模式,因為沒有傾斜,如果我不得不手動操作,我真的不知道如何進行數學運算。
這些Javascript軟件渲染器如何做得這么好?

您可以利用java.awt.TexturePaint這里這里說明。 在這種情況下,您應該知道TexturePaint與渲染表面的柵格對齊,而不是與形狀的邊界對齊。

圖片

附錄:雖然陰影是一個廣泛的話題,也可以考慮使用具有α梯度着色的基於像素的方法中,示出在KineticModel引用在這里 請注意,這樣的漸變可以應用於TexturePaintWritableRaster

有關非仿射變換,請參閱此處引用的javax.media.jai.Warp.Warp

我把這看作是一個OpenGL功能的“后備”,由於JOGL問題而無法在某些機器上運行。 我沒有成功。 這些是導致我停止工作的未解決的問題:

  • 隱藏表面去除。 我找不到在Graphics2d原語下實現z-buffer的方法。

  • 透視紋理變換。 如果圖像投影是平行的,而不是透視,則Graphics2d中可用的AffineTransform具有足夠的力量來映射紋理。

  • 2d剪輯中的不匹配。 紋理化的最后一個操作必須是對2d掩碼進行裁剪。 事實證明,Graphics2d剪輯中存在一個錯誤。 如果您剪切完全相鄰的2d多邊形,則剪裁的補丁不能完美匹配。 邊界處的單個像素沒有陰影。

  • 性能。 雖然最近版本的Graphics2d管道嘗試使用硬件加速,但是原始多邊形渲染仍然比JOGL慢了一個數量級,這對我的目的來說還不夠好。

我看過的Javascript 3d庫都是基於WebGL構建的,而WebGL又是在HTML 5 Canvas對象中實現的。 WebGL是一個必須由瀏覽器實現的OpenGL API。 其他3d Javascript庫使用插件來獲取硬件加速圖形。 因此,它們不是有關如何在Swing中執行3d的有用信息來源。

加成

也許值得添加我所做的事情。 為了替換用戶可以通過移動相機“飛過”的3D JOGL場景,我選擇了單個固定視點和“硬連線”繪圖順序,有效地實現具有固定邏輯的Painter算法來確定排序順序,渲染更多 - 或者與JOGL視圖相同的模型。 我使用漸變填充多邊形實現了Gouraud着色,這是我發現上面提到的剪輯錯誤的地方。 它一切正常,並且運行了數十萬份,但是它既凌亂又脆弱,我不想再這樣做了。

我假設您只使用Swing / AWT框架進行圖形處理。 如果這是錯誤的,請更新您的問題。

如果您正在使用Swing和Graphics2D類(這是類擺動組件使用),那么您正在處理2D框架。 這只意味着沒有內置花哨的3D東西 - 你必須自己實現轉換(或者開始抓取3D類來完成你的工作)。

因此,您處於正確的軌道上 - 您必須先設置剪輯(因此它適合您的形狀),然后執行旋轉(因此它以正確的角度顯示)。

話雖這么說,做基本的旋轉變換並不太難。 還有的(基本)轉好提綱這里 當然,當您的旋轉不僅僅基於一個軸時,它會變得有點復雜。 但正如文章后面解釋的那樣,如果將矩陣(Rx)(Ry)(Rz)相乘,則可以使用生成的矩陣來確定像素位置。

我創建了一個在Y軸上旋轉的快速示例。 請注意我制作了一個愚蠢的算法( MagicVanishingpointTechnology® )來給出模糊的深度幻覺。 我假設你已經有了一些東西 - 它可能更正確。

import java.awt.*;
import java.awt.image.*;
import java.io.*;

import javax.imageio.ImageIO;
import javax.swing.*;

public class Rotation3D extends JPanel{
    Image img;

    BufferedImage rotatedImage;
    final int ROTATION_DEGREES = 70;

    int vanishX = 0;
    int vanishY = 0;
    int vanishZ = -1000;

    public Rotation3D(){

        try {
            //Grabbed an image from the java folder - hopefully your computer has it
            img = ImageIO.read(new File(System.getProperty("java.home") + "/lib/deploy/splash.gif"));
            setPreferredSize(new Dimension(img.getWidth(this) * 2,img.getHeight(this) * 2));

            //Create a buffered image with the appropriate size, and draw the image on it
            BufferedImage shadedImage = new BufferedImage(img.getWidth(this), img.getWidth(this), BufferedImage.TYPE_INT_ARGB);
            shadedImage.getGraphics().drawImage(img, 0, 0, this);
            Raster r = shadedImage.getData();

            //Not really necessary unless you're using Magic Vanishingpoint Technology®
            vanishX = shadedImage.getWidth() /2;
            vanishY = shadedImage.getHeight() /2;

            //Create a Wraster for the transformed image
            WritableRaster wr = r.createCompatibleWritableRaster();

            //Do the transformation
            for(int i = 0; i < shadedImage.getWidth(); i++){
                for(int j = 0; j < shadedImage.getHeight(); j++){
                    //Remapping the pixel based on a matrix rotation
                    int[] result = r.getPixel(i, j, new int[4]);
                    Double radians = Math.toRadians(ROTATION_DEGREES);
                    Double newX, newY, newZ;
                    //newX = ((i-vanishX) * Math.cos(radians)) + vanishX; // places the rotation in the middle of the image
                    // x * cos(θ) + y * 0 + z * sin(θ)
                    newX = i * Math.cos(radians); //places the rotation in the y=0 axis
                    // x * 0 + y * 1 + z * 0
                    newY = j * 1.0;
                    // x * -sin(θ) + y * 0 + z * cos(θ)
                    newZ= i * Math.sin(radians) * -1;

                    //Apply Magic Vanishingpoint Technology®
                    //(Not actually trademarked or correct - just something thrown together)
                    if(newZ < vanishZ){
                        newX = 0.0;
                        newY = 0.0;
                    }else if(newZ < 0){
                        double magicVanish =  newZ / vanishZ;
                        newX += magicVanish * newX;
                        newY += magicVanish * newY;
                    }

                    //Print the pixel if it fits on the screen to the new Raster
                    if(newX > 0 && newX < shadedImage.getWidth() && newY > 0 && newY < shadedImage.getHeight())
                        wr.setPixel(newX.intValue(), newY.intValue(), result);
                }
            }

            //Create an image based on the raster.
            rotatedImage = new BufferedImage(img.getWidth(this), img.getWidth(this), BufferedImage.TYPE_INT_ARGB);
            rotatedImage.setData(wr);

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(rotatedImage, 0, 0, this);
    }

    public static void main(String[] args){
        final JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new Rotation3D());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM