Tuesday, 15 March 2011

java - Texture deforming, 4 points -



java - Texture deforming, 4 points -

i writing simple 3d game in java , need code / lib texture deforming. don't want utilize opengl.

example:

i have got texture:

and need deform to:

i hope can understand me. thanks!

ok, here go. implemented small, self-contained illustration can drag around corners mouse:

+1 to...

tucuxi posted basic approach in his answer mvg @ math.stackexchange.com described how compute projective transformation 4 points

here's code:

import java.awt.color; import java.awt.graphics; import java.awt.gridlayout; import java.awt.point; import java.awt.event.mouseevent; import java.awt.event.mouselistener; import java.awt.event.mousemotionlistener; import java.awt.geom.point2d; import java.awt.image.bufferedimage; import java.io.file; import java.io.ioexception; import javax.imageio.imageio; import javax.swing.imageicon; import javax.swing.jframe; import javax.swing.jlabel; import javax.swing.jpanel; import javax.swing.swingutilities; public class pseudo3dtest { public static void main(string[] args) { swingutilities.invokelater(new runnable() { @override public void run() { createandshowgui(); } }); } private static void createandshowgui() { jframe f = new jframe(); f.setdefaultcloseoperation(jframe.exit_on_close); bufferedimage image = null; seek { image = imageio.read(new file("lena512color.png")); } grab (ioexception e) { e.printstacktrace(); return; } f.getcontentpane().setlayout(new gridlayout(1,2)); f.getcontentpane().add(new jlabel(new imageicon(image))); f.getcontentpane().add(new pseudo3dimagepanel(image)); f.pack(); f.setlocationrelativeto(null); f.setvisible(true); } } class pseudo3dimagepanel extends jpanel implements mouselistener, mousemotionlistener { private final bufferedimage inputimage; private final point2d p0; private final point2d p1; private final point2d p2; private final point2d p3; private point2d draggedpoint; pseudo3dimagepanel(bufferedimage inputimage) { this.inputimage = inputimage; this.p0 = new point2d.double(30,20); this.p1 = new point2d.double(50,400); this.p2 = new point2d.double(450,300); this.p3 = new point2d.double(430,100); addmouselistener(this); addmousemotionlistener(this); } @override protected void paintcomponent(graphics g) { super.paintcomponent(g); bufferedimage image = pseudo3d.computeimage(inputimage, p0, p1, p2, p3); g.drawimage(image, 0, 0, null); int r = 8; g.setcolor(color.red); g.filloval((int)p0.getx()-r, (int)p0.gety()-r, r+r, r+r); g.filloval((int)p1.getx()-r, (int)p1.gety()-r, r+r, r+r); g.filloval((int)p2.getx()-r, (int)p2.gety()-r, r+r, r+r); g.filloval((int)p3.getx()-r, (int)p3.gety()-r, r+r, r+r); } @override public void mousepressed(mouseevent e) { point p = e.getpoint(); int r = 8; if (p.distance(p0) < r) draggedpoint = p0; if (p.distance(p1) < r) draggedpoint = p1; if (p.distance(p2) < r) draggedpoint = p2; if (p.distance(p3) < r) draggedpoint = p3; } @override public void mousedragged(mouseevent e) { if (draggedpoint != null) { draggedpoint.setlocation(e.getx(), e.gety()); repaint(); } } @override public void mousereleased(mouseevent e) { draggedpoint = null; } @override public void mousemoved(mouseevent e) {} @override public void mouseclicked(mouseevent e) {} @override public void mouseentered(mouseevent e) {} @override public void mouseexited(mouseevent e) {} } class pseudo3d { static bufferedimage computeimage( bufferedimage image, point2d p0, point2d p1, point2d p2, point2d p3) { int w = image.getwidth(); int h = image.getheight(); bufferedimage result = new bufferedimage(w, h, bufferedimage.type_int_argb); point2d ip0 = new point2d.double(0,0); point2d ip1 = new point2d.double(0,h); point2d ip2 = new point2d.double(w,h); point2d ip3 = new point2d.double(w,0); matrix3d m = computeprojectionmatrix( new point2d[] { p0, p1, p2, p3 }, new point2d[] { ip0, ip1, ip2, ip3 }); matrix3d minv = new matrix3d(m); minv.invert(); (int y = 0; y < h; y++) { (int x = 0; x < w; x++) { point2d p = new point2d.double(x,y); minv.transform(p); int ix = (int)p.getx(); int iy = (int)p.gety(); if (ix >= 0 && ix < w && iy >= 0 && iy < h) { int rgb = image.getrgb(ix, iy); result.setrgb(x, y, rgb); } } } homecoming result; } // http://math.stackexchange.com/questions/296794 private static matrix3d computeprojectionmatrix(point2d p0[], point2d p1[]) { matrix3d m0 = computeprojectionmatrix(p0); matrix3d m1 = computeprojectionmatrix(p1); m1.invert(); m0.mul(m1); homecoming m0; } // http://math.stackexchange.com/questions/296794 private static matrix3d computeprojectionmatrix(point2d p[]) { matrix3d m = new matrix3d( p[0].getx(), p[1].getx(), p[2].getx(), p[0].gety(), p[1].gety(), p[2].gety(), 1, 1, 1); point3d p3 = new point3d(p[3].getx(), p[3].gety(), 1); matrix3d minv = new matrix3d(m); minv.invert(); minv.transform(p3); m.m00 *= p3.x; m.m01 *= p3.y; m.m02 *= p3.z; m.m10 *= p3.x; m.m11 *= p3.y; m.m12 *= p3.z; m.m20 *= p3.x; m.m21 *= p3.y; m.m22 *= p3.z; homecoming m; } private static class point3d { double x; double y; double z; point3d(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } } private static class matrix3d { double m00; double m01; double m02; double m10; double m11; double m12; double m20; double m21; double m22; matrix3d( double m00, double m01, double m02, double m10, double m11, double m12, double m20, double m21, double m22) { this.m00 = m00; this.m01 = m01; this.m02 = m02; this.m10 = m10; this.m11 = m11; this.m12 = m12; this.m20 = m20; this.m21 = m21; this.m22 = m22; } matrix3d(matrix3d m) { this.m00 = m.m00; this.m01 = m.m01; this.m02 = m.m02; this.m10 = m.m10; this.m11 = m.m11; this.m12 = m.m12; this.m20 = m.m20; this.m21 = m.m21; this.m22 = m.m22; } // http://www.dr-lex.be/random/matrix_inv.html void invert() { double invdet = 1.0 / determinant(); double nm00 = m22 * m11 - m21 * m12; double nm01 = -(m22 * m01 - m21 * m02); double nm02 = m12 * m01 - m11 * m02; double nm10 = -(m22 * m10 - m20 * m12); double nm11 = m22 * m00 - m20 * m02; double nm12 = -(m12 * m00 - m10 * m02); double nm20 = m21 * m10 - m20 * m11; double nm21 = -(m21 * m00 - m20 * m01); double nm22 = m11 * m00 - m10 * m01; m00 = nm00 * invdet; m01 = nm01 * invdet; m02 = nm02 * invdet; m10 = nm10 * invdet; m11 = nm11 * invdet; m12 = nm12 * invdet; m20 = nm20 * invdet; m21 = nm21 * invdet; m22 = nm22 * invdet; } // http://www.dr-lex.be/random/matrix_inv.html double determinant() { homecoming m00 * (m11 * m22 - m12 * m21) + m01 * (m12 * m20 - m10 * m22) + m02 * (m10 * m21 - m11 * m20); } final void mul(double factor) { m00 *= factor; m01 *= factor; m02 *= factor; m10 *= factor; m11 *= factor; m12 *= factor; m20 *= factor; m21 *= factor; m22 *= factor; } void transform(point3d p) { double x = m00 * p.x + m01 * p.y + m02 * p.z; double y = m10 * p.x + m11 * p.y + m12 * p.z; double z = m20 * p.x + m21 * p.y + m22 * p.z; p.x = x; p.y = y; p.z = z; } void transform(point2d pp) { point3d p = new point3d(pp.getx(), pp.gety(), 1.0); transform(p); pp.setlocation(p.x / p.z, p.y / p.z); } void mul(matrix3d m) { double nm00 = m00 * m.m00 + m01 * m.m10 + m02 * m.m20; double nm01 = m00 * m.m01 + m01 * m.m11 + m02 * m.m21; double nm02 = m00 * m.m02 + m01 * m.m12 + m02 * m.m22; double nm10 = m10 * m.m00 + m11 * m.m10 + m12 * m.m20; double nm11 = m10 * m.m01 + m11 * m.m11 + m12 * m.m21; double nm12 = m10 * m.m02 + m11 * m.m12 + m12 * m.m22; double nm20 = m20 * m.m00 + m21 * m.m10 + m22 * m.m20; double nm21 = m20 * m.m01 + m21 * m.m11 + m22 * m.m21; double nm22 = m20 * m.m02 + m21 * m.m12 + m22 * m.m22; m00 = nm00; m01 = nm01; m02 = nm02; m10 = nm10; m11 = nm11; m12 = nm12; m20 = nm20; m21 = nm21; m22 = nm22; } } }

java image-processing

No comments:

Post a Comment