Polygon vertices as UV coordinates

I am working on a 3D renderer in Java using the Graphics class. Now he is able to draw any shape with colored faces, but I was wondering if it is possible to texture the faces? I saw a lot of people creating software visualization tools in Javascript, so of course there is an equivalent function / method, however they do it in Java ...
I have looked around so far, but all I can find is Graphics.setClip (Shape), I don’t think it would be suitable because it just sets the background textures and does not stretch the texture if you move the vertex - and that’s just in 2D, you also need to stretch / skew the texture when it is at an angle to the camera (think about the sides of the rotating cube).

I really don’t know where to start, I can’t use XOR modes due to the lack of skew, and I really wouldn’t know how to do the math if I had to do it manually.
How do these Javascript software handlers do this so well?

+6
source share
3 answers

You might be able to use java.awt.TexturePaint , illustrated here and here . In this context, you should know that TexturePaint aligns with raster rendering, not with the borders of the form.

image

Addendum: Although shading is a wide topic, we KineticModel also look at the pixel-based gradient gradient shading approach shown in KineticModel here . Note that such a gradient can be applied to WritableRaster a TexturePaint .

For non-affine transformations see javax.media.jai.Warp.Warp , cited here .

+7
source

I saw this as a “reserve” for the OpenGL function, which did not start on some machines due to problems with the JOGL. I have not been successful. These were unresolved issues that caused me to stop working:

  • Hidden surface removal. I could not find a way to implement the z buffer under Graphics2d primitives.

  • Prospective textures are converted. AffineTransform, available in Graphics2d, is powerful enough to display textures if the image projection is parallel but not promising.

  • Clipping mismatch 2d. The last texturing operation should be trimmed against the 2d mask. It turns out there is an error in cropping Graphics2d. If you make a clip against perfectly adjacent 2d polygons, cropped patches do not fit perfectly. Individual pixels at the border are asymmetrical.

  • Performance

    . While the latest versions of the Graphics2d pipeline are trying to use hardware acceleration, if it is there, the raw rendering of polygons was still tested an order of magnitude slower than JOGL, which was not enough for my purposes.

The Javascript 3d libraries I looked at are all built on WebGL, which in turn are implemented in Canvas HTML 5 objects. WebGL is the OpenGL API that must be implemented by the browser. Other 3d Javascript libraries use plug-ins for receiving graphics with hardware acceleration. Therefore, they are not a useful source of information on how to do 3D in Swing.

Adding

Maybe it's worth adding what I did. To replace the 3D JOGL scene that the user can fly by moving the camera, I chose a single fixed viewpoint and a hard-wired drawing order, effectively implementing the Painter Algorithm with fixed logic to determine the sort order, providing more or less the same models as the JOGL view. I implemented Gouraud shading using gradient polygons where I found the cropping error mentioned above. It all works and works in hundreds of thousands of copies, but it is messy and fragile, and I don't want to repeat it again.

+5
source

I assume that you are using only Swing / AWT frames for graphics. If this is not the case, please update your question.

If you use Swing and the Graphics2D class (which uses the components of the swing class), you are dealing with a 2D framework. It just means that the fantastic 3D material is not built-in - you will have to implement the transformations yourself (or start capturing 3D classes to do your job).

So, you are on the right track - you need to first set the clip (so that it matches your shape), and then perform the rotation (therefore, it is displayed at the right angle).

Saying this, making basic rotary transformations is not so difficult. There is a good outline of the (main) turns here . Of course, this gets a little trickier if you have turns based on more than just one axis. But, as explained later in the article, if you multiply matrices (Rx) (Ry) (Rz), you can use the resulting matrix to determine the location of your pixel.

I created a quick example with rotation along the Y axis. Notice that I compiled a silent algorithm (Magic Vanishingpoint Technology®) to give a vague illusion of depth. I assume that you already have something for this - this is probably more correct.

 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); } } 
+2
source

All Articles