/*
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.PropertyCategory;
import org.jwildfire.base.PropertyMax;
import org.jwildfire.base.PropertyMin;
import org.jwildfire.base.mathlib.MathLib;
import org.jwildfire.image.WFImage;
import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor;
public class Transform3DTransformer extends Mesh3DTransformer {
public enum Rotate {
XY, YZ, XZ, NONE
}
@Property(category = PropertyCategory.PRIMARY, description = "X-coordinate of the centre of the transformation")
private double originX = 120.0;
@Property(category = PropertyCategory.PRIMARY, description = "Y-coordinate of the centre of the transformation")
private double originY = 120.0;
@Property(category = PropertyCategory.PRIMARY, description = "Z-coordinate of the centre of the transformation")
private double originZ = 0.0;
@Property(category = PropertyCategory.PRIMARY, description = "Object movement in x-direction")
private double transX = 0.0;
@Property(category = PropertyCategory.PRIMARY, description = "Object movement in y-direction")
private double transY = 0.0;
@Property(category = PropertyCategory.PRIMARY, description = "Object movement in z-direction")
private double transZ = 0.0;
@Property(category = PropertyCategory.PRIMARY, description = "Object scale factor for x-direction")
private double scaleX = 1.0;
@Property(category = PropertyCategory.PRIMARY, description = "Object scale factor for y-direction")
private double scaleY = 1.0;
@Property(category = PropertyCategory.PRIMARY, description = "Object scale factor for z-direction")
private double scaleZ = 1.0;
@Property(category = PropertyCategory.RENDERING, description = "Object rotation angle alpha")
@PropertyMin(-360)
@PropertyMax(360)
protected double objAlpha = 0.0;
@Property(category = PropertyCategory.RENDERING, description = "Object rotation angle beta")
@PropertyMin(-360)
@PropertyMax(360)
protected double objBeta = 0.0;
@Property(category = PropertyCategory.RENDERING, description = "Object rotation mode", editorClass = RotateEditor.class)
protected Rotate objRotate = Rotate.XY;
@Override
protected void transformMesh(Mesh3D pMesh3D, int pImageWidth, int pImageHeight) {
double x[] = pMesh3D.getX();
double y[] = pMesh3D.getY();
double z[] = pMesh3D.getZ();
int pCount = pMesh3D.getPCount();
int width = pMesh3D.getImageWidth();
int height = pMesh3D.getImageHeight();
boolean doRotate = (objRotate != Rotate.NONE);
boolean doTrans = (Math.abs(transX) > MathLib.EPSILON) || (Math.abs(transY) > MathLib.EPSILON)
|| (Math.abs(transZ) > MathLib.EPSILON);
boolean doScale = (Math.abs(scaleX - 1.0) > MathLib.EPSILON)
|| (Math.abs(scaleY - 1.0) > MathLib.EPSILON) || (Math.abs(scaleX - 1.0) > MathLib.EPSILON)
|| (Math.abs(scaleZ - 1.0) > MathLib.EPSILON);
double zeroX = (double) originX - (double) width / 2.0;
double zeroY = (double) originY - (double) height / 2.0;
double zeroZ = (double) originZ;
if (doScale) {
for (int i = 0; i < pCount; i++) {
double dx = x[i] - zeroX;
double dy = y[i] - zeroY;
double dz = z[i] - zeroZ;
x[i] = dx * scaleX + zeroX;
y[i] = dy * scaleY + zeroY;
z[i] = dz * scaleZ + zeroZ;
}
}
if (doRotate) {
double alpha = this.objAlpha * Math.PI / 180.0;
double beta = this.objBeta * Math.PI / 180.0;
double sinA = Math.sin(alpha);
double cosA = Math.cos(alpha);
double sinB = Math.sin(beta);
double cosB = Math.cos(beta);
if (objRotate == Rotate.XY) {
for (int i = 0; i < pCount; i++) {
double dx = x[i] - zeroX;
double dy = y[i] - zeroY;
double dz = z[i] - zeroZ;
x[i] = cosA * dx - sinB * sinA * dy + cosB * sinA * dz + zeroX;
y[i] = cosB * dy + sinB * dz + zeroY;
z[i] = -sinA * dx - sinB * cosA * dy + cosB * cosA * dz + zeroZ;
}
}
else if (objRotate == Rotate.YZ) {
for (int i = 0; i < pCount; i++) {
double dx = x[i] - zeroX;
double dy = y[i] - zeroY;
double dz = z[i] - zeroZ;
x[i] = cosA * cosB * dx + sinA * cosB * dy + sinB * dz + zeroX;
y[i] = -sinA * dx + cosA * dy + zeroY;
z[i] = -cosA * sinB * dx - sinA * sinB * dy + cosB * dz + zeroZ;
}
}
else /* xz */{
for (int i = 0; i < pCount; i++) {
double dx = x[i] - zeroX;
double dy = y[i] - zeroY;
double dz = z[i] - zeroZ;
x[i] = cosA * dx + cosB * sinA * dy + sinB * sinA * dz + zeroX;
y[i] = -sinA * dx + cosB * cosA * dy + sinB * cosA * dz + zeroY;
z[i] = -sinB * dy + cosB * dz + zeroZ;
}
}
}
if (doTrans) {
for (int i = 0; i < pCount; i++) {
x[i] += transX;
y[i] += transY;
z[i] += transZ;
}
}
}
@Override
public void initDefaultParams(WFImage pImg) {
super.initDefaultParams(pImg);
int width = pImg.getImageWidth();
int height = pImg.getImageHeight();
originX = (double) width / 2.0;
originY = (double) height / 2.0;
originZ = 0.0;
transX = 0.0;
transY = 0.0;
transZ = 0.0;
scaleX = 1.0;
scaleY = 1.0;
scaleZ = 1.0;
objAlpha = 0.0;
objBeta = 0.0;
objRotate = Rotate.XY;
}
public static class RotateEditor extends ComboBoxPropertyEditor {
public RotateEditor() {
super();
setAvailableValues(new Rotate[] { Rotate.XY, Rotate.YZ, Rotate.XZ, Rotate.NONE });
}
}
public double getOriginX() {
return originX;
}
public void setOriginX(double originX) {
this.originX = originX;
}
public double getOriginY() {
return originY;
}
public void setOriginY(double originY) {
this.originY = originY;
}
public double getOriginZ() {
return originZ;
}
public void setOriginZ(double originZ) {
this.originZ = originZ;
}
public double getTransX() {
return transX;
}
public void setTransX(double transX) {
this.transX = transX;
}
public double getTransY() {
return transY;
}
public void setTransY(double transY) {
this.transY = transY;
}
public double getTransZ() {
return transZ;
}
public void setTransZ(double transZ) {
this.transZ = transZ;
}
public double getScaleX() {
return scaleX;
}
public void setScaleX(double scaleX) {
this.scaleX = scaleX;
}
public double getScaleY() {
return scaleY;
}
public void setScaleY(double scaleY) {
this.scaleY = scaleY;
}
public double getScaleZ() {
return scaleZ;
}
public void setScaleZ(double scaleZ) {
this.scaleZ = scaleZ;
}
public double getObjAlpha() {
return objAlpha;
}
public void setObjAlpha(double objAlpha) {
this.objAlpha = objAlpha;
}
public double getObjBeta() {
return objBeta;
}
public void setObjBeta(double objBeta) {
this.objBeta = objBeta;
}
public Rotate getObjRotate() {
return objRotate;
}
public void setObjRotate(Rotate objRotate) {
this.objRotate = objRotate;
}
}