/**
* GroupOfTexturedMeshSample.java
*
* Copyright (c) 2013-2016, F(X)yz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of F(X)yz, any associated website, nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL F(X)yz BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.fxyz3d.samples.shapes;
import java.util.function.Function;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.Group;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import org.fxyz3d.controls.TextureImage;
import org.fxyz3d.geometry.Point3D;
import org.fxyz3d.scene.paint.Patterns;
import org.fxyz3d.scene.paint.Patterns.CarbonPatterns;
import org.fxyz3d.shapes.primitives.TexturedMesh;
import org.fxyz3d.shapes.primitives.helper.TriangleMeshHelper;
import org.fxyz3d.shapes.primitives.helper.TriangleMeshHelper.TextureType;
import org.fxyz3d.tools.NormalMap;
/**
*
* @author Jason Pollastrini aka jdub1581
*/
public abstract class GroupOfTexturedMeshSample extends ShapeBaseSample<Group>{
public GroupOfTexturedMeshSample(){
sectionType.addListener((obs,s0,s1)->{
if (model != null) {
model.getChildren().stream().filter(TexturedMesh.class::isInstance)
.map(TexturedMesh.class::cast)
.forEach(s->s.setSectionType(sectionType.getValue()));
}
});
textureType.addListener((obs,t0,t1)->{
if (model != null) {
model.getChildren().stream().filter(TexturedMesh.class::isInstance)
.map(TexturedMesh.class::cast)
.forEach(s->{
switch(t1){
case NONE:
s.setTextureModeNone(colorBinding.get());
break;
case IMAGE:
s.setTextureModeImage(textureImage.getValue()==null?null:textureImage.getValue().getSource());
break;
case PATTERN:
s.setTextureModePattern(patterns.get(), pattScale.getValue());
break;
case COLORED_VERTICES_1D:
s.setTextureModeVertices1D(1540, func.getValue());
break;
case COLORED_VERTICES_3D:
s.setTextureModeVertices3D(1600, dens.getValue());
break;
case COLORED_FACES:
s.setTextureModeFaces(1550);
break;
}
});
}
});
colorBinding.addListener((obs,c0,c1)->{
if (model != null){
model.getChildren().stream().filter(TexturedMesh.class::isInstance)
.map(TexturedMesh.class::cast)
.filter(s->s.getTextureType().equals(TextureType.NONE))
.forEach(s->s.setDiffuseColor(c1));
}
});
pattScale.addListener((obs,p0,p1)->{
if (model != null){
model.getChildren().stream().filter(TexturedMesh.class::isInstance)
.map(TexturedMesh.class::cast)
.filter(s->s.getTextureType().equals(TextureType.PATTERN))
.forEach(s->s.setPatternScale(p1.doubleValue()));
}
});
patterns.addListener((obs,c0,c1)->{
if (model != null){
model.getChildren().stream().filter(TexturedMesh.class::isInstance)
.map(TexturedMesh.class::cast)
.filter(s->s.getTextureType().equals(TextureType.PATTERN))
.forEach(s->{
s.setCarbonPattern(c1);
((PhongMaterial)s.getMaterial()).setSpecularColor(specColorBinding.get());
((PhongMaterial)s.getMaterial()).setSpecularPower(specularPower.doubleValue());
if (useBumpMap.get()) {
((PhongMaterial)s.getMaterial()).setBumpMap(new NormalMap(
bumpScale.doubleValue(), bumpFineScale.doubleValue(),
invert.getValue(), ((PhongMaterial) s.getMaterial()).getDiffuseMap()
));
}
});
}
});
dens.addListener((obs,f0,f1)->{
if (model != null){
model.getChildren().stream().filter(TexturedMesh.class::isInstance)
.map(TexturedMesh.class::cast)
.filter(s->s.getTextureType().equals(TextureType.COLORED_VERTICES_3D))
.forEach(s->s.setDensity(f1));
}
});
func.addListener((obs,f0,f1)->{
if (model != null){
model.getChildren().stream().filter(TexturedMesh.class::isInstance)
.map(TexturedMesh.class::cast)
.filter(s->s.getTextureType().equals(TextureType.COLORED_VERTICES_1D))
.forEach(s->s.setFunction(f1));
}
});
textureImage.addListener((obs,f0,f1)->{
if (model != null){
model.getChildren().stream().filter(TexturedMesh.class::isInstance)
.map(TexturedMesh.class::cast)
.filter(s->s.getTextureType().equals(TextureType.IMAGE))
.forEach(s->{
s.setTextureModeImage(textureImage.getValue().getSource());
if (useBumpMap.getValue() || invert.getValue()) {
useBumpMap.setValue(false);
invert.setValue(false);
}
});
}
});
invert.addListener((obs,b,b1)->updateGroupMaterial());
bumpScale.addListener((obs,b,b1)->updateGroupMaterial());
bumpFineScale.addListener((obs,b,b1)->updateGroupMaterial());
useBumpMap.addListener((obs,b,b1)->{
if (b1) {
updateGroupMaterial();
} else {
if (model != null) {
model.getChildren().stream().filter(TexturedMesh.class::isInstance)
.map(TexturedMesh.class::cast)
.forEach(s->((PhongMaterial)s.getMaterial()).setBumpMap(null));
}
}
});
specularPower.addListener((obs,n,n1)->{
if (model != null) {
model.getChildren().stream().filter(TexturedMesh.class::isInstance)
.map(TexturedMesh.class::cast)
.forEach(s->{
((PhongMaterial)s.getMaterial()).setSpecularPower(n1.doubleValue());
});
}
});
specColorBinding.addListener((obs,c,c1)->{
if (model != null) {
model.getChildren().stream().filter(TexturedMesh.class::isInstance)
.map(TexturedMesh.class::cast)
.forEach(s->{
((PhongMaterial)s.getMaterial()).setSpecularColor(c1);
});
}
});
}
//specific
protected final Property<TriangleMeshHelper.SectionType> sectionType = new SimpleObjectProperty<TriangleMeshHelper.SectionType>(model, "secType", TriangleMeshHelper.SectionType.CIRCLE) {};
protected final Property<TriangleMeshHelper.TextureType> textureType = new SimpleObjectProperty<TriangleMeshHelper.TextureType>(model, "texType", TriangleMeshHelper.TextureType.NONE) {};
protected final ObjectProperty<Color> colorBinding = new SimpleObjectProperty<Color>(Color.BROWN){};
protected final IntegerProperty colors = new SimpleIntegerProperty(model, "Color :", 700) {
@Override
protected void invalidated() {
super.invalidated();
if (model != null) {
colorBinding.set(Color.hsb(360 * (1d - get() / 1530d), 1, 1));
}
}
};
/*
TriangleMeshHelper.TextureType.IMAGE
*/
protected final Property<TextureImage> textureImage = new SimpleObjectProperty(this, "Texture");
/*
TriangleMeshHelper.TextureType.PATTERN
*/
protected final DoubleProperty pattScale = new SimpleDoubleProperty(this, "Pattern Scale: ", 2.0d) {};
protected final ObjectProperty<CarbonPatterns> patterns = new SimpleObjectProperty<CarbonPatterns>(Patterns.CarbonPatterns.DARK_CARBON){};
private void updateGroupMaterial(){
if (model != null) {
model.getChildren().stream().filter(TexturedMesh.class::isInstance)
.map(TexturedMesh.class::cast)
.filter(s->((PhongMaterial)s.getMaterial()).getDiffuseMap()!=null)
.forEach(s->{
((PhongMaterial)s.getMaterial()).setBumpMap(
new NormalMap(bumpScale.doubleValue(), bumpFineScale.doubleValue(),
invert.getValue(), ((PhongMaterial)s.getMaterial()).getDiffuseMap()));
});
}
}
protected final Property<Boolean> invert = new SimpleBooleanProperty(this, "Invert Bump Map", false);
protected final DoubleProperty bumpScale = new SimpleDoubleProperty(this, "Bump Scale", 27d);
protected final ObjectProperty<Image> bumpMap = new SimpleObjectProperty<>(this, "bumpMap", null);
protected final DoubleProperty bumpFineScale = new SimpleDoubleProperty(this, "Bump Fine Scale", 9d);
protected final BooleanProperty useBumpMap = new SimpleBooleanProperty(this, "Generate Bump Map", false);
protected final DoubleProperty specularPower = new SimpleDoubleProperty(this, "Specular Power");
protected final ObjectProperty<Color> specColorBinding = new SimpleObjectProperty<>(Color.BLACK);
protected final IntegerProperty specColor = new SimpleIntegerProperty(this, "Specular Color", 1) {
@Override
protected void invalidated() {
super.invalidated();
if (model != null) {
specColorBinding.set(Color.hsb(360 * (1d - get() / 1530d), 1, 1));
}
}
};
/*
TriangleMeshHelper.TextureType.COLORED_VERTICES_3D
*/
protected final DoubleProperty densMax = new SimpleDoubleProperty(this, "Density Scale: ");
protected final Property<Function<Point3D,Number>> dens = new SimpleObjectProperty<Function<Point3D,Number>>(p -> p.x * p.y * p.z) {};
/*
TriangleMeshHelper.TextureType.COLORED_VERTICES_1D
*/
protected final Property<Function<Number,Number>> func = new SimpleObjectProperty<Function<Number,Number>>(t->t) {};
}