/*
JWildfire - an image and animation processor written in Java
Copyright (C) 1995-2015 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.create.eden.sunflow;
import java.lang.reflect.Field;
import org.jwildfire.base.mathlib.MathLib;
import org.jwildfire.create.eden.sunflow.base.PartBuilder;
import org.jwildfire.create.tina.meshgen.marchingcubes.Point3f;
import org.sunflow.math.Matrix4;
public class TransformBuilder<TParent extends PrimitiveBuilder<?>> implements PartBuilder {
private final TParent parent;
protected final Point3f rotate = new Point3f(0.0, 0.0, 0.0);
protected final Point3f scale = new Point3f(1.0, 1.0, 1.0);
protected final Point3f translate = new Point3f(0.0, 0.0, 0.0);
protected Matrix4 matrix = null;
public TransformBuilder(TParent pParent) {
parent = pParent;
}
@Override
public void buildPart(StringBuilder pTarget) {
if (!isEmpty()) {
if (matrix != null) {
pTarget.append(" transform row ");
pTarget.append(readMatrixValue(matrix, "m00") + " ");
pTarget.append(readMatrixValue(matrix, "m01") + " ");
pTarget.append(readMatrixValue(matrix, "m02") + " ");
pTarget.append(readMatrixValue(matrix, "m03") + " ");
pTarget.append(readMatrixValue(matrix, "m10") + " ");
pTarget.append(readMatrixValue(matrix, "m11") + " ");
pTarget.append(readMatrixValue(matrix, "m12") + " ");
pTarget.append(readMatrixValue(matrix, "m13") + " ");
pTarget.append(readMatrixValue(matrix, "m20") + " ");
pTarget.append(readMatrixValue(matrix, "m21") + " ");
pTarget.append(readMatrixValue(matrix, "m22") + " ");
pTarget.append(readMatrixValue(matrix, "m23") + " ");
pTarget.append("0 0 0 1\n");
}
else {
pTarget.append(" transform {\n");
if (doScale()) {
if (areTheSame(scale.x, scale.y, scale.z)) {
pTarget.append(" scaleu " + scale.x + "\n");
}
else {
pTarget.append(" scale " + scale.x + " " + scale.y + " " + scale.z + "\n");
}
}
if (doRotateX()) {
pTarget.append(" rotatex " + rotate.x + "\n");
}
if (doRotateY()) {
pTarget.append(" rotatey " + rotate.y + "\n");
}
if (doRotateZ()) {
pTarget.append(" rotatez " + rotate.z + "\n");
}
if (doTranslate()) {
pTarget.append(" translate " + translate.x + " " + translate.y + " " + translate.z + "\n");
}
pTarget.append(" }\n");
}
}
}
private float readMatrixValue(Matrix4 pMatrix, String pFieldname) {
Field f;
try {
f = pMatrix.getClass().getDeclaredField(pFieldname);
f.setAccessible(true);
return f.getFloat(pMatrix);
}
catch (Exception e) {
e.printStackTrace();
return 0.0f;
}
}
private boolean areTheSame(float pX, float pY, float pZ) {
return MathLib.fabs(pY - pX) < MathLib.EPSILON && MathLib.fabs(pZ - pY) < MathLib.EPSILON && MathLib.fabs(pX - pZ) < MathLib.EPSILON;
}
public TParent close() {
return parent;
}
private boolean doRotateX() {
return MathLib.fabs(rotate.x) > MathLib.EPSILON;
}
private boolean doRotateY() {
return MathLib.fabs(rotate.y) > MathLib.EPSILON;
}
private boolean doRotateZ() {
return MathLib.fabs(rotate.z) > MathLib.EPSILON;
}
private boolean doTranslate() {
return MathLib.fabs(translate.x) > MathLib.EPSILON || MathLib.fabs(translate.y) > MathLib.EPSILON || MathLib.fabs(translate.z) > MathLib.EPSILON;
}
private boolean doScale() {
return MathLib.fabs(scale.x - 1.0) > MathLib.EPSILON || MathLib.fabs(scale.y - 1.0) > MathLib.EPSILON || MathLib.fabs(scale.z - 1.0) > MathLib.EPSILON;
}
private boolean isEmpty() {
return !(matrix != null || doRotateX() || doRotateY() || doRotateZ() || doTranslate() || doScale());
}
public TransformBuilder<TParent> withRotateX(double pRotateX) {
rotate.x = (float) pRotateX;
return this;
}
public TransformBuilder<TParent> withRotateY(double pRotateY) {
rotate.y = (float) pRotateY;
return this;
}
public TransformBuilder<TParent> withRotateZ(double pRotateZ) {
rotate.z = (float) pRotateZ;
return this;
}
public TransformBuilder<TParent> withScaleX(double pScaleX) {
scale.x = (float) pScaleX;
return this;
}
public TransformBuilder<TParent> withScaleY(double pScaleY) {
scale.y = (float) pScaleY;
return this;
}
public TransformBuilder<TParent> withScaleZ(double pScaleZ) {
scale.z = (float) pScaleZ;
return this;
}
public TransformBuilder<TParent> withTranslateX(double pTranslateX) {
translate.x = (float) pTranslateX;
return this;
}
public TransformBuilder<TParent> withTranslateY(double pTranslateY) {
translate.y = (float) pTranslateY;
return this;
}
public TransformBuilder<TParent> withTranslateZ(double pTranslateZ) {
translate.z = (float) pTranslateZ;
return this;
}
public void withMatrix(Matrix4 pMatrix) {
matrix = pMatrix;
}
}