/*
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.export;
import java.util.ArrayList;
import java.util.List;
import org.jwildfire.base.mathlib.MathLib;
import org.jwildfire.create.eden.scene.MaterialGroup;
import org.jwildfire.create.eden.scene.PositionableSceneElement;
import org.jwildfire.create.eden.scene.Scene;
import org.jwildfire.create.eden.scene.SceneElement;
import org.jwildfire.create.eden.scene.SceneElementVisitor;
import org.jwildfire.create.eden.scene.camera.Camera;
import org.jwildfire.create.eden.scene.light.PointLight;
import org.jwildfire.create.eden.scene.light.SkyLight;
import org.jwildfire.create.eden.scene.material.Glass;
import org.jwildfire.create.eden.scene.material.Material;
import org.jwildfire.create.eden.scene.material.Shiny;
import org.jwildfire.create.eden.scene.primitive.Box;
import org.jwildfire.create.eden.scene.primitive.Cylinder;
import org.jwildfire.create.eden.scene.primitive.Mesh;
import org.jwildfire.create.eden.scene.primitive.Sphere;
import org.jwildfire.create.eden.sunflow.SunflowSceneBuilder;
import org.jwildfire.create.eden.sunflow.base.CameraType;
import org.jwildfire.create.eden.sunflow.base.LightType;
import org.jwildfire.create.eden.sunflow.base.ShaderType;
import org.sunflow.math.Matrix4;
public class AddSceneObjectsVisitor implements SceneElementVisitor {
private final SunflowSceneBuilder sceneBuilder;
private boolean useMatrix = true;
public AddSceneObjectsVisitor(SunflowSceneBuilder pSceneBuilder) {
sceneBuilder = pSceneBuilder;
}
@Override
public void visitBefore(SceneElement pSceneElement) {
if (pSceneElement instanceof PositionableSceneElement) {
addPositionableSceneElement((PositionableSceneElement) pSceneElement);
}
else if (pSceneElement instanceof Material) {
addMaterial(pSceneElement);
}
else {
System.out.println("Unknown element " + pSceneElement);
}
}
private void addMaterial(SceneElement pSceneElement) {
if (pSceneElement instanceof Glass) {
Glass glass = (Glass) pSceneElement;
sceneBuilder.addShader()
.withName(glass.getName())
.withType(ShaderType.GLASS)
.withEta(glass.getEta())
.withColor(glass.getColor().getR(), glass.getColor().getG(), glass.getColor().getB())
.withAbsorbtionColor(glass.getAbsorptionColor().getR(), glass.getAbsorptionColor().getG(), glass.getAbsorptionColor().getB());
}
else if (pSceneElement instanceof Shiny) {
Shiny shiny = (Shiny) pSceneElement;
sceneBuilder.addShader()
.withName(shiny.getName())
.withType(ShaderType.SHINY)
.withDiff(shiny.getColor().getR(), shiny.getColor().getG(), shiny.getColor().getB())
.withRefl(shiny.getRefl());
}
else {
System.out.println("Unknown material " + pSceneElement);
}
}
private void addPositionableSceneElement(PositionableSceneElement pSceneElement) {
Matrix4 matrix = calcTransform(pSceneElement);
if (pSceneElement instanceof Sphere) {
Sphere sphere = (Sphere) pSceneElement;
if (useMatrix) {
sceneBuilder.addSphere()
.withShader(sphere.getMaterial())
.withTransform()
.withMatrix(matrix);
}
else {
sceneBuilder.addSphere()
.withShader(sphere.getMaterial())
.withTransform()
.withScaleX(sphere.getSize().getX())
.withScaleY(sphere.getSize().getY())
.withScaleZ(sphere.getSize().getZ())
.withTranslateX(sphere.getPosition().getX())
.withTranslateY(sphere.getPosition().getY())
.withTranslateZ(sphere.getPosition().getZ());
}
}
else if (pSceneElement instanceof Cylinder) {
Cylinder cylinder = (Cylinder) pSceneElement;
if (useMatrix) {
sceneBuilder.addCylinder()
.withShader(cylinder.getMaterial())
.withTransform()
.withMatrix(matrix);
}
else {
sceneBuilder.addCylinder()
.withShader(cylinder.getMaterial())
.withTransform()
.withScaleX(cylinder.getSize().getX())
.withScaleY(cylinder.getSize().getY())
.withScaleZ(cylinder.getSize().getZ())
.withTranslateX(cylinder.getPosition().getX())
.withTranslateY(cylinder.getPosition().getY())
.withTranslateZ(cylinder.getPosition().getZ())
.withRotateX(cylinder.getOrientation().getAlpha())
.withRotateY(cylinder.getOrientation().getBeta())
.withRotateZ(cylinder.getOrientation().getGamma());
}
}
else if (pSceneElement instanceof Box) {
Box box = (Box) pSceneElement;
if (useMatrix) {
sceneBuilder.addBox()
.withShader(box.getMaterial())
.withTransform()
.withMatrix(matrix);
}
else {
sceneBuilder.addBox()
.withShader(box.getMaterial())
.withTransform()
.withScaleX(box.getSize().getX())
.withScaleY(box.getSize().getY())
.withScaleZ(box.getSize().getZ())
.withTranslateX(box.getPosition().getX())
.withTranslateY(box.getPosition().getY())
.withTranslateZ(box.getPosition().getZ())
.withRotateX(box.getOrientation().getAlpha())
.withRotateY(box.getOrientation().getBeta())
.withRotateZ(box.getOrientation().getGamma());
}
}
else if (pSceneElement instanceof Mesh) {
Mesh mesh = (Mesh) pSceneElement;
if (useMatrix) {
sceneBuilder.addMesh()
.withShader(mesh.getMaterial())
.withMesh(mesh)
.withTransform()
.withMatrix(matrix);
}
else {
sceneBuilder.addMesh()
.withShader(mesh.getMaterial())
.withMesh(mesh)
.withTransform()
.withScaleX(mesh.getSize().getX())
.withScaleY(mesh.getSize().getY())
.withScaleZ(mesh.getSize().getZ())
.withTranslateX(mesh.getPosition().getX())
.withTranslateY(mesh.getPosition().getY())
.withTranslateZ(mesh.getPosition().getZ());
}
}
else if (pSceneElement instanceof PointLight) {
PointLight light = (PointLight) pSceneElement;
sceneBuilder.addLight()
.withType(LightType.POINT)
.withColor(light.getColor().getR(), light.getColor().getG(), light.getColor().getB())
.withP(light.getPosition().getX(), light.getPosition().getY(), light.getPosition().getZ())
.withPower(light.getIntensity() * 2000000.0);
}
else if (pSceneElement instanceof SkyLight) {
SkyLight light = (SkyLight) pSceneElement;
sceneBuilder.addSkyLight()
.withUp(light.getUp().getX(), light.getUp().getY(), light.getUp().getZ())
.withEast(light.getEast().getX(), light.getEast().getY(), light.getEast().getZ())
.withSundir(light.getSundir().getX(), light.getSundir().getY(), light.getSundir().getZ())
.withTurbidity(light.getTurbidity())
.withSamples(light.getSamples());
}
else if (pSceneElement instanceof Camera) {
Camera camera = (Camera) pSceneElement;
sceneBuilder
.openCamera()
.withType(CameraType.PINHOLE)
.withEye(camera.getEye().getX(), camera.getEye().getY(), camera.getEye().getZ())
.withTarget(camera.getTarget().getX(), camera.getTarget().getY(), camera.getTarget().getZ())
.withUp(camera.getUp().getX(), camera.getUp().getY(), camera.getUp().getZ())
.withFov(camera.getFov())
.withAspect(camera.getAspect());
}
else if (pSceneElement instanceof Scene || pSceneElement instanceof MaterialGroup) {
}
else {
System.out.println("Unknown positionable element " + pSceneElement);
}
}
private Matrix4 calcTransform(PositionableSceneElement pElement) {
Matrix4 transform = Matrix4.IDENTITY;
List<Matrix4> transforms = new ArrayList<Matrix4>();
PositionableSceneElement element = pElement;
while (element != null) {
transforms.add(Matrix4.scale(element.getSize().getX(), element.getSize().getY(), element.getSize().getZ()));
if (MathLib.fabs(element.getOrientation().getAlpha()) > MathLib.EPSILON) {
transforms.add(Matrix4.rotateX((float) Math.toRadians(element.getOrientation().getAlpha())));
}
if (MathLib.fabs(element.getOrientation().getBeta()) > MathLib.EPSILON) {
transforms.add(Matrix4.rotateY((float) Math.toRadians(element.getOrientation().getBeta())));
}
if (MathLib.fabs(element.getOrientation().getGamma()) > MathLib.EPSILON) {
transforms.add(Matrix4.rotateZ((float) Math.toRadians(element.getOrientation().getGamma())));
}
transforms.add(Matrix4.translation(element.getPosition().getX(), element.getPosition().getY(), element.getPosition().getZ()));
element = element.getParent();
}
for (int i = transforms.size() - 1; i >= 0; i--) {
transform = transform.multiply(transforms.get(i));
}
return transform;
}
@Override
public void visitAfter(SceneElement pSceneElement) {
// EMPTY
}
}