Partage
  • Partager sur Facebook
  • Partager sur Twitter

probleme d'interpolation cubique

    26 mars 2009 à 23:14:26

    Bonsoir,

    Voilà après deux jours de prises de tête j'appelle à l'aide parce que la j'en peux plus...

    En fait ce code à pour but de générer une carte 3d à partir d'une heightmap et d'une colormap. Dans ce but il faut générer la texture...

    Alors etant donné que chaque pixel donne un carré de 16x16 pixel sur la texture, il est nécessaire d'interpoler les valeurs afin de calculer l'inclinaison (des seuils d'inclinaison distinguent différentes textures pour un même type de terrain), et c'est là que ça coince... je ne sais pas trop où c'est faux mais c'est à mon avis au niveau de l'interpolation cubique, parce qu'en utilisant une linéaire ça fonctionne

    enfin voilà le code (c'est aux environs de la ligne 185)

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.image.BufferedImage;
    import java.io.BufferedReader;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.util.ArrayList;
    
    import javax.imageio.ImageIO;
    
    import lwjgl03.util.Util;
    
    /**
     * @author Benoit Amand
     * 
     */
    public class MapCreator {
    
        private static Terrain[] terrains;
        private static int resolution = 16;
    
        private float[][] alt;
        private Terrain[][] terrain;
        private BufferedImage mapText;
    
        public void createMap(BufferedImage heightmap, BufferedImage terrainMap) {
    	createMap(heightmap, terrainMap, 0, 0, heightmap.getWidth(), heightmap
    		.getHeight());
        }
    
        public void createMap(BufferedImage heightmap, BufferedImage terrainMap,
    	    int startx, int starty, int width, int height) {
    
    	alt = new float[height + 3][width + 3];
    	float ratio = heightmap.getWidth() / ((float) terrainMap.getWidth());
    
    	terrain = new Terrain[(int) (height / ratio)][(int) (width / ratio)];
    	int r, g, b, p;
    	Terrain t = terrains[0];
    	float sm, nsm;
    
    	for (int x = startx - 1; x < startx + alt[0].length - 1; x++)
    	    for (int y = starty - 1; y < starty + alt.length - 1; y++) {
    		alt[y - starty + 1][x - startx + 1] = (new Color(heightmap
    			.getRGB(Math.min(heightmap.getWidth() - 1, Math.max(x,
    				0)), Math.min(heightmap.getHeight() - 1, Math
    				.max(y, 0))))).getRed()
    			* resolution / 256f;
    
    		if (alt[y - starty + 1][x - startx + 1] < 0) {
    		    System.out.println("erreur : ");
    
    		}
    
    	    }
    	for (int x = (int) (startx / ratio); x < startx + terrain[0].length; x++)
    	    for (int y = (int) (starty / ratio); y < starty + terrain.length; y++) {
    		if (terrainMap != null) {
    
    		    p = terrainMap.getRGB(x, y);
    
    		    sm = 0;
    
    		    for (int i = 0; i < terrains.length; i++) {
    			r = Math.abs(((p >> 16) & 0xFF)
    				- ((terrains[i].color >> 16) & 0xFF));
    			g = Math.abs(((p >> 8) & 0xFF)
    				- ((terrains[i].color >> 8) & 0xFF));
    			b = Math.abs(((p >> 0) & 0xFF)
    				- ((terrains[i].color >> 0) & 0xFF));
    
    			nsm = 1 - ((r + g + b) / (3 * 256f));
    
    			if (nsm > sm) {
    			    sm = nsm;
    			    t = terrains[i];
    			}
    		    }
    
    		    terrain[y - (int) (starty / ratio)][x
    			    - (int) (startx / ratio)] = t;
    		} else
    		    terrain[y - (int) (starty / ratio)][x
    			    - (int) (starty / ratio)] = terrains[0];
    	    }
    
    	mapText = new BufferedImage((int) (alt[0].length - 3 * ratio)
    		* resolution, (int) (alt.length - 3 * ratio) * resolution,
    		BufferedImage.TYPE_INT_RGB);
    
    	Graphics graphics = mapText.getGraphics();
    	Color c1, c2, c3, c4;
    	for (int x = (int) (ratio * resolution); x < (alt[0].length - 2 * ratio)
    		* resolution; x++)
    	    for (int y = (int) (ratio * resolution); y < (alt.length - 2 * ratio)
    		    * resolution; y++) {
    
    		c1 = getColorAt(x, y,
    			terrain[(int) (y / resolution / ratio)][(int) (x
    				/ resolution / ratio)]);
    		c2 = getColorAt(x, y,
    			terrain[(int) (y / resolution / ratio)][(int) (x
    				/ resolution / ratio + 1)]);
    		c3 = getColorAt(x, y,
    			terrain[(int) (y / resolution / ratio + 1)][(int) (x
    				/ resolution / ratio)]);
    		c4 = getColorAt(x, y,
    			terrain[(int) (y / resolution / ratio + 1)][(int) (x
    				/ resolution / ratio + 1)]);
    
    		graphics.setColor(interpolate(interpolate(c1, c2,
    			(x % (resolution * ratio)) / (resolution * ratio)),
    			interpolate(c3, c4, ((float) x % (resolution * ratio))
    				/ (resolution * ratio)),
    			((float) y % (resolution * ratio))
    				/ (resolution * ratio)));
    
    		graphics.drawRect(x - (int) (ratio * resolution), y
    			- (int) (ratio * resolution), 1, 1);
    	    }
    
    	float[][] alt2 = new float[height][width];
    	for (int x = 0; x < alt2[0].length; x++)
    	    for (int y = 0; y < alt2.length; y++)
    		alt2[y][x] = alt[y + 1][x + 1];
    
    	alt = alt2;
    
        }
    
        private Color interpolate(Color c1, Color c2, float x) {
    	double k = (1 - Math.cos(Math.PI * x)) / 2;
    	return new Color((int) (c1.getRed() * (1 - k) + c2.getRed() * k),
    		(int) (c1.getGreen() * (1 - k) + c2.getGreen() * k), (int) (c1
    			.getBlue()
    			* (1 - k) + c2.getBlue() * k));
        }
    
        private float i(float y0, float y1, float y2, float y3, float x) {
    	float a = y3 - y2 - y0 + y1;
    	float b = y0 - y1 - a;
    	float c = y2 - y0;
    	float d = y1;
    	return a * x * x * x + b * x * x + c * x + d;
        }
    
        private float di(float y0, float y1, float y2, float y3, float x) {
    	float a = y3 - y2 - y0 + y1;
    	float b = y0 - y1 - a;
    	float c = y2 - y0;
    
    	return 3 * a * x * x + 2 * b * x + c;
        }
    
        private float calcInc(float y00, float y01, float y02, float y03,
    	    float y10, float y11, float y12, float y13, float y20, float y21,
    	    float y22, float y23, float y30, float y31, float y32, float y33,
    	    float x, float y) {
    
    	float dv0 = di(y00, y01, y02, y03, x);
    	float dv1 = di(y10, y11, y12, y13, x);
    	float dv2 = di(y20, y21, y22, y23, x);
    	float dv3 = di(y30, y31, y32, y33, x);
    
    	float v0 = i(y00, y01, y02, y03, x);
    	float v1 = i(y10, y11, y12, y13, x);
    	float v2 = i(y20, y21, y22, y23, x);
    	float v3 = i(y30, y31, y32, y33, x);
    
    	float dzdx = i(dv0, dv1, dv2, dv3, y);
    	float dzdy = di(v0, v1, v2, v3, y);
    
    	
    	return (float) (Math.atan(Math.sqrt((dzdx * dzdx + dzdy * dzdy))) * 180
    		/ Math.PI);
        }
    
        private Color getColorAt(int x, int y, Terrain t) {
    
    	float inc = calcInc(alt[y / resolution - 1][x / resolution - 1], alt[y
    		/ resolution - 1][x / resolution], alt[y / resolution - 1][x
    		/ resolution + 1], alt[y / resolution - 1][x / resolution + 2],
    		alt[y / resolution][x / resolution - 1], alt[y / resolution][x
    			/ resolution], alt[y / resolution][x / resolution + 1],
    		alt[y / resolution][x / resolution + 2],
    		alt[y / resolution + 1][x / resolution - 1], alt[y / resolution
    			+ 1][x / resolution], alt[y / resolution + 1][x
    			/ resolution + 1], alt[y / resolution + 1][x
    			/ resolution + 2], alt[y / resolution + 2][x
    			/ resolution - 1], alt[y / resolution + 2][x
    			/ resolution], alt[y / resolution + 2][x / resolution
    			+ 1], alt[y / resolution + 2][x / resolution + 2],
    		((float) x) / resolution % 1, ((float) y) / resolution % 1);
    
    	int i = 0;
    		if (t.thresholds != null && t.thresholds.length > 0)
    	    while (i < t.thresholds.length && t.thresholds[i] < inc)
    		i++;
    	if (i % 2 == 0)
    	    return new Color(t.images[i / 2].getRGB(x
    		    % t.images[i / 2].getWidth(), y
    		    % t.images[i / 2].getHeight()));
    	else {
    	    Color c1 = new Color(t.images[i / 2].getRGB(x
    		    % t.images[i / 2].getWidth(), y
    		    % t.images[i / 2].getHeight()));
    	    Color c2 = new Color(t.images[i / 2 + 1].getRGB(x
    		    % t.images[i / 2 + 1].getWidth(), y
    		    % t.images[i / 2 + 1].getHeight()));
    
    	    float k = (inc - t.thresholds[i - 1])
    		    / (t.thresholds[i] - t.thresholds[i - 1]);
    
    	    return new Color((int) (c1.getRed() * (1 - k) + c2.getRed() * k),
    		    (int) (c1.getGreen() * (1 - k) + c2.getGreen() * k),
    		    (int) (c1.getBlue() * (1 - k) + c2.getBlue() * k));
    	}
    
        }
    
        public static void loadTerrainParams(InputStream input) throws Exception {
    	BufferedReader in = new BufferedReader(new InputStreamReader(input));
    
    	String str;
    	ArrayList<Terrain> tb = new ArrayList<Terrain>();
    	float[] thresholds = new float[0];
    	File basedir = null;
    
    	while ((str = in.readLine()) != null) {
    	    str = str.trim();
    	    if (str.length() == 0 || str.startsWith("#"))
    		continue;
    	    if (str.startsWith("threshold")
    		    && (str = str.substring(9).trim()).startsWith(":")) {
    
    		if ((str = str.substring(1).trim()).length() == 0)
    		    thresholds = new float[0];
    		else {
    		    String[] tbl = str.split(" ");
    
    		    thresholds = new float[tbl.length];
    		    for (int i = 0; i < tbl.length; i++)
    			thresholds[i] = Float.parseFloat(tbl[i]);
    		}
    		continue;
    	    }
    	    if (str.startsWith("basedir")
    		    && (str = str.substring(7).trim()).startsWith(":")) {
    		basedir = new File(str.substring(1).trim());
    		if (!basedir.isDirectory())
    		    basedir = null;
    		continue;
    	    }
    	    if (str.startsWith("resolution")
    		    && (str = str.substring(10).trim()).startsWith(":")) {
    		resolution = Integer.parseInt(str.substring(1).trim());
    		continue;
    	    }
    
    	    int i = str.indexOf(' ');
    	    Terrain tr = new Terrain();
    	    tb.add(tr);
    
    	    tr.thresholds = thresholds;
    	    tr.color = Integer.parseInt(str.substring(0, i), 16);
    
    	    String[] tbl = str.substring(i + 1).trim().split(" ");
    
    	    if ((tbl.length - 1) * 2 != thresholds.length)
    		throw new Exception(
    			"le nombre de seuils et d'images ne correspondent pas");
    
    	    tr.images = new BufferedImage[tbl.length];
    
    	    for (int j = 0; j < tbl.length; j++) {
    		String str2 = tbl[j].trim();
    
    		File f = (basedir == null) ? new File(str2) : new File(basedir,
    			str2);
    		tr.images[j] = ImageIO.read(f);
    	    }
    	}
    
    	in.close();
    	terrains = tb.toArray(new Terrain[tb.size()]);
    
        }
    
        public void writeData(OutputStream outp) throws IOException {
    // TODO:
        }
    
        private static class Terrain {
    	int color;
    	BufferedImage[] images;
    	float[] thresholds;
        }
    
        public static void main(String arg[]) {
    	try {
    	    loadTerrainParams(Util.getInputStream(".mapgen_params"));
    
    	    MapCreator m = new MapCreator();
    	    m.createMap(ImageIO.read(Util.getInputStream("heightmap.png")),
    		    ImageIO.read(Util.getInputStream("colormap.png")));
    
    	    ImageIO.write(m.mapText, "jpg", new File("aaa.png"));
    	} catch (Exception e) {
    	    e.printStackTrace();
    	}
        }
    }
    
    • Partager sur Facebook
    • Partager sur Twitter

    probleme d'interpolation cubique

    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
    • Editeur
    • Markdown