在 3D 场景中绘制纹理
getPickResult().getIntersectedTexCoord()from mouseEvent 将返回一个 point2d ,它是一个 uv 坐标(从 0 到 1 )。为了将其映射到图像像素;我们必须将 u 和 v 乘以图像的高度和宽度(在本例中为 800)。一旦我们有了像素坐标,我们就可以使用 pixelWriter.setPixels() 方法进行绘制。setPixel 中的第三个和第四个参数对应于用于绘制的矩形,在本例中是一个 12*12 的正方形。因此,需要一个长度为 144 的 argb 数组来setPixels用颜色选择器结果给出的颜色值填充正方形。ImageView 和 DifuseMap 共享相同的 WritableImage,这就是为什么绘制 Shape3d 也会更新 imageView 中的图像
这是一个单类 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;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
219 次 |
| 最近记录: |