/* 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.Property; import org.jwildfire.base.PropertyMin; import org.jwildfire.image.WFImage; public class SphereTransformer extends Mesh3DTransformer { @Property(description = "Size of the sphere") @PropertyMin(0.0) private double radius = 120.0; @Override protected void transformMesh(Mesh3D pMesh3D, int pImageWidth, int pImageHeight) { int pCount = pMesh3D.getPCount(); int width = pImageWidth; int height = pImageHeight; double twoPi = 2.0 * Math.PI; double mPI2 = 0.0 - Math.PI / 2.0; double pPI2 = Math.PI / 2.0; double dx = (double) width; double dy = (double) height; double radius0; if (width > height) radius0 = dy / twoPi; else radius0 = dx / twoPi; int[] illPnt = new int[pCount]; double radius = this.radius; if (radius < 0.5) radius = 0.5; double scale = radius / radius0; double rmax = radius * Math.PI; double x[] = pMesh3D.getX(); double y[] = pMesh3D.getY(); double z[] = pMesh3D.getZ(); for (int i = 0; i < pCount; i++) { x[i] *= scale; y[i] *= scale; z[i] *= scale; } for (int i = 0; i < pCount; i++) { dx = x[i]; dy = y[i]; double zz = z[i]; double dr = Math.sqrt(dx * dx + dy * dy); if (dr <= rmax) { /* inverse rotation */ double angle2; if (dx != 0.0) { angle2 = Math.atan(dy / dx); } else { if (dy < 0.0) angle2 = mPI2; else angle2 = pPI2; } /* wrapping */ double angle = dr / radius; double sa = Math.sin(angle); double ca = Math.cos(angle); double rx; if (dx < 0) rx = 0.0 - (radius - zz) * sa; else rx = (radius - zz) * sa; z[i] = 0.0 - (radius - zz) * ca; /* rotation */ x[i] = rx * Math.cos(angle2); y[i] = rx * Math.sin(angle2); } else { illPnt[i] = 1; } } // Fix points int fc = pMesh3D.getFCount(); if (fc > 0) { int fInd[] = new int[fc]; int p1[] = pMesh3D.getPP1(); int p2[] = pMesh3D.getPP2(); int p3[] = pMesh3D.getPP3(); int color[] = pMesh3D.getColor(); int curr = 0; for (int i = 0; i < fc; i++) { if ((illPnt[p1[i]] != 0) || (illPnt[p2[i]] != 0) || (illPnt[p3[i]] != 0)) { // currently nothing to do } else { fInd[curr++] = i; } } fc = curr; for (int i = 0; i < curr; i++) { int j = fInd[i]; if (i != j) { if (color != null) { color[i] = color[j]; } p1[i] = p1[j]; p2[i] = p2[j]; p3[i] = p3[j]; } } pMesh3D.setReducedFCount(fc); } } @Override public void initDefaultParams(WFImage pImg) { super.initDefaultParams(pImg); int width = pImg.getImageWidth(); int height = pImg.getImageHeight(); double rr = Math.sqrt(width * width + height * height); radius = rr / 15.0; zoom = 2.0; ambient = 0.40; alpha = 15.0; beta = -35.0; } public double getRadius() { return radius; } public void setRadius(double radius) { this.radius = radius; } }