Применить градиент к объекту сферы с помощью JavaFX

Я работаю в JavaFX для класса, и я пытаюсь применить градиент к сфере, но (очевидно), я не могу понять, как это сделать. Я застрял, потому что я знаю, что сфера - это объект, и поэтому он должен иметь материал, но (что касается цветов), PhongMaterial принимает только один цвет, и поэтому он не будет принимать градиент, потому что градиент - это диапазон цветов. Итак, в основном я пытаюсь сделать следующее:

    Sphere sphere = new Sphere(50);
    RadialGradient rg = new RadialGradient(0, 0, 0, 0, 5, true, CycleMethod.REPEAT, /*arbitrary/irrelevant color Stop objects*/));
    PhongMaterial pm = new PhongMaterial();
    pm.setDiffuseMap(pm);
    sphere.setMaterial(asdf);

Теперь, очевидно, этот код не работает, но я думаю, что это идея / поток того, что я пытаюсь сделать.

1 ответ

Решение

Вы правы в одном, PhongMaterial занимает Color как диффузный цвет, и это не позволяет Gradient, Для этого следует принять Paint, Но это не тот случай.

Поэтому мы должны искать разные альтернативы.

DiffuseMap

Если вы проверите PhongMaterialВы можете установить диффузную карту с изображением. Это означает, что вы можете использовать существующее изображение с некоторым градиентом и применить его к сфере.

Что-то вроде этого:

Sphere sphere = new Sphere(100);
PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(new Image("http://westciv.com/images/wdblogs/radialgradients/simpleclorstops.png"));
sphere.setMaterial(material);

даст следующий результат:

Динамическая Диффузная Карта

Очевидно, что это имеет недостаток в зависимости от статического изображения. Что если вы хотите изменить это динамически?

Вы можете сделать это, если вы сгенерируете свой радиальный градиент, визуализируете его на вторичной сцене и сделаете его снимок. Этот снимок возвращает WritableImage что вы можете использовать непосредственно в качестве диффузной карты.

Что-то вроде этого:

Scene aux = new Scene(new StackPane(), 100, 100, 
        new RadialGradient(0, 0, 0.5, 0.5, 1, true, CycleMethod.REPEAT, 
                new Stop(0, Color.GREEN), new Stop(0.4, Color.YELLOW), 
                new Stop(0.6, Color.BLUE), new Stop(0.7, Color.RED)));
WritableImage snapshot = aux.snapshot(null);

Sphere sphere = new Sphere(100);
PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(snapshot);
sphere.setMaterial(material);

Теперь у вас будет:

Карта плотности

Есть еще один вариант использования математической функции для создания карты плотности, и цвета будут заданы отображением этой функции.

Для этого вы не можете использовать встроенный Sphere, но вы должны либо создать свой собственный TriangleMesh и поиграйте с текстурными координатами, или вы можете просто использовать FXyz, библиотеку JavaFX 3D с открытым исходным кодом с множеством различных примитивов и параметров текстуры.

Для этого случая вы можете получить библиотеку из Maven Central (org.fxyz3d:fxyz3d:0.3.0), использовать SegmentedSphereMesh управления, а затем выберите режим текстуры `Vertices3D:

SegmentedSphereMesh sphere = new SegmentedSphereMesh(100);
sphere.setTextureModeVertices3D(1530, p -> p.z);

Обратите внимание, что функция в этом случае просто основана на z координаты, но, очевидно, вы можете изменить это при необходимости.

Проверьте библиотеку (есть сэмплер), чтобы изучить другие варианты.

Другие вопросы по тегам