Oppure

Loading
12/08/16 12:40
Bonnox
Buongiorno, ho cercato ovunque su internet ma non ho trovato molto.
Sto cercando di replicare l'effetto "mode 7" dello SNES e del GBA in software, sul computer, senza usare API. Infatti so che in java esiste una classe per le trasformazioni affini, che si possono applicare ad un'immagine per poi disegnarla. Finchè si tratta di un insieme di punti mi va anche bene, basta semplicemente moltiplicare il vettore del punto per la matrice. Ma io vorrei farlo per le immagini (leggi: texture), ma non riesco a capire che algoritmo devo usare. posso utilizzare un singolo pixel come se fosse un punto? Non verrebbe un po' "bruttino"?

E poi, domanda dal quadro più ampio:
se io avessi un piano normalissimo, e una "faccia" (un poligono giacente su un altro piano), come posso calcolare la matrice di trasformazione per la texture considerando la proiezione della faccia sul piano iniziale?

Spero di essere stato abbastanza chiaro. grazie.
Ultima modifica effettuata da Bonnox 12/08/16 12:41
aaa
15/08/16 20:55
Bonnox
up, mi servirebbe soltanto sapere un algoritmo per fare in software il texture mapping...
aaa
20/08/16 16:51
Bonnox
ho provato a fare qualcosa, ma al momento ho un paio di problemi.

package testmapping;

import java.awt.Color;

public class Texel
{
	public int		x;
	public int		y;
	public Color	clr;
					
	public Texel (int i, int j, Color c)
	{
		
		x = i;
		y = j;
		clr = c;
	}
}


package testmapping;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.util.ArrayList;

import javax.swing.JComponent;

public class DrawingPlane extends JComponent
{
	boolean					trans		= true;
										
	ArrayList<Texel[]>		immagini	= new ArrayList<Texel[]>();
	ArrayList<double[][]>	matrici		= new ArrayList<double[][]>();
										
	@Override
	protected void paintComponent(Graphics g)
	{
		// Auto-generated method stub
		super.paintComponent(g);
		
		Graphics2D g2 = (Graphics2D) g;
		
		int xglob = getSize().width;
		int yglob = getSize().height;
		
		// Point origin = new Point(xglob / 2, yglob / 2);
		
		if (!trans) paintNorm(g2);
		else
			paintAffine(g2);
	}
	
	private void paintAffine(Graphics2D g2)
	{
		for (int h = 0; h < immagini.size(); h++)
			{
				
				for (int i = 0; i < immagini.get(h).length; i++)
					{
						try
					{
						int vect[] = { immagini.get(h)[i].x, immagini.get(h)[i].y, 1 };
						
						double fin[] = new double[3];
						
						fin[0] = vect[0] * matrici.get(h)[0][0] + vect[1] * matrici.get(h)[0][1] + vect[2] * matrici.get(h)[0][2];
						fin[1] = vect[0] * matrici.get(h)[1][0] + vect[1] * matrici.get(h)[1][1] + vect[2] * matrici.get(h)[1][1];
						fin[2] = vect[0] * matrici.get(h)[2][0] + vect[1] * matrici.get(h)[2][1] + vect[2] * matrici.get(h)[2][1];
						
								// fin[0] /= fin[2];
								// fin[1] /= fin[2];
						g2.setColor(immagini.get(h)[i].clr);
						int x1 = (int) Math.round(fin[0]);
						int y1 = (int) Math.round(fin[1]);
						g2.drawLine(x1, y1, x1, y1);
							} catch (Exception e)
							{
								// System.err.println(i);
								
							}
							}
					
			}
			
	}
	
	private void paintNorm(Graphics2D g2)
	{
		for (int h = 0; h < immagini.size(); h++)
			{
				for (int i = 0; i < immagini.get(h).length; i++)
					
					{
						try
							{
						g2.setColor(immagini.get(h)[i].clr);
						int x = immagini.get(h)[i].x;// % mappingmain.DIM;
						int y = immagini.get(h)[i].y; // mappingmain.DIM;
						g2.drawLine(x, y, x, y);
							} catch (Exception e)
							{
							
							}
					}
			}
	}
	
	public DrawingPlane (Texel[] img, double[][] mtr)
	{
		
		immagini.add(img);
		matrici.add(mtr);
	}
	
	public void addImage(Texel[] img, double[][] mtr)
	{
		
		immagini.add(img);
		matrici.add(mtr);
	}
	
}


package testmapping;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class mappingmain
{
	private static final double	matrix1[][]	= { { 0.56826, -0.33442, 131 }, { 0.19429, 0.65218, +38 }, { -0.00018, 0, 0 } };
											
	// private static final double matrix2[][] = { { 1.5, -0.866, 200 }, {
	// 0.866, 1.5, 200 }, { 0, 0, 1 } };
	
	/**
	 * @Deprecated
	 */
	// public static final int DIM = 200;
	private JFrame				frame;
								
	/**
	 * Launch the application.
	 */
								public static void main(String[] args)
	{
		EventQueue.invokeLater(new Runnable()
		{
			public void run()
			{
				try
					{
						mappingmain window = new mappingmain();
						window.frame.setVisible(true);
					} catch (Exception e)
					{
						e.printStackTrace();
					}
			}
		});
	}
	
	/**
	 * Create the application.
	 */
	public mappingmain () throws IOException
	{
		initialize();
		
	}
	
	private Texel[] readimg(String percorso) throws IOException
	{
		
		BufferedImage bi = ImageIO.read(new File(percorso));
		
		int my = bi.getHeight();
		int mx = bi.getWidth();
		
		int npix = mx * my;
		
		Texel[] immagine = new Texel[npix];
		
		// int[] data = ((DataBufferInt)
		// bi.getRaster().getDataBuffer()).getData();
		
		for (int i = 0; i < npix; i++)
			{
				try
					{
						immagine[i] = new Texel(i / mx, i % mx, new Color(bi.getRGB(i / mx, i % mx)));
					} catch (Exception e)
					{
						System.err.println(i);
					}
					
			}
			
//		for (int i = 0; i < mx; i++)
//			{
//				for (int j = 0; j < my; j++)
//					{
//						immagine[i] = new Texel(i, j, new Color(bi.getRGB(i, j)));
//					}
//			}
//			
		return immagine;
		
	}
	
	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() throws IOException
	{
		frame = new JFrame();
		frame.setBounds(100, 100, 800, 800);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLayout(new BorderLayout());
		DrawingPlane dp = new DrawingPlane(readimg("D:/jpg_file_37138.jpg"), mappingmain.matrix1);
		frame.add(dp);
		
		// dp.addImage(initimg2(), matrix2);
		
	}
	
	/*
	 * private Texel[] initimg()
	 * {
	 * Texel[] immagine = new Texel[DIM * DIM];
	 * 
	 * for (int i = 0; i < immagine.length / 2; i++)
	 * {
	 * if (i % DIM < DIM / 2) immagine[i] = new Texel(i % DIM, i / DIM,
	 * Color.RED);
	 * else
	 * immagine[i] = new Texel(i % DIM, i / DIM, Color.YELLOW);
	 * 
	 * }
	 * for (int i = immagine.length / 2; i < immagine.length; i++)
	 * {
	 * 
	 * if (i % DIM < DIM / 2) immagine[i] = new Texel(i % DIM, i / DIM,
	 * Color.GREEN);
	 * else
	 * immagine[i] = new Texel(i % DIM, i / DIM, Color.BLUE);
	 * 
	 * }
	 * return immagine;
	 * }
	 */
	
	/*
	 * private Texel[] initimg1()
	 * {
	 * Texel[] immagine = new Texel[DIM * DIM];
	 * 
	 * for (int i = 0; i < immagine.length / 2; i++)
	 * {
	 * if (i % DIM < DIM / 2) immagine[i] = new Texel(i % DIM, i / DIM,
	 * Color.RED);
	 * else
	 * immagine[i] = new Texel(i % DIM, i / DIM, Color.YELLOW);
	 * 
	 * }
	 * for (int i = immagine.length / 2; i < immagine.length; i++)
	 * {
	 * 
	 * if (i % DIM < DIM / 2) immagine[i] = new Texel(i % DIM, i / DIM,
	 * Color.GREEN);
	 * else
	 * immagine[i] = new Texel(i % DIM, i / DIM, Color.BLUE);
	 * 
	 * }
	 * for (int i = 0; i < immagine.length; i++)
	 * {
	 * int riga = i / DIM;
	 * int colonna = i % DIM;
	 * 
	 * if (riga + colonna > DIM) immagine[i] = new Texel(immagine[i].x,
	 * immagine[i].y, new Color(238, 238, 238));
	 * 
	 * }
	 * 
	 * return immagine;
	 * }
	 */
	
	/*
	 * private Texel[] initimg2()
	 * {
	 * Texel[] immagine = new Texel[DIM * DIM];
	 * 
	 * for (int i = 0; i < immagine.length / 2; i++)
	 * {
	 * if (i % DIM < DIM / 2) immagine[i] = new Texel(i % DIM, i / DIM,
	 * Color.RED);
	 * else
	 * immagine[i] = new Texel(i % DIM, i / DIM, Color.YELLOW);
	 * 
	 * }
	 * for (int i = immagine.length / 2; i < immagine.length; i++)
	 * {
	 * 
	 * if (i % DIM < DIM / 2) immagine[i] = new Texel(i % DIM, i / DIM,
	 * Color.GREEN);
	 * else
	 * immagine[i] = new Texel(i % DIM, i / DIM, Color.BLUE);
	 * 
	 * }
	 * for (int i = 0; i < immagine.length; i++)
	 * {
	 * int riga = i / DIM;
	 * int colonna = i % DIM;
	 * 
	 * if (riga + colonna <= DIM) immagine[i] = new Texel(immagine[i].x,
	 * immagine[i].y, new Color(238, 238, 238));
	 * 
	 * }
	 * 
	 * return immagine;
	 * }
	 * 
	 */
	
}

/*
 * 
 * */


screenshot:

normale:
s4.postimg.org/o42em3wgd/…
rotazione 45 gradi:
s3.postimg.org/pao9lkrr7/…
(va be non è interpolato non mi interessa al momento)


i problemi sono che se l'immagine non è perfettamente quadrata, dei pixel del lato lungo vengono tagliati. Ma credo che questo dipenda dal mio algoritmo.
Mentre invece per quanto riguarda la trasformazione va bene. cioè se metto una matrice affine funziona (scalatura trasposizione e rotazione). il problema è che non mi fa la trasformazione prospettica. E sì che la matrice l'ho presa da GIMP! l'ho aperto, ho applicato lo strumento prospettiva ad una immagine e ho copiato la matrice. finchè i 4 lati rimangono paralleli a coppie funziona. se muovo i vertici in modo che sembra proiettato, no. talvolta non va neanche.

in particolare, sto cercando un effetto del genere:
i.stack.imgur.com/…

Ma si svolge in maniera diversa questo effetto?
Secondo voi è alta la difficoltà di reperire questo comportamento nel sorgente di GIMP??

qualcuno ne sa di più in merito? grazie.
Ultima modifica effettuata da Bonnox 21/08/16 8:30
aaa
21/08/16 15:24
Bonnox
ok ora va già meglio. ho corretto già il secondo bug relativo alla parte più importante, la moltiplicazione riga * colonna !!
Ora se copio una matrice di GIMP e la metto dentro, si assomigliano, ovvero "c'è un barlume di prospettiva", ma ancora i lati rimangono paralleli. ecco un paragone di esempio.

s10.postimg.org/6i02qx7fd/…

(hpo usato la prima immagine disponibile, uno screenshot del VBA:rotfl: )
aaa