/* JWildfire - an image and animation processor written in Java Copyright (C) 1995-2011 Andreas Maschke This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this software; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jwildfire.transform; import org.jwildfire.base.Tools; import org.jwildfire.base.mathlib.MathLib; import org.jwildfire.image.SimpleImage; public class Mesh3D implements Cloneable { private double x[]; private double y[]; private double z[]; private int pCount; private int pp1[]; private int pp2[]; private int pp3[]; private int color[]; private int fCount; private SimpleImage texture; private double u[], v[]; private int imageWidth; private int imageHeight; // TODO change this (circular reference) all the needed parameters are known: private Mesh3DTransformer lastTransformation; public double[] getX() { return x; } public double[] getY() { return y; } public double[] getZ() { return z; } public int getPCount() { return pCount; } public int getFCount() { return fCount; } public void readPixels(SimpleImage pImg, double pQuant) { this.imageWidth = pImg.getImageWidth(); this.imageHeight = pImg.getImageHeight(); int width = pImg.getImageWidth(); int height = pImg.getImageHeight(); int width2, height2; if (pQuant < 0.1) pQuant = 1.0; width2 = (int) ((double) width / pQuant + 0.5); height2 = (int) ((double) height / pQuant + 0.5); if ((width2 == width) && (height2 == height)) { pCount = (int) (width + 1) * (height + 1); fCount = (int) 2 * (int) width * (int) height; x = new double[pCount]; y = new double[pCount]; z = new double[pCount]; pp1 = new int[fCount]; pp2 = new int[fCount]; pp3 = new int[fCount]; if (Tools.USE_TEXTURES) { texture = pImg.clone(); u = new double[pCount]; v = new double[pCount]; double du = 1.0 / (double) (width + 1); double dv = 1.0 / (double) (height + 1); color = null; int curr = 0; double currV = 0.0; for (int i = 0; i <= height; i++) { double currU = 0.0; for (int j = 0; j <= width; j++) { u[curr] = currU; v[curr++] = currV; currU += du; } currV += dv; } } else { u = v = null; texture = null; color = new int[fCount]; int curr = 0; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int argb = pImg.getARGBValue(j, i); /* two faces with same color */ color[curr++] = argb; color[curr++] = argb; } } } /* create the points */ double cx = (double) (width) / 2.0; double cy = (double) (height) / 2.0; double xmin0 = 0.0 - cx; double ymin0 = 0.0 - cy; double ymin = ymin0; int curr = 0; for (int i = 0; i <= height; i++) { double xmin = xmin0; for (int j = 0; j <= width; j++) { x[curr] = xmin; xmin += 1.0; y[curr] = ymin; z[curr++] = 0.0; } ymin += 1.0; } /* create the faces */ curr = 0; for (int i = 0; i < height; i++) { int p0 = i * (width + 1); int p1 = (i + 1) * (width + 1); for (int j = 0; j < width; j++) { pp3[curr] = p0; pp2[curr] = p0 + 1; pp1[curr++] = p1 + 1; pp3[curr] = p0++; pp2[curr] = p1 + 1; pp1[curr++] = p1++; } } } else { // pCount = (int) (width2 + 1) * (height2 + 1); fCount = (int) 2 * (int) width2 * (int) height2; color = new int[fCount]; // copy the colors if (Tools.USE_TEXTURES) { texture = pImg.clone(); u = new double[pCount]; v = new double[pCount]; color = null; double du = 1.0 / (double) (width2 + 1); double dv = 1.0 / (double) (height2 + 1); int curr = 0; double currV = 0.0; for (int i = 0; i <= height2; i++) { double currU = 0.0; for (int j = 0; j <= width2; j++) { u[curr] = currU; v[curr++] = currV; currU += du; } currV += dv; } } else { u = v = null; texture = null; // Scale the image SimpleImage sImg = pImg.clone(); ScaleTransformer scaleT = new ScaleTransformer(); scaleT.setAspect(ScaleAspect.IGNORE); scaleT.setUnit(ScaleTransformer.Unit.PIXELS); scaleT.setScaleWidth(width2); scaleT.setScaleHeight(height2); scaleT.performImageTransformation(sImg); int curr = 0; for (int i = 0; i < height2; i++) { for (int j = 0; j < width2; j++) { int argb = sImg.getARGBValue(j, i); /* two faces with same color */ color[curr++] = argb; color[curr++] = argb; } } sImg = null; } // x = new double[pCount]; y = new double[pCount]; z = new double[pCount]; pp1 = new int[fCount]; pp2 = new int[fCount]; pp3 = new int[fCount]; // create the points double dx = (double) width / (double) width2; double dy = (double) height / (double) height2; double cx = (double) (width) / 2.0; double cy = (double) (height) / 2.0; double xmin0 = 0.0 - cx; double ymin0 = 0.0 - cy; double ymin = ymin0; int curr = 0; for (int i = 0; i <= height2; i++) { double xmin = xmin0; for (int j = 0; j <= width2; j++) { x[curr] = xmin; xmin += dx; y[curr] = ymin; z[curr++] = 0.0; } ymin += dy; } /* create the faces */ curr = 0; for (int i = 0; i < height2; i++) { int p0 = (int) i * (int) (width2 + 1); int p1 = (int) (i + 1) * (int) (width2 + 1); for (int j = 0; j < width2; j++) { pp3[curr] = p0; pp2[curr] = p0 + 1; pp1[curr++] = p1 + 1; pp3[curr] = p0++; pp2[curr] = p1 + 1; pp1[curr++] = p1++; } } } } public int[] getPP1() { return pp1; } public int[] getPP2() { return pp2; } public int[] getPP3() { return pp3; } public int[] getColor() { return color; } public void setReducedFCount(int pFCount) { if (pFCount > fCount) throw new IllegalArgumentException(); fCount = pFCount; } @Override public Mesh3D clone() { Mesh3D res = new Mesh3D(); res.x = new double[x.length]; System.arraycopy(x, 0, res.x, 0, x.length); res.y = new double[y.length]; System.arraycopy(y, 0, res.y, 0, y.length); res.z = new double[z.length]; System.arraycopy(z, 0, res.z, 0, z.length); res.pp1 = new int[pp1.length]; System.arraycopy(pp1, 0, res.pp1, 0, pp1.length); res.pp2 = new int[pp2.length]; System.arraycopy(pp2, 0, res.pp2, 0, pp2.length); res.pp3 = new int[pp3.length]; System.arraycopy(pp3, 0, res.pp3, 0, pp3.length); if (color != null && color.length > 0) { res.color = new int[color.length]; System.arraycopy(color, 0, res.color, 0, color.length); } else { res.color = null; } if (u != null && u.length > 0) { res.u = new double[u.length]; System.arraycopy(u, 0, res.u, 0, u.length); } else { res.u = null; } if (v != null && v.length > 0) { res.v = new double[v.length]; System.arraycopy(v, 0, res.v, 0, v.length); } else { res.v = null; } if (texture != null) { res.texture = texture.clone(); } else { res.texture = null; } res.pCount = pCount; res.fCount = fCount; res.imageWidth = imageWidth; res.imageHeight = imageHeight; return res; } public Mesh3D clone(double pScale) { Mesh3D res = clone(); if (Math.abs(pScale - 1.0) > MathLib.EPSILON) { for (int i = 0; i < pCount; i++) { res.x[i] *= pScale; res.y[i] *= pScale; res.z[i] *= pScale; } res.imageWidth = (int) ((double) res.imageWidth * pScale + 0.5); res.imageHeight = (int) ((double) res.imageHeight * pScale + 0.5); } return res; } public int getImageWidth() { return imageWidth; } public int getImageHeight() { return imageHeight; } public void setFCount(int pFCount) { fCount = pFCount; } public void setPP1(int[] pPP1) { pp1 = pPP1; } public void setPP2(int[] pPP2) { pp2 = pPP2; } public void setPP3(int[] pPP3) { pp3 = pPP3; } public void setColor(int[] pColor) { color = pColor; } public void setPCount(int pPCount) { pCount = pPCount; } public void setX(double[] pX) { x = pX; } public void setY(double[] pY) { y = pY; } public void setZ(double[] pZ) { z = pZ; } public void setImageWidth(int imageWidth) { this.imageWidth = imageWidth; } public void setImageHeight(int imageHeight) { this.imageHeight = imageHeight; } public Mesh3DTransformer getLastTransformation() { return lastTransformation; } public void setLastTransformation(Mesh3DTransformer lastTransformation) { this.lastTransformation = lastTransformation; } public SimpleImage getTexture() { return texture; } public void setTexture(SimpleImage texture) { this.texture = texture; } public double[] getU() { return u; } public void setU(double[] u) { this.u = u; } public double[] getV() { return v; } public void setV(double[] v) { this.v = v; } }