在 javafx 中绘制漫反射纹理?
Painting difuse texture in javafx?
有没有办法像 blender 那样在 3d 表面上绘制 3d 纹理?
在 3d 场景中绘制纹理
来自 mouseEvent 的 getPickResult().getIntersectedTexCoord()
将 return point2d 是一个 uv 坐标(从 0 到 1 )。为了将它映射到图像像素;我们必须将 u & v 乘以图像的高度和宽度(在本例中为 800)。一旦我们有了像素坐标,我们就可以使用 pixelWriter.setPixels()
方法进行绘制。 setPixel 中的第三个和第四个参数对应于用于绘制的矩形,在本例中是一个 12*12 的正方形。因此,需要一个长度为 144 的 argb 数组来用 colorpicker 结果给出的颜色值填充 setPixels
中的正方形。
ImageView 和 DifuseMap 共享相同的 WritableImage,这就是为什么绘制 Shape3d 也会更新 imageView 中的图像
这是一个您可以尝试的 class javafx 功能应用程序。你可以用鼠标右键旋转和左键绘画
public class App extends Application {
private boolean paintMode;
private boolean rotaionMode;
private double anchorX;
private final WritableImage writableImage = new WritableImage(800, 800);
private int[] colorArray;
private PixelWriter pixelWriter = writableImage.getPixelWriter();
@Override
public void start(Stage stage) {
// this loop will paint all writableImage object pixel with Color.WHEAT
for (int i = 0; i < 800; i++) {
for (int j = 0; j < 800; j++) {
pixelWriter.setColor(i, j, Color.WHEAT);
}
}
// giving a starting value to colorPicker
ColorPicker picker = new ColorPicker(Color.AQUAMARINE);
// giving initial valuest to colorArray
colorArray = getColorArray(picker.getValue());
picker.setOnAction(e -> colorArray = getColorArray(picker.getValue()));
PerspectiveCamera camera = new PerspectiveCamera(true);
camera.setTranslateZ(-30);
Shape3D sphere = new Sphere(6);
PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(writableImage);
material.setDiffuseColor(Color.CORAL);
sphere.setMaterial(material);
sphere.setOnMousePressed(e -> {
if (e.isSecondaryButtonDown()) {
anchorX = e.getSceneX();
}
rotaionMode = e.isSecondaryButtonDown();
paintMode = e.isPrimaryButtonDown();
});
sphere.setOnMouseDragged(e -> {
// painting if primary button is pressed
Point2D intersectedTexCoord = e.getPickResult().getIntersectedTexCoord();
if (paintMode && intersectedTexCoord != null) {
// uv cordinates to writableImage x y indices
int x = (int) (intersectedTexCoord.getX() * 800);
int y = (int) (intersectedTexCoord.getY() * 800);
// the rectangle of pixelWritter is 12*12 therefore an array 144 length of argb is needed
pixelWriter.setPixels(x, y, 12, 12, PixelFormat.getIntArgbInstance(), colorArray, 0, 0);
}
// rotate if secondary button is pressred
if (rotaionMode) {
sphere.setRotationAxis(Rotate.Y_AXIS);
sphere.setRotate(sphere.getRotate() + (e.getSceneX() - anchorX) * -0.05);
}
});
// writableImage in imageView and difuseMap
ImageView imageView = new ImageView(writableImage);
imageView.setFitHeight(300);
imageView.setFitWidth(300);
Group group = new Group(camera, sphere);
SubScene subScene = new SubScene(group, 300, 300, true, SceneAntialiasing.BALANCED);
subScene.setFill(Color.AQUAMARINE);
subScene.setCamera(camera);
HBox hBox = new HBox(picker, subScene, imageView);
hBox.setAlignment(Pos.CENTER);
hBox.setSpacing(30);
Scene scene = new Scene(hBox, 800, 600);
stage.setTitle("painting 3d texture");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
public int[] getColorArray(Color color) {
// get color values in doubles
double alphaD = color.getOpacity();
double redD = color.getRed();
double greenD = color.getGreen();
double blueD = color.getBlue();
// double to int
int alpha = (int) Math.round(255 * alphaD);
int red = (int) Math.round(255 * redD);
int green = (int) Math.round(255 * greenD);
int blue = (int) Math.round(255 * blueD);
// shifting int on hex
alpha = (alpha << 24) & 0xFF000000;
red = (red << 16) & 0x00FF0000;
green = (green << 8) & 0x0000FF00;
blue = blue & 0x000000FF;
// argb value
int argb = alpha | red | green | blue;
// the rectangle of pixelWritter is 12*12 therefore an array 144 length of argb is needed
int[] colors = new int[144];
for (int i = 0; i < colors.length; i++) {
colors[i] = argb;
}
return colors;
}
}
有没有办法像 blender 那样在 3d 表面上绘制 3d 纹理?
在 3d 场景中绘制纹理
getPickResult().getIntersectedTexCoord()
将 return point2d 是一个 uv 坐标(从 0 到 1 )。为了将它映射到图像像素;我们必须将 u & v 乘以图像的高度和宽度(在本例中为 800)。一旦我们有了像素坐标,我们就可以使用 pixelWriter.setPixels()
方法进行绘制。 setPixel 中的第三个和第四个参数对应于用于绘制的矩形,在本例中是一个 12*12 的正方形。因此,需要一个长度为 144 的 argb 数组来用 colorpicker 结果给出的颜色值填充 setPixels
中的正方形。
ImageView 和 DifuseMap 共享相同的 WritableImage,这就是为什么绘制 Shape3d 也会更新 imageView 中的图像
这是一个您可以尝试的 class javafx 功能应用程序。你可以用鼠标右键旋转和左键绘画
public class App extends Application {
private boolean paintMode;
private boolean rotaionMode;
private double anchorX;
private final WritableImage writableImage = new WritableImage(800, 800);
private int[] colorArray;
private PixelWriter pixelWriter = writableImage.getPixelWriter();
@Override
public void start(Stage stage) {
// this loop will paint all writableImage object pixel with Color.WHEAT
for (int i = 0; i < 800; i++) {
for (int j = 0; j < 800; j++) {
pixelWriter.setColor(i, j, Color.WHEAT);
}
}
// giving a starting value to colorPicker
ColorPicker picker = new ColorPicker(Color.AQUAMARINE);
// giving initial valuest to colorArray
colorArray = getColorArray(picker.getValue());
picker.setOnAction(e -> colorArray = getColorArray(picker.getValue()));
PerspectiveCamera camera = new PerspectiveCamera(true);
camera.setTranslateZ(-30);
Shape3D sphere = new Sphere(6);
PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(writableImage);
material.setDiffuseColor(Color.CORAL);
sphere.setMaterial(material);
sphere.setOnMousePressed(e -> {
if (e.isSecondaryButtonDown()) {
anchorX = e.getSceneX();
}
rotaionMode = e.isSecondaryButtonDown();
paintMode = e.isPrimaryButtonDown();
});
sphere.setOnMouseDragged(e -> {
// painting if primary button is pressed
Point2D intersectedTexCoord = e.getPickResult().getIntersectedTexCoord();
if (paintMode && intersectedTexCoord != null) {
// uv cordinates to writableImage x y indices
int x = (int) (intersectedTexCoord.getX() * 800);
int y = (int) (intersectedTexCoord.getY() * 800);
// the rectangle of pixelWritter is 12*12 therefore an array 144 length of argb is needed
pixelWriter.setPixels(x, y, 12, 12, PixelFormat.getIntArgbInstance(), colorArray, 0, 0);
}
// rotate if secondary button is pressred
if (rotaionMode) {
sphere.setRotationAxis(Rotate.Y_AXIS);
sphere.setRotate(sphere.getRotate() + (e.getSceneX() - anchorX) * -0.05);
}
});
// writableImage in imageView and difuseMap
ImageView imageView = new ImageView(writableImage);
imageView.setFitHeight(300);
imageView.setFitWidth(300);
Group group = new Group(camera, sphere);
SubScene subScene = new SubScene(group, 300, 300, true, SceneAntialiasing.BALANCED);
subScene.setFill(Color.AQUAMARINE);
subScene.setCamera(camera);
HBox hBox = new HBox(picker, subScene, imageView);
hBox.setAlignment(Pos.CENTER);
hBox.setSpacing(30);
Scene scene = new Scene(hBox, 800, 600);
stage.setTitle("painting 3d texture");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
public int[] getColorArray(Color color) {
// get color values in doubles
double alphaD = color.getOpacity();
double redD = color.getRed();
double greenD = color.getGreen();
double blueD = color.getBlue();
// double to int
int alpha = (int) Math.round(255 * alphaD);
int red = (int) Math.round(255 * redD);
int green = (int) Math.round(255 * greenD);
int blue = (int) Math.round(255 * blueD);
// shifting int on hex
alpha = (alpha << 24) & 0xFF000000;
red = (red << 16) & 0x00FF0000;
green = (green << 8) & 0x0000FF00;
blue = blue & 0x000000FF;
// argb value
int argb = alpha | red | green | blue;
// the rectangle of pixelWritter is 12*12 therefore an array 144 length of argb is needed
int[] colors = new int[144];
for (int i = 0; i < colors.length; i++) {
colors[i] = argb;
}
return colors;
}
}